Appearance
EA Script API Reference
All methods below are available inside your script.js plugin registration function via this.
js
plugins["my-plugin"] = function () {
// this.addLanguage(...)
// this.addRole(...)
// etc.
}addLanguage(code, key, value)
Registers i18n translation strings for your plugin. Will not overwrite a namespace that is already registered.
| Parameter | Type | Description |
|---|---|---|
code | "ar" | "en" | Locale code |
key | string | Namespace (e.g. "music", "form") |
value | object | Key/value translation pairs |
js
this.addLanguage("en", "music", {
name: "Music",
playlist: "Playlist"
});
this.addLanguage("ar", "music", {
name: "الموسيقى",
playlist: "قائمة التشغيل"
});In Vue templates, use translations with $t("namespace.key"):
vue
<h5>{{ $t("music.name") }}</h5>addRole(role)
Registers a permission role for your plugin. Roles control access to actions (create, save, delete, etc.) and are configurable by administrators.
| Parameter | Type | Description |
|---|---|---|
role.id | string | Unique role identifier |
role.text | string | Display name |
role.key | string | i18n key for the role label |
role.roles | object | Map of permission keys to permission definitions |
Each permission inside role.roles:
| Property | Type | Description |
|---|---|---|
text | string | Display name |
key | string | i18n key |
value | boolean | Default value (false = denied by default) |
js
this.addRole({
id: "music",
text: "Music",
key: "music.name",
roles: {
create: { text: "Create", key: "button.create", value: false },
save: { text: "Save", key: "button.save", value: false },
delete: { text: "Delete", key: "button.delete", value: false }
}
});In Vue components, check permissions with the role() helper:
vue
<Button v-if="role('music', 'delete')" icon="pi pi-trash" />addWidget(item)
Mounts a Vue component onto the EA dashboard as a widget tile. This is what you use for the standard widget.vue file — it shows up in the draggable widget grid on the home dashboard, and users can resize/remove it in dashboard edit mode.
| Parameter | Type | Description |
|---|---|---|
item.name | string | Unique component route name |
item.id | string | Widget identifier |
item.file | string[] | File path array passed to loadModule |
js
this.addWidget({
name: "/[music]widget.vue",
id: "init-music",
file: ["music", "widget.vue"]
});The
filearray resolves relative to the plugin's version folder.["music", "widget.vue"]loads1.0.0/widget.vuefrom themusicplugin.
addTask(item)
Registers a background task component, shown in the app's task panel — a different UI surface from the dashboard widget grid. Use this for long-running or status-style components rather than the main widget tile.
| Parameter | Type | Description |
|---|---|---|
item.name | string | Unique component name |
item.id | string | Task identifier |
item.file | string[] | File path array passed to loadModule |
js
this.addTask({
name: "/[music]sync-task.vue",
id: "init-music-sync",
file: ["music", "sync-task.vue"]
});addToSetting(route)
Adds a navigation entry to the Settings sidebar in the EA application.
| Parameter | Type | Description |
|---|---|---|
route.label | string | Sidebar display label |
route.key | string | i18n key for the label |
route.icon | string | Icon class (MDI or PrimeIcons) |
route.to | string | Route path this item navigates to |
js
this.addToSetting({
label: "Music",
key: "music.name",
icon: "mdi mdi-book-music",
to: "/app/setting/music"
});The
topath must match thepathyou register withaddPage(..., "setting").
addToToolbar(route)
Adds a button or link to the application toolbar.
| Parameter | Type | Description |
|---|---|---|
route | object | Route config pushed to the toolbar array |
js
this.addToToolbar({
icon: "pi pi-music",
to: "/app/music"
});addToDashboard(cat, item)
Adds one navigation item inside an existing dashboard category — internally it does navigation[cat].items[item.to] = item and app.adminRoute[cat].push(item.to), so cat must already exist in both, or this throws.
| Parameter | Type | Description |
|---|---|---|
cat | string | Category key — see the built-in list below, or a category name a plugin already created via addToDashboardRoot |
item.to | string | Route path — also used as the item's key in navigation[cat].items |
item.label | string | Display label |
item.key | string | i18n key for the label |
item.icon | string | Icon class (MDI or PrimeIcons) |
item.items | array? | Optional sub-menu items (each {label, key, icon, to}), for a flyout under this entry |
js
this.addToDashboard("System", {
label: "Music",
key: "music.name",
icon: "mdi mdi-book-music",
to: "/app/music"
});Built-in category keys
These are always present (defined in app/src/router/navigation.js), so they're safe to target from any plugin regardless of load order:
cat | Sidebar label | Existing items |
|---|---|---|
Home | Home | Dashboard, Tasks |
Explorer | Explorer | File Explorer, Shortcut |
Users | Users | Users, Roles, Sessions |
System | System | Store, Profile, License, Setting |
About | About | Contact, Info, Website |
You can also target a category a plugin created earlier via addToDashboardRoot (e.g. "cashir") — but that only works if that plugin has already run, so prefer creating your own root category with addToDashboardRoot unless you specifically mean to extend a category owned by another known plugin.
addToDashboardRoot(cat, item, routes)
Creates (or replaces) a root-level sidebar category — a top-level entry in the main navigation, with its own set of menu items, sitting alongside the built-in categories (Home, Explorer, Users, System, About). Use addToDashboard instead if you just want to add one item into an existing category.
| Parameter | Type | Description |
|---|---|---|
cat | string | Category key. Becomes the key under both navigation (sidebar) and app.adminRoute (route access) — must be unique |
item.label | string | Category display label |
item.key | string | i18n key for the label |
item.order | number? | Optional position among the other sidebar categories (see below) |
item.items | object | Menu entries for this category, keyed by route path. Each entry is { label, key, icon, to }, and can itself have a nested items: [] array for a sub-menu (see suppliers below) |
routes | string[] | Route path prefixes this category owns, used for role-based access (see below) |
item.items is required if you want the category to actually show any menu entries — it becomes navigation[cat].items, the same shape addToDashboard and addToSetting read from. Skipping it (as a bare {label, icon, order}) creates an empty category.
order controls where the category sits in the sidebar. If you pass it, both navigation and app.adminRoute are re-keyed so the category lands at that index and everything else shifts — keeping sidebar order and role/route data in sync. If you omit it, the category is just appended (or, if cat already exists, replaced in place without moving it).
routes feeds app.adminRoute[cat], which the router's role guard (checkRouter) uses to decide whether a non-admin user may open a given path — it checks path.startsWith(...) against every entry. In practice you only need to list each top-level page path once; nested sub-pages (like suppliers/add below) are already covered because they start with an already-listed prefix (suppliers).
Real example, trimmed from the bundled cashir plugin (plugins/cashir/script.js):
js
this.addToDashboardRoot(
"cashir",
{
label: "Cashir",
key: "cashir.name",
order: 2,
items: {
"/app/cashir/addBill": {
to: "/app/cashir/addBill",
label: "Add Bill",
key: "cashir.bills",
icon: "mdi mdi-receipt-text-outline"
},
"/app/cashir/suppliers": {
label: "Suppliers",
key: "cashir.suppliers",
icon: "mdi mdi-account-hard-hat-outline",
// Sub-menu under "Suppliers" — note this is an array, unlike the outer `items` map
items: [
{ label: "List", key: "menu.list", icon: "mdi mdi-format-list-group", to: "/app/cashir/suppliers" },
{ label: "Add", key: "menu.add", icon: "mdi mdi-plus", to: "/app/cashir/suppliers/add" }
]
},
"/app/cashir/setting": {
key: "menu.setting",
label: "setting",
icon: "pi pi-fw pi-cog",
to: "/app/cashir/setting"
}
}
},
// routes: one prefix per top-level item above — "/app/cashir/suppliers/add" is
// covered automatically since it starts with the already-listed "/app/cashir/suppliers"
["/app/cashir/addBill", "/app/cashir/suppliers", "/app/cashir/setting"]
);
addRole()is separate from this —routes/app.adminRoutegates which pages a role can open, whileaddRole()gates individual actions (create/save/delete) inside those pages.
addToExplorer(data)
Registers your plugin with the application explorer, making it discoverable as an installed application.
| Parameter | Type | Description |
|---|---|---|
data.id | string | Unique key in the application registry |
data | object | Full application descriptor |
js
this.addToExplorer({
id: "music",
label: "Music",
icon: "mdi mdi-book-music"
});addPage(page, to)
Registers a Vue component as a routed page inside the EA application.
| Parameter | Type | Description |
|---|---|---|
page.name | string | Unique route name |
page.path | string | Route path |
page.file | string[] | File path array passed to loadModule |
to | string | Parent route name. Defaults to "app". Use "setting" for settings pages |
If a route with page.name already exists, the registration is skipped silently.
js
// Register a settings page
this.addPage({
name: "/[music]setting.vue",
path: "/app/setting/music",
file: ["music", "setting.vue"]
}, "setting");
// Register a main app page
this.addPage({
name: "/[music]index.vue",
path: "/app/music",
file: ["music", "index.vue"]
}, "app");Typical plugin registration pattern
js
plugins["music"] = function () {
// 1. Register translations
this.addLanguage("en", "music", { name: "Music", playlist: "Playlist" });
this.addLanguage("ar", "music", { name: "الموسيقى", playlist: "قائمة التشغيل" });
// 2. Register roles
this.addRole({
id: "music",
text: "Music",
key: "music.name",
roles: {
create: { text: "Create", key: "button.create", value: false },
save: { text: "Save", key: "button.save", value: false },
delete: { text: "Delete", key: "button.delete", value: false }
}
});
// 3. Mount dashboard widget
this.addWidget({
name: "/[music]widget.vue",
id: "init-music",
file: ["music", "widget.vue"]
});
// 4. Add Settings sidebar entry
this.addToSetting({
label: "Music",
key: "music.name",
icon: "mdi mdi-book-music",
to: "/app/setting/music"
});
// 5. Register settings page route
this.addPage({
name: "/[music]setting.vue",
path: "/app/setting/music",
file: ["music", "setting.vue"]
}, "setting");
}