Introduction to Webadmin Plugins

Webadmin Plugins

This is an explanation of the Webadmin Plugin system
A few examples will be provided in Lua.

What is Webadmin?


Webadmin is a resource that comes with FXServer by default.
It’s a web interface that allows you to control resources, see online players and do other server administration.

Webadmin is enabled by default and can be accessed by going to your server’s address in a browser.
For example on a local server: http://localhost:30120/ (or http://localhost:30120/webadmin/)

How do plugins work?

Webadmin provides a few exported functions that allow you to add elements to the interface.
You can add elements to the front page, add custom pages and add to a few other key locations.
There are also ways to make sure the person is logged in and has proper access rights via ACE permissions.

Adding a new page

You can add a new page to the interface with the webadmin export registerPluginPage(name, function).
You need to pass a name and a function to this export.
The name is the navigational target of the page, think of it as a page ID. No two pages can have the same name.
The function is a function that returns the contents of the page in raw HTML.

An example use of this export would be:

exports['webadmin']:registerPluginPage("demo", function()
    return "<h1>Hello World</h1>"
end)

Running this script would yield the following page:

How to access the page will be shown in the next part

Adding to the sidebar menu

The sidebar menu usually contains buttons to navigate between different pages.
This is where you want to add a button to navigate to your custom page.

You can add elements to the sidebar menu using the webadmin export registerPluginOutlet(outlet, function).
There are multiple outlets to choose from, but the one we are going to use is nav/sideList.
Just as for the registerPluginPage export, we also need a function to return the contents with.

Thanks to Webadmin utilizing CoreUI, there are pre-made styles for the sidebar elements.
We want to add a list element (li) that contains an anchor element (a) with an icon and some text.
Some basic HTML layout for this is:

<li class="nav-item">
    <a class="nav-link" href="/webadmin/">
        <i class="nav-icon fa fa-home"></i> Home
    </a>
</li>

(The built-in home button on the interface)

We also want to add a link to our own custom page.
Here is where the next webadmin export, getPluginUrl(name), comes into play.
This export creates a link to a custom page by the given name.
By passing the same name you used in registerPluginPage for your page, it will give a direct link to that page.

We can now create some mixed HTML and Lua code to produce the button:

exports['webadmin']:registerPluginOutlet("nav/sideList", function()
    local url = exports['webadmin']:getPluginUrl("demo")
    return [[
        <li class="nav-item">
            <a class="nav-link" href="]] .. url .. [[">
                <i class="nav-icon fa fa-dragon"></i> Demo Page
            </a>
        </li>
    ]]
end)

Note that we replaced fa-home with fa-dragon and Home with Demo Page
The fa-home and fa-dragon is from Font Awesome, a library of pre-made icons you can use.
The text is what appears on the sidebar entry, and should represent your page together with the icon.

By using the code we’ve created so far, you should see this:

You can now click on the new button to access your custom page.

Plugin outlets

There are a few plugin outlets in different locations on the default Webadmin interface.
Here’s some key outlets:

nav/sideList

As we just showed, nav/sideList appears in the navigational sidebar

nav/topList

The nav/topList outlet appears on the top of the interface. Together with the Home button.

exports['webadmin']:registerPluginOutlet("nav/topList", function()
    return "I'm on-top of the world!"
end)


(highlighted in red)

home/dashboardTop

The home/dashboardTop appears on the front / home page of the interface. This can be used to show general or important information.

exports['webadmin']:registerPluginOutlet("home/dashboardTop", function()
    return "<h2>I am some very important information</h2>"
end)


(highlighted in red)

Authentication and preventing access

In some cases you might not want everyone to see or access something, thankfully there are built-in features to prevent this.
You can use the webadmin export isInRole(role) to see if the logged in user has a certain ACE permission.

Note that all custom pages require the user to be logged in regardless!

Passing data from page to code

The registerPluginOutlet(outlet, function)'s function has an additional parameter that contains current parameters from the URL.
Using this, you can pass data from the page into code.

exports['webadmin']:registerPluginPage("demo", function(data)
    return json.encode(data)
end)

Will show us the data passed to the page.
By default this only contains the page name, so it will show {"name":["demo"]}.

We can add a form to the page that sends text input as a parameter to the page.

exports['webadmin']:registerPluginPage("demo", function(data)
    if data.text then
        return "<h1>" .. data.text[1] .. "</h1>"
    end
    local url = exports['webadmin']:getPluginUrl("demo")
    return [[
        <form action="]] .. url .. [[" method="get">
            <input type="hidden" name="name" value="demo">
            <input type="text" name="text" class="form-control"  placeholder = "Text Input">
            <input type="submit" value="Show Text">
        </form>
    ]]
end)

In this example we show a text input by default:

If we input some text and click the “Show Text” button, the page changes to this:

Note that we also have to add the name parameter into the form, as the form strips that away from the URL automatically.
This could easily be achieved by adding a hidden input field with the name name and the value demo (or what you named your page)

The data returned may appear to be formatted oddly, this is because you can pass multiple of the same parameter. In our case we only pass one entry for text and thus we use the first text entry.

End

This has covered some basics of the plugin system.
With only four covered exports, we already have the ability to create incredible plugins!

The plugin system is still in a very early stage, so changes are very likely to occur.

Creating raw HTML output isn’t an easy task, so it is recommended to make helper functions to more easily generate elements!
I’ve created one such helper library and would very much appreciate community feedback and contributons! You can find more info on that system here:

Thank you to the FiveM developers for creating Webadmin, and for adding a plugin system to it.

8 Likes

This is quality content. You’ve done a really good job!

3 Likes

Couldn’t agree with Zeemah any more! Amazing work, really glad you made this tutorial :grin:

2 Likes