mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-04-16 01:34:08 +00:00
Adds the read-only company "Active Modules" index page (lists every
instance-activated module with a Settings shortcut) and the schema-driven
settings framework (generic BaseSchemaForm.vue renderer + per-company
persistence in CompanySetting). Bundled because they share the same
routes/api.php edit and the index page's Settings button targets the
settings page.
Backend:
- CompanyModulesController::index() returns every Module::enabled = true row
with a kebab-case slug (via Str::kebab()) and a has_settings flag computed
from \InvoiceShelf\Modules\Registry::settingsFor(). nwidart stores module
names in PascalCase ("HelloWorld") but URLs and registry keys use kebab
("hello-world") — the controller normalizes so module authors can call
Registry::registerSettings('hello-world') naturally without thinking
about the storage format.
- ModuleSettingsController::show(\$slug) returns the registered Schema +
per-company values from CompanySetting (defaults flow through when nothing
has been saved yet). update(\$slug) builds Laravel validator rules from
the Schema's per-field rules arrays — with type-rule fallbacks for
switch -> boolean, number -> numeric, multiselect -> array — silently
drops unknown keys, and persists via CompanySetting::setSettings() under
the module.{slug}.{key} prefix. Activation is instance-global, but
settings are per-company: two companies on the same instance can
configure the same activated module differently.
- routes/api.php mounts GET /api/v1/company-modules at the root of the
company API group and GET/PUT /api/v1/modules/{slug}/settings inside the
existing modules prefix.
Frontend:
- BaseSchemaForm.vue is the central new component — a generic schema-driven
form renderer that maps schema fields to BaseInput / BaseTextarea /
BaseSwitch / BaseMultiselect by type, and builds Vuelidate rules
dynamically from each field's rules array (supports required, email, url,
numeric, min:N, max:N). New fields are added by extending the type ->
component map.
- CompanyModulesIndexView.vue fetches /company-modules and renders a card
grid (with empty/loading states); CompanyModuleCard.vue is the per-row
component with the Settings button. ModuleSettingsView.vue fetches
/modules/{slug}/settings, hands {schema, values} to BaseSchemaForm, and
posts back on submit.
- Company-context routes.ts is rebuilt after the previous commit relocated
the marketplace browser away. It now declares modules.index +
modules.settings, both gated by manage-module ability.
- New api/services/{companyModules,moduleSettings}.service.ts thin clients.
- lang/en.json adds modules.index.{description,empty_title,empty_description},
modules.settings.{title,open,saved,not_found,none}, and
modules.sidebar.section_title. The sidebar key is added here even though
the dynamic sidebar rendering lands in the next commit — keeping all i18n
additions in one file edit avoids hunk-splitting lang/en.json.
40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
import type { RouteRecordRaw } from 'vue-router'
|
|
|
|
const CompanyModulesIndexView = () => import('./views/CompanyModulesIndexView.vue')
|
|
const ModuleSettingsView = () => import('./views/ModuleSettingsView.vue')
|
|
|
|
/**
|
|
* Company-context module routes.
|
|
*
|
|
* - `/admin/modules` — read-only Active Modules index, lists every module the
|
|
* super admin has activated on this instance with a "Settings" link.
|
|
* - `/admin/modules/:slug/settings` — schema-rendered settings form for a
|
|
* specific active module, backed by the InvoiceShelf\Modules\Registry::settingsFor()
|
|
* schema and CompanySetting persistence (per-company values).
|
|
*
|
|
* The marketplace browser (install/uninstall/activate) lives in the super-admin
|
|
* context at `/admin/administration/modules`, see features/admin/modules/routes.ts.
|
|
*/
|
|
export const moduleRoutes: RouteRecordRaw[] = [
|
|
{
|
|
path: 'modules',
|
|
name: 'modules.index',
|
|
component: CompanyModulesIndexView,
|
|
meta: {
|
|
requiresAuth: true,
|
|
ability: 'manage-module',
|
|
title: 'modules.title',
|
|
},
|
|
},
|
|
{
|
|
path: 'modules/:slug/settings',
|
|
name: 'modules.settings',
|
|
component: ModuleSettingsView,
|
|
meta: {
|
|
requiresAuth: true,
|
|
ability: 'manage-module',
|
|
title: 'modules.settings.title',
|
|
},
|
|
},
|
|
]
|