56ffca767d
7-day full-access trial, then gated behind an Ed25519-signed license key (internal/license) verified entirely offline — no phone-home dependency. Middleware 402s non-exempt API routes once the trial lapses with no valid key; frontend shows a countdown banner in the last 3 days and a blocking overlay once actually gated, both pointing at the new Settings -> Лицензия tab. tools/gen-license mints keys for the vendor side (never ships the private key).
64 lines
4.6 KiB
JavaScript
64 lines
4.6 KiB
JavaScript
import { Settings, MonitorSmartphone, Users, KeyRound, ListChecks, Tags, Hammer, FileText, Blocks, ToggleLeft, Columns3, LayoutTemplate, Sparkles, Star, Plug, ShieldCheck } from 'lucide-react'
|
|
import SettingsPage from './SettingsPage'
|
|
import IntegrationsPage from './IntegrationsPage'
|
|
import InterfaceTab from './InterfaceTab'
|
|
import UpdatesTab from './UpdatesTab'
|
|
import LicenseTab from './LicenseTab'
|
|
import SectionsTab from './SectionsTab'
|
|
import OrderStatusesPage from './OrderStatusesPage'
|
|
import PcBuildPresetsPage from './PcBuildPresetsPage'
|
|
import StaffPage from '../staff/StaffPage'
|
|
import RolesPage from '../roles/RolesPage'
|
|
import OrderFieldsPage from '../orderfields/OrderFieldsPage'
|
|
import CatalogsPage from '../catalogs/CatalogsPage'
|
|
import ServicesPage from '../servicecatalog/ServicesPage'
|
|
import DocumentTemplatesPage from '../doctemplates/DocumentTemplatesPage'
|
|
import ModulesPage from '../modules/ModulesPage'
|
|
import SiteBuilderPage from '../site/SiteBuilderPage'
|
|
|
|
// Single source of truth for both the tab bar (SettingsLayout) and the
|
|
// nested routes under /settings/* (App.jsx) — same "one array drives two
|
|
// renderers" shape as layout/navItems.js's buildNavEntries, so tabs and
|
|
// routes can never drift out of sync. path: '' is the index tab.
|
|
// permission: undefined means every role that can reach /settings sees it
|
|
// (Интерфейс is personal display prefs, not an owner-only concern).
|
|
//
|
|
// moduleKey ties a tab to feature_modules (see hooks/useFeatureModules.js) —
|
|
// SettingsLayout hides the tab (and redirects away from its route) the same
|
|
// way it already hides permission-gated tabs, when that module is off.
|
|
// "Разделы" itself has no moduleKey — you can't toggle away the page that
|
|
// does the toggling.
|
|
//
|
|
// group ties a tab to one of SETTINGS_GROUPS below — purely a rendering
|
|
// grouping (SettingsLayout clusters tabs under a label instead of one long
|
|
// horizontal-scroll strip), not a routing or permission concept, so it
|
|
// never needs touching if a tab moves permission tiers.
|
|
export const SETTINGS_TABS = [
|
|
{ path: '', label: 'Общие', icon: Settings, permission: 'settings', group: 'general', Component: SettingsPage },
|
|
{ path: 'integrations', label: 'Интеграции', icon: Plug, permission: 'settings', group: 'general', Component: IntegrationsPage },
|
|
{ path: 'interface', label: 'Интерфейс', icon: MonitorSmartphone, group: 'general', Component: InterfaceTab },
|
|
{ path: 'updates', label: 'Обновления', icon: Sparkles, group: 'general', Component: UpdatesTab },
|
|
{ path: 'sections', label: 'Разделы', icon: ToggleLeft, permission: 'settings', group: 'workflow', Component: SectionsTab },
|
|
{ path: 'order-statuses', label: 'Статусы канбана', icon: Columns3, permission: 'catalogs', group: 'workflow', Component: OrderStatusesPage },
|
|
{ path: 'order-fields', label: 'Поля приёмки', icon: ListChecks, permission: 'order_fields', group: 'workflow', Component: OrderFieldsPage },
|
|
{ path: 'catalogs', label: 'Справочники', icon: Tags, permission: 'catalogs', moduleKey: 'catalogs', group: 'catalog', Component: CatalogsPage },
|
|
{ path: 'services', label: 'Прайс-лист работ', icon: Hammer, permission: 'services', group: 'catalog', Component: ServicesPage },
|
|
{ path: 'pc-build-presets', label: 'Популярные сборки', icon: Star, permission: 'catalogs', group: 'catalog', Component: PcBuildPresetsPage },
|
|
{ path: 'document-templates', label: 'Шаблоны документов', icon: FileText, permission: 'document_templates', group: 'catalog', Component: DocumentTemplatesPage },
|
|
{ path: 'staff', label: 'Сотрудники', icon: Users, permission: 'staff', group: 'access', Component: StaffPage },
|
|
{ path: 'roles', label: 'Роли', icon: KeyRound, permission: 'staff', group: 'access', Component: RolesPage },
|
|
{ path: 'modules', label: 'Модули', icon: Blocks, permission: 'modules', group: 'system', Component: ModulesPage },
|
|
{ path: 'site-builder', label: 'Конструктор сайта', icon: LayoutTemplate, permission: 'settings', group: 'system', Component: SiteBuilderPage },
|
|
{ path: 'license', label: 'Лицензия', icon: ShieldCheck, permission: 'settings', group: 'system', Component: LicenseTab },
|
|
]
|
|
|
|
// Order here is display order — groups render top to bottom, tabs within a
|
|
// group keep SETTINGS_TABS' own relative order.
|
|
export const SETTINGS_GROUPS = [
|
|
{ key: 'general', label: 'Общие' },
|
|
{ key: 'workflow', label: 'Рабочий процесс' },
|
|
{ key: 'catalog', label: 'Каталоги и документы' },
|
|
{ key: 'access', label: 'Доступ' },
|
|
{ key: 'system', label: 'Система' },
|
|
]
|