Zum Inhalt springen

DACore · coming December 2026

How the DACore admin template and menu work

DACore ships a free admin template: sidebar, top bar, language switch, notification dropdown, optional embedded AI chat, error pages, and a login layout. You do not build a second HTML shell. Every operator page is a fragment passed to DACore:Page@withMenu!. The sidebar is not a hardcoded PHP array in your module. It is a table. You register rows once in Installation.php, operators can reorder siblings, and visibility follows JSON rights on each item.

Common mistakes

Wrong Right
Return a full HTML document from your controller. Return a body fragment (cards, tables, forms) and wrap with Page@withMenu!.
Register menu rows on every request in initialize(). Register in the installer. Repeat registrations on each page load write to MySQL for nothing.
INSERT into dacore_menu. DotApp::call('DACore:Menu@register', $menuid, $data).
Steal another module’s menuid prefix, then uninstall with LIKE 'Host.%'. Your ids start with your module name. Uninstall only your prefix.
Dump ten leaf links under one header. Ask whether you need a shared sidebar or a module-own branch ($menuId). Group with type => 2.
Restyle the admin by editing DACore CSS. Add {modulename}_* classes in your module assets. DACore updates wipe shell patches.

Page@withMenu

The callable returns the complete admin HTML string: left menu from the model, navbar title, user menu, optional AI chat when the profile allows it. You pass extra CSS and JS URL arrays for that page only. Hooks Dacore:Page@withMenu.rendering and .rendered exist if you must wrap output without forking Page.php.

return DotApp::call(
    'DACore:Page@withMenu!',
    Translator::trans('Orders'),
    $html,
    [],
    ['/assets/modules/Shop/css/orders.css'],
    ['/assets/modules/Shop/js/orders.js'],
    ''
);

The last argument is an optional menu branch id. Pass it when the module should show a focused tree plus a “return back” item instead of the full company sidebar. AIRULES-DACORE tells agents to ask shared vs module-own before scaffolding. Do not guess.

Menu@register

Stable menuid, max 50 characters, namespaced Shop.orders.list. Upsert by that id. Cache for the menu (when enabled) is cleared on register.

DotApp::call('DACore:Menu@register', 'Shop.orders.list', [
    'parent' => 'Shop.orders',
    'icon' => 'ri ri-shopping-cart-line',
    'name' => 'Orders',
    'url' => '/orders',
    'urlprefix' => 1,
    'type' => 1,
    'ordering' => 10,
    'rights' => json_encode(['dotapp.root', 'Shop.orders.view']),
]);

urlprefix = 1 prepends Config::module('DACore', 'prefixUrl'). Types: 0 section header, 1 leaf, 2 parent with children. Rights JSON: * any logged-in user, Shop.* prefix match, otherwise OR of listed permissions. Labels go through Translator::trans — put the same strings in your module locale files.

Ordering in the UI

Operators with DACore.admin.menu open menu ordering and drag siblings under the same parent. Encrypted ids in the UI follow the same identifier discipline as the rest of DotApp. Your installer should set a sensible initial ordering. Do not fight the operator on every update: the register API preserves operator order on later upserts for that concern.

Notifications

Modules push with DACore:Notifications@push on the event — not from the installer, not on every request. Topics such as operations, security, system, account; severities info through danger; optional dedupe key, icon, title, body, URL. The navbar shows recent items; a full inbox supports filters and mark-read. That is how a warehouse module tells the night operator that import failed without inventing a mailer.

Languages

DACore ships locale JSON (Slovak, Czech, German, Russian, Ukrainian, plus English as the default surface). Login and the navbar can switch language. A profile can pin a UI language. Your module adds translations/sk_sk.json (and friends) and loads them in init/module.init.php. User-visible strings must read as product copy. AIRULES forbids prompt-echo labels.

FAQ

Can I use jQuery widgets in the admin?

Widgets may sit beside the page. Every request still goes through $dotapp() (form / load / bridge). Do not $.ajax to PHP. Porting a jQuery plugin means a new $dotapp().fn library — ask first.

What about preloaders?

DACore admin prefers Notiflix. Public websites must build their own overlay. Deletes open a graphical confirm, never alert().

Should I register a “Return back” menu row?

No. The shell adds it when you pass $menuId. Registering your own duplicate confuses uninstall.

See also