Merge branch 'feature/menu-refactoring'

This commit is contained in:
Igor Kulikov 2024-08-20 15:46:21 +03:00
commit 77d1ebb032
34 changed files with 1042 additions and 1076 deletions

View File

@ -14,11 +14,14 @@
/// limitations under the License.
///
import { HasUUID } from '@shared/models/id/has-uuid';
import { AuthState } from '@core/auth/auth.models';
import { Authority } from '@shared/models/authority.enum';
import { deepClone } from '@core/utils';
export declare type MenuSectionType = 'link' | 'toggle';
export interface MenuSection extends HasUUID{
export interface MenuSection {
id: MenuId | string;
name: string;
fullName?: string;
type: MenuSectionType;
@ -26,17 +29,901 @@ export interface MenuSection extends HasUUID{
icon: string;
pages?: Array<MenuSection>;
opened?: boolean;
disabled?: boolean;
rootOnly?: boolean;
customTranslate?: boolean;
}
export interface MenuReference {
id: MenuId;
pages?: Array<MenuReference>;
}
export interface HomeSectionReference {
name: string;
places: Array<MenuId>;
}
export interface HomeSection {
name: string;
places: Array<HomeSectionPlace>;
places: Array<MenuSection>;
}
export interface HomeSectionPlace {
name: string;
icon: string;
path: string;
export enum MenuId {
home = 'home',
tenants = 'tenants',
tenant_profiles = 'tenant_profiles',
resources = 'resources',
widget_library = 'widget_library',
widget_types = 'widget_types',
widgets_bundles = 'widgets_bundles',
images = 'images',
scada_symbols = 'scada_symbols',
resources_library = 'resources_library',
notifications_center = 'notifications_center',
notification_inbox = 'notification_inbox',
notification_sent = 'notification_sent',
notification_recipients = 'notification_recipients',
notification_templates = 'notification_templates',
notification_rules = 'notification_rules',
settings = 'settings',
general = 'general',
mail_server = 'mail_server',
home_settings = 'home_settings',
notification_settings = 'notification_settings',
repository_settings = 'repository_settings',
auto_commit_settings = 'auto_commit_settings',
queues = 'queues',
mobile_app_settings = 'mobile_app_settings',
security_settings = 'security_settings',
security_settings_general = 'security_settings_general',
two_fa = '2fa',
oauth2 = 'oauth2',
audit_log = 'audit_log',
alarms = 'alarms',
dashboards = 'dashboards',
entities = 'entities',
devices = 'devices',
assets = 'assets',
entity_views = 'entity_views',
profiles = 'profiles',
device_profiles = 'device_profiles',
asset_profiles = 'asset_profiles',
customers = 'customers',
rule_chains = 'rule_chains',
edge_management = 'edge_management',
edges = 'edges',
edge_instances = 'edge_instances',
rulechain_templates = 'rulechain_templates',
features = 'features',
otaUpdates = 'otaUpdates',
version_control = 'version_control',
api_usage = 'api_usage'
}
declare type MenuFilter = (authState: AuthState) => boolean;
export const menuSectionMap = new Map<MenuId, MenuSection>([
[
MenuId.home,
{
id: MenuId.home,
name: 'home.home',
type: 'link',
path: '/home',
icon: 'home'
}
],
[
MenuId.tenants,
{
id: MenuId.tenants,
name: 'tenant.tenants',
type: 'link',
path: '/tenants',
icon: 'supervisor_account'
}
],
[
MenuId.tenant_profiles,
{
id: MenuId.tenant_profiles,
name: 'tenant-profile.tenant-profiles',
type: 'link',
path: '/tenantProfiles',
icon: 'mdi:alpha-t-box'
}
],
[
MenuId.resources,
{
id: MenuId.resources,
name: 'admin.resources',
type: 'toggle',
path: '/resources',
icon: 'folder'
}
],
[
MenuId.widget_library,
{
id: MenuId.widget_library,
name: 'widget.widget-library',
type: 'link',
path: '/resources/widgets-library',
icon: 'now_widgets'
}
],
[
MenuId.widget_types,
{
id: MenuId.widget_types,
name: 'widget.widgets',
type: 'link',
path: '/resources/widgets-library/widget-types',
icon: 'now_widgets'
}
],
[
MenuId.widgets_bundles,
{
id: MenuId.widgets_bundles,
name: 'widgets-bundle.widgets-bundles',
type: 'link',
path: '/resources/widgets-library/widgets-bundles',
icon: 'now_widgets'
}
],
[
MenuId.images,
{
id: MenuId.images,
name: 'image.gallery',
type: 'link',
path: '/resources/images',
icon: 'filter'
}
],
[
MenuId.scada_symbols,
{
id: MenuId.scada_symbols,
name: 'scada.symbols',
type: 'link',
path: '/resources/scada-symbols',
icon: 'view_in_ar'
}
],
[
MenuId.resources_library,
{
id: MenuId.resources_library,
name: 'resource.resources-library',
type: 'link',
path: '/resources/resources-library',
icon: 'mdi:rhombus-split'
}
],
[
MenuId.notifications_center,
{
id: MenuId.notifications_center,
name: 'notification.notification-center',
type: 'link',
path: '/notification',
icon: 'mdi:message-badge'
}
],
[
MenuId.notification_inbox,
{
id: MenuId.notification_inbox,
name: 'notification.inbox',
fullName: 'notification.notification-inbox',
type: 'link',
path: '/notification/inbox',
icon: 'inbox'
}
],
[
MenuId.notification_sent,
{
id: MenuId.notification_sent,
name: 'notification.sent',
fullName: 'notification.notification-sent',
type: 'link',
path: '/notification/sent',
icon: 'outbox'
}
],
[
MenuId.notification_recipients,
{
id: MenuId.notification_recipients,
name: 'notification.recipients',
fullName: 'notification.notification-recipients',
type: 'link',
path: '/notification/recipients',
icon: 'contacts'
}
],
[
MenuId.notification_templates,
{
id: MenuId.notification_templates,
name: 'notification.templates',
fullName: 'notification.notification-templates',
type: 'link',
path: '/notification/templates',
icon: 'mdi:message-draw'
}
],
[
MenuId.notification_rules,
{
id: MenuId.notification_rules,
name: 'notification.rules',
fullName: 'notification.notification-rules',
type: 'link',
path: '/notification/rules',
icon: 'mdi:message-cog'
}
],
[
MenuId.settings,
{
id: MenuId.settings,
name: 'admin.settings',
type: 'link',
path: '/settings',
icon: 'settings'
}
],
[
MenuId.general,
{
id: MenuId.general,
name: 'admin.general',
fullName: 'admin.general-settings',
type: 'link',
path: '/settings/general',
icon: 'settings_applications'
}
],
[
MenuId.mail_server,
{
id: MenuId.mail_server,
name: 'admin.outgoing-mail',
type: 'link',
path: '/settings/outgoing-mail',
icon: 'mail'
}
],
[
MenuId.home_settings,
{
id: MenuId.home_settings,
name: 'admin.home',
fullName: 'admin.home-settings',
type: 'link',
path: '/settings/home',
icon: 'settings_applications'
}
],
[
MenuId.notification_settings,
{
id: MenuId.notification_settings,
name: 'admin.notifications',
fullName: 'admin.notifications-settings',
type: 'link',
path: '/settings/notifications',
icon: 'mdi:message-badge'
}
],
[
MenuId.repository_settings,
{
id: MenuId.repository_settings,
name: 'admin.repository',
fullName: 'admin.repository-settings',
type: 'link',
path: '/settings/repository',
icon: 'manage_history'
}
],
[
MenuId.auto_commit_settings,
{
id: MenuId.auto_commit_settings,
name: 'admin.auto-commit',
fullName: 'admin.auto-commit-settings',
type: 'link',
path: '/settings/auto-commit',
icon: 'settings_backup_restore'
}
],
[
MenuId.queues,
{
id: MenuId.queues,
name: 'admin.queues',
type: 'link',
path: '/settings/queues',
icon: 'swap_calls'
}
],
[
MenuId.mobile_app_settings,
{
id: MenuId.mobile_app_settings,
name: 'admin.mobile-app.mobile-app',
fullName: 'admin.mobile-app.mobile-app',
type: 'link',
path: '/settings/mobile-app',
icon: 'smartphone'
}
],
[
MenuId.security_settings,
{
id: MenuId.security_settings,
name: 'security.security',
type: 'toggle',
path: '/security-settings',
icon: 'security'
}
],
[
MenuId.security_settings_general,
{
id: MenuId.security_settings_general,
name: 'admin.general',
fullName: 'security.general-settings',
type: 'link',
path: '/security-settings/general',
icon: 'settings_applications'
}
],
[
MenuId.two_fa,
{
id: MenuId.two_fa,
name: 'admin.2fa.2fa',
type: 'link',
path: '/security-settings/2fa',
icon: 'mdi:two-factor-authentication'
}
],
[
MenuId.oauth2,
{
id: MenuId.oauth2,
name: 'admin.oauth2.oauth2',
type: 'link',
path: '/security-settings/oauth2',
icon: 'mdi:shield-account'
}
],
[
MenuId.audit_log,
{
id: MenuId.audit_log,
name: 'audit-log.audit-logs',
type: 'link',
path: '/security-settings/auditLogs',
icon: 'track_changes'
}
],
[
MenuId.alarms,
{
id: MenuId.alarms,
name: 'alarm.alarms',
type: 'link',
path: '/alarms',
icon: 'mdi:alert-outline'
}
],
[
MenuId.dashboards,
{
id: MenuId.dashboards,
name: 'dashboard.dashboards',
type: 'link',
path: '/dashboards',
icon: 'dashboards'
}
],
[
MenuId.entities,
{
id: MenuId.entities,
name: 'entity.entities',
type: 'toggle',
path: '/entities',
icon: 'category'
}
],
[
MenuId.devices,
{
id: MenuId.devices,
name: 'device.devices',
type: 'link',
path: '/entities/devices',
icon: 'devices_other'
}
],
[
MenuId.assets,
{
id: MenuId.assets,
name: 'asset.assets',
type: 'link',
path: '/entities/assets',
icon: 'domain'
}
],
[
MenuId.entity_views,
{
id: MenuId.entity_views,
name: 'entity-view.entity-views',
type: 'link',
path: '/entities/entityViews',
icon: 'view_quilt'
}
],
[
MenuId.profiles,
{
id: MenuId.profiles,
name: 'profiles.profiles',
type: 'toggle',
path: '/profiles',
icon: 'badge'
}
],
[
MenuId.device_profiles,
{
id: MenuId.device_profiles,
name: 'device-profile.device-profiles',
type: 'link',
path: '/profiles/deviceProfiles',
icon: 'mdi:alpha-d-box'
}
],
[
MenuId.asset_profiles,
{
id: MenuId.asset_profiles,
name: 'asset-profile.asset-profiles',
type: 'link',
path: '/profiles/assetProfiles',
icon: 'mdi:alpha-a-box'
}
],
[
MenuId.customers,
{
id: MenuId.customers,
name: 'customer.customers',
type: 'link',
path: '/customers',
icon: 'supervisor_account'
}
],
[
MenuId.rule_chains,
{
id: MenuId.rule_chains,
name: 'rulechain.rulechains',
type: 'link',
path: '/ruleChains',
icon: 'settings_ethernet'
}
],
[
MenuId.edge_management,
{
id: MenuId.edge_management,
name: 'edge.management',
type: 'toggle',
path: '/edgeManagement',
icon: 'settings_input_antenna'
}
],
[
MenuId.edges,
{
id: MenuId.edges,
name: 'edge.instances',
fullName: 'edge.edge-instances',
type: 'link',
path: '/edgeManagement/instances',
icon: 'router'
}
],
[
MenuId.edge_instances,
{
id: MenuId.edge_instances,
name: 'edge.edge-instances',
fullName: 'edge.edge-instances',
type: 'link',
path: '/edgeManagement/instances',
icon: 'router'
}
],
[
MenuId.rulechain_templates,
{
id: MenuId.rulechain_templates,
name: 'edge.rulechain-templates',
fullName: 'edge.edge-rulechain-templates',
type: 'link',
path: '/edgeManagement/ruleChains',
icon: 'settings_ethernet'
}
],
[
MenuId.features,
{
id: MenuId.features,
name: 'feature.advanced-features',
type: 'toggle',
path: '/features',
icon: 'construction'
}
],
[
MenuId.otaUpdates,
{
id: MenuId.otaUpdates,
name: 'ota-update.ota-updates',
type: 'link',
path: '/features/otaUpdates',
icon: 'memory'
}
],
[
MenuId.version_control,
{
id: MenuId.version_control,
name: 'version-control.version-control',
type: 'link',
path: '/features/vc',
icon: 'history'
}
],
[
MenuId.api_usage,
{
id: MenuId.api_usage,
name: 'api-usage.api-usage',
type: 'link',
path: '/usage',
icon: 'insert_chart'
}
]
]);
const menuFilters = new Map<MenuId, MenuFilter>([
[
MenuId.edges, (authState) => authState.edgesSupportEnabled
],
[
MenuId.edge_management, (authState) => authState.edgesSupportEnabled
],
[
MenuId.rulechain_templates, (authState) => authState.edgesSupportEnabled
]
]);
const defaultUserMenuMap = new Map<Authority, MenuReference[]>([
[
Authority.SYS_ADMIN,
[
{id: MenuId.home},
{id: MenuId.tenants},
{id: MenuId.tenant_profiles},
{
id: MenuId.resources,
pages: [
{
id: MenuId.widget_library,
pages: [
{id: MenuId.widget_types},
{id: MenuId.widgets_bundles}
]
},
{id: MenuId.images},
{id: MenuId.scada_symbols},
{id: MenuId.resources_library}
]
},
{
id: MenuId.notifications_center,
pages: [
{id: MenuId.notification_inbox},
{id: MenuId.notification_sent},
{id: MenuId.notification_recipients},
{id: MenuId.notification_templates},
{id: MenuId.notification_rules}
]
},
{
id: MenuId.settings,
pages: [
{id: MenuId.general},
{id: MenuId.mail_server},
{id: MenuId.notification_settings},
{id: MenuId.queues},
{id: MenuId.mobile_app_settings}
]
},
{
id: MenuId.security_settings,
pages: [
{id: MenuId.security_settings_general},
{id: MenuId.two_fa},
{id: MenuId.oauth2}
]
}
]
],
[
Authority.TENANT_ADMIN,
[
{id: MenuId.home},
{id: MenuId.alarms},
{id: MenuId.dashboards},
{
id: MenuId.entities,
pages: [
{id: MenuId.devices},
{id: MenuId.assets},
{id: MenuId.entity_views}
]
},
{
id: MenuId.profiles,
pages: [
{id: MenuId.device_profiles},
{id: MenuId.asset_profiles}
]
},
{id: MenuId.customers},
{id: MenuId.rule_chains},
{
id: MenuId.edge_management,
pages: [
{id: MenuId.edges},
{id: MenuId.rulechain_templates}
]
},
{
id: MenuId.features,
pages: [
{id: MenuId.otaUpdates},
{id: MenuId.version_control}
]
},
{
id: MenuId.resources,
pages: [
{
id: MenuId.widget_library,
pages: [
{id: MenuId.widget_types},
{id: MenuId.widgets_bundles}
]
},
{id: MenuId.images},
{id: MenuId.scada_symbols},
{id: MenuId.resources_library}
]
},
{
id: MenuId.notifications_center,
pages: [
{id: MenuId.notification_inbox},
{id: MenuId.notification_sent},
{id: MenuId.notification_recipients},
{id: MenuId.notification_templates},
{id: MenuId.notification_rules}
]
},
{id: MenuId.api_usage},
{
id: MenuId.settings,
pages: [
{id: MenuId.home_settings},
{id: MenuId.notification_settings},
{id: MenuId.repository_settings},
{id: MenuId.auto_commit_settings}
]
},
{
id: MenuId.security_settings,
pages: [
{id: MenuId.audit_log}
]
}
]
],
[
Authority.CUSTOMER_USER,
[
{id: MenuId.home},
{id: MenuId.alarms},
{id: MenuId.dashboards},
{
id: MenuId.entities,
pages: [
{id: MenuId.devices},
{id: MenuId.assets},
{id: MenuId.entity_views}
]
},
{id: MenuId.edge_instances},
{
id: MenuId.notifications_center,
pages: [
{id: MenuId.notification_inbox}
]
}
]
]
]);
const defaultHomeSectionMap = new Map<Authority, HomeSectionReference[]>([
[
Authority.SYS_ADMIN,
[
{
name: 'tenant.management',
places: [MenuId.tenants, MenuId.tenant_profiles]
},
{
name: 'widget.management',
places: [MenuId.widget_library]
},
{
name: 'admin.system-settings',
places: [MenuId.general, MenuId.mail_server,
MenuId.notification_settings, MenuId.security_settings, MenuId.oauth2, MenuId.two_fa, MenuId.resources_library, MenuId.queues]
}
]
],
[
Authority.TENANT_ADMIN,
[
{
name: 'rulechain.management',
places: [MenuId.rule_chains]
},
{
name: 'customer.management',
places: [MenuId.customers]
},
{
name: 'asset.management',
places: [MenuId.assets, MenuId.asset_profiles]
},
{
name: 'device.management',
places: [MenuId.devices, MenuId.device_profiles, MenuId.otaUpdates]
},
{
name: 'entity-view.management',
places: [MenuId.entity_views]
},
{
name: 'edge.management',
places: [MenuId.edges, MenuId.rulechain_templates]
},
{
name: 'dashboard.management',
places: [MenuId.widget_library, MenuId.dashboards]
},
{
name: 'version-control.management',
places: [MenuId.version_control]
},
{
name: 'audit-log.audit',
places: [MenuId.audit_log, MenuId.api_usage]
},
{
name: 'admin.system-settings',
places: [MenuId.home_settings, MenuId.resources_library, MenuId.repository_settings, MenuId.auto_commit_settings]
}
]
],
[
Authority.CUSTOMER_USER,
[
{
name: 'asset.view-assets',
places: [MenuId.assets]
},
{
name: 'device.view-devices',
places: [MenuId.devices]
},
{
name: 'entity-view.management',
places: [MenuId.entity_views]
},
{
name: 'edge.management',
places: [MenuId.edge_instances]
},
{
name: 'dashboard.view-dashboards',
places: [MenuId.dashboards]
}
]
]
]);
export const buildUserMenu = (authState: AuthState): Array<MenuSection> => {
const references = defaultUserMenuMap.get(authState.authUser.authority);
return (references || []).map(ref => referenceToMenuSection(authState, ref)).filter(section => !!section);
};
export const buildUserHome = (authState: AuthState, availableMenuSections: MenuSection[]): Array<HomeSection> => {
const references = defaultHomeSectionMap.get(authState.authUser.authority);
return (references || []).map(ref =>
homeReferenceToHomeSection(availableMenuSections, ref)).filter(section => !!section);
};
const referenceToMenuSection = (authState: AuthState, reference: MenuReference): MenuSection | undefined => {
if (filterMenuReference(authState, reference)) {
const section = menuSectionMap.get(reference.id);
if (section) {
const result = deepClone(section);
if (reference.pages?.length) {
result.pages = reference.pages.map(page =>
referenceToMenuSection(authState, page)).filter(page => !!page);
}
return result;
} else {
return undefined;
}
} else {
return undefined;
}
};
const filterMenuReference = (authState: AuthState, reference: MenuReference): boolean => {
const filter = menuFilters.get(reference.id);
if (filter) {
if (filter(authState)) {
if (reference.pages?.length) {
if (reference.pages.every(page => !filterMenuReference(authState, page))) {
return false;
}
}
return true;
}
return false;
} else {
return true;
}
};
const homeReferenceToHomeSection = (availableMenuSections: MenuSection[], reference: HomeSectionReference): HomeSection | undefined => {
const places = reference.places.map(id => availableMenuSections.find(m => m.id === id)).filter(p => !!p);
if (places.length) {
return {
name: reference.name,
places
};
} else {
return undefined;
}
};

View File

@ -19,9 +19,8 @@ import { select, Store } from '@ngrx/store';
import { AppState } from '../core.state';
import { getCurrentOpenedMenuSections, selectAuth, selectIsAuthenticated } from '../auth/auth.selectors';
import { filter, map, take } from 'rxjs/operators';
import { HomeSection, MenuSection } from '@core/services/menu.models';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { Authority } from '@shared/models/authority.enum';
import { buildUserHome, buildUserMenu, HomeSection, MenuId, MenuSection } from '@core/services/menu.models';
import { Observable, ReplaySubject, Subject } from 'rxjs';
import { AuthState } from '@core/auth/auth.models';
import { NavigationEnd, Router } from '@angular/router';
@ -30,10 +29,11 @@ import { NavigationEnd, Router } from '@angular/router';
})
export class MenuService {
currentMenuSections: Array<MenuSection>;
menuSections$: Subject<Array<MenuSection>> = new BehaviorSubject<Array<MenuSection>>([]);
homeSections$: Subject<Array<HomeSection>> = new BehaviorSubject<Array<HomeSection>>([]);
availableMenuLinks$ = this.menuSections$.pipe(
private currentMenuSections: Array<MenuSection>;
private menuSections$: Subject<Array<MenuSection>> = new ReplaySubject<Array<MenuSection>>(1);
private homeSections$: Subject<Array<HomeSection>> = new ReplaySubject<Array<HomeSection>>(1);
private availableMenuSections$: Subject<Array<MenuSection>> = new ReplaySubject<Array<MenuSection>>(1);
private availableMenuLinks$ = this.menuSections$.pipe(
map((items) => this.allMenuLinks(items))
);
@ -57,23 +57,12 @@ export class MenuService {
this.store.pipe(select(selectAuth), take(1)).subscribe(
(authState: AuthState) => {
if (authState.authUser) {
let homeSections: Array<HomeSection>;
switch (authState.authUser.authority) {
case Authority.SYS_ADMIN:
this.currentMenuSections = this.buildSysAdminMenu();
homeSections = this.buildSysAdminHome();
break;
case Authority.TENANT_ADMIN:
this.currentMenuSections = this.buildTenantAdminMenu(authState);
homeSections = this.buildTenantAdminHome(authState);
break;
case Authority.CUSTOMER_USER:
this.currentMenuSections = this.buildCustomerUserMenu(authState);
homeSections = this.buildCustomerUserHome(authState);
break;
}
this.currentMenuSections = buildUserMenu(authState);
this.updateOpenedMenuSections();
this.menuSections$.next(this.currentMenuSections);
const availableMenuSections = this.allMenuSections(this.currentMenuSections);
this.availableMenuSections$.next(availableMenuSections);
const homeSections = buildUserHome(authState, availableMenuSections);
this.homeSections$.next(homeSections);
}
}
@ -89,916 +78,6 @@ export class MenuService {
);
}
private buildSysAdminMenu(): Array<MenuSection> {
const sections: Array<MenuSection> = [];
sections.push(
{
id: 'home',
name: 'home.home',
type: 'link',
path: '/home',
icon: 'home'
},
{
id: 'tenants',
name: 'tenant.tenants',
type: 'link',
path: '/tenants',
icon: 'supervisor_account'
},
{
id: 'tenant_profiles',
name: 'tenant-profile.tenant-profiles',
type: 'link',
path: '/tenantProfiles',
icon: 'mdi:alpha-t-box'
},
{
id: 'resources',
name: 'admin.resources',
type: 'toggle',
path: '/resources',
icon: 'folder',
pages: [
{
id: 'widget_library',
name: 'widget.widget-library',
type: 'link',
path: '/resources/widgets-library',
icon: 'now_widgets',
pages: [
{
id: 'widget_types',
name: 'widget.widgets',
type: 'link',
path: '/resources/widgets-library/widget-types',
icon: 'now_widgets'
},
{
id: 'widgets_bundles',
name: 'widgets-bundle.widgets-bundles',
type: 'link',
path: '/resources/widgets-library/widgets-bundles',
icon: 'now_widgets'
}
]
},
{
id: 'images',
name: 'image.gallery',
type: 'link',
path: '/resources/images',
icon: 'filter'
},
{
id: 'scada_symbols',
name: 'scada.symbols',
type: 'link',
path: '/resources/scada-symbols',
icon: 'view_in_ar'
},
{
id: 'resources_library',
name: 'resource.resources-library',
type: 'link',
path: '/resources/resources-library',
icon: 'mdi:rhombus-split'
}
]
},
{
id: 'notifications_center',
name: 'notification.notification-center',
type: 'link',
path: '/notification',
icon: 'mdi:message-badge',
pages: [
{
id: 'notification_inbox',
name: 'notification.inbox',
fullName: 'notification.notification-inbox',
type: 'link',
path: '/notification/inbox',
icon: 'inbox'
},
{
id: 'notification_sent',
name: 'notification.sent',
fullName: 'notification.notification-sent',
type: 'link',
path: '/notification/sent',
icon: 'outbox'
},
{
id: 'notification_recipients',
name: 'notification.recipients',
fullName: 'notification.notification-recipients',
type: 'link',
path: '/notification/recipients',
icon: 'contacts'
},
{
id: 'notification_templates',
name: 'notification.templates',
fullName: 'notification.notification-templates',
type: 'link',
path: '/notification/templates',
icon: 'mdi:message-draw'
},
{
id: 'notification_rules',
name: 'notification.rules',
fullName: 'notification.notification-rules',
type: 'link',
path: '/notification/rules',
icon: 'mdi:message-cog'
}
]
},
{
id: 'settings',
name: 'admin.settings',
type: 'link',
path: '/settings',
icon: 'settings',
pages: [
{
id: 'general',
name: 'admin.general',
fullName: 'admin.general-settings',
type: 'link',
path: '/settings/general',
icon: 'settings_applications'
},
{
id: 'mail_server',
name: 'admin.outgoing-mail',
type: 'link',
path: '/settings/outgoing-mail',
icon: 'mail'
},
{
id: 'notification_settings',
name: 'admin.notifications',
fullName: 'admin.notifications-settings',
type: 'link',
path: '/settings/notifications',
icon: 'mdi:message-badge'
},
{
id: 'queues',
name: 'admin.queues',
type: 'link',
path: '/settings/queues',
icon: 'swap_calls'
},
{
id: 'mobile_app_settings',
name: 'admin.mobile-app.mobile-app',
fullName: 'admin.mobile-app.mobile-app',
type: 'link',
path: '/settings/mobile-app',
icon: 'smartphone'
}
]
},
{
id: 'security_settings',
name: 'security.security',
type: 'toggle',
path: '/security-settings',
icon: 'security',
pages: [
{
id: 'security_settings_general',
name: 'admin.general',
fullName: 'security.general-settings',
type: 'link',
path: '/security-settings/general',
icon: 'settings_applications'
},
{
id: '2fa',
name: 'admin.2fa.2fa',
type: 'link',
path: '/security-settings/2fa',
icon: 'mdi:two-factor-authentication'
},
{
id: 'oauth2',
name: 'admin.oauth2.oauth2',
type: 'link',
path: '/security-settings/oauth2',
icon: 'mdi:shield-account'
}
]
}
);
return sections;
}
private buildSysAdminHome(): Array<HomeSection> {
const homeSections: Array<HomeSection> = [];
homeSections.push(
{
name: 'tenant.management',
places: [
{
name: 'tenant.tenants',
icon: 'supervisor_account',
path: '/tenants'
},
{
name: 'tenant-profile.tenant-profiles',
icon: 'mdi:alpha-t-box',
path: '/tenantProfiles'
},
]
},
{
name: 'widget.management',
places: [
{
name: 'widget.widget-library',
icon: 'now_widgets',
path: '/resources/widgets-library',
}
]
},
{
name: 'admin.system-settings',
places: [
{
name: 'admin.general',
icon: 'settings_applications',
path: '/settings/general'
},
{
name: 'admin.outgoing-mail',
icon: 'mail',
path: '/settings/outgoing-mail'
},
{
name: 'admin.sms-provider',
icon: 'sms',
path: '/settings/sms-provider'
},
{
name: 'admin.security-settings',
icon: 'security',
path: '/settings/security-settings'
},
{
name: 'admin.oauth2.oauth2',
icon: 'security',
path: '/settings/oauth2'
},
{
name: 'admin.2fa.2fa',
icon: 'mdi:two-factor-authentication',
path: '/settings/2fa'
},
{
name: 'resource.resources-library',
icon: 'folder',
path: '/settings/resources-library'
},
{
name: 'admin.queues',
icon: 'swap_calls',
path: '/settings/queues'
},
]
}
);
return homeSections;
}
private buildTenantAdminMenu(authState: AuthState): Array<MenuSection> {
const sections: Array<MenuSection> = [];
sections.push(
{
id: 'home',
name: 'home.home',
type: 'link',
path: '/home',
icon: 'home'
},
{
id: 'alarms',
name: 'alarm.alarms',
type: 'link',
path: '/alarms',
icon: 'mdi:alert-outline'
},
{
id: 'dashboards',
name: 'dashboard.dashboards',
type: 'link',
path: '/dashboards',
icon: 'dashboards'
},
{
id: 'entities',
name: 'entity.entities',
type: 'toggle',
path: '/entities',
icon: 'category',
pages: [
{
id: 'devices',
name: 'device.devices',
type: 'link',
path: '/entities/devices',
icon: 'devices_other'
},
{
id: 'assets',
name: 'asset.assets',
type: 'link',
path: '/entities/assets',
icon: 'domain'
},
{
id: 'entity_views',
name: 'entity-view.entity-views',
type: 'link',
path: '/entities/entityViews',
icon: 'view_quilt'
}
]
},
{
id: 'profiles',
name: 'profiles.profiles',
type: 'toggle',
path: '/profiles',
icon: 'badge',
pages: [
{
id: 'device_profiles',
name: 'device-profile.device-profiles',
type: 'link',
path: '/profiles/deviceProfiles',
icon: 'mdi:alpha-d-box'
},
{
id: 'asset_profiles',
name: 'asset-profile.asset-profiles',
type: 'link',
path: '/profiles/assetProfiles',
icon: 'mdi:alpha-a-box'
}
]
},
{
id: 'customers',
name: 'customer.customers',
type: 'link',
path: '/customers',
icon: 'supervisor_account'
},
{
id: 'rule_chains',
name: 'rulechain.rulechains',
type: 'link',
path: '/ruleChains',
icon: 'settings_ethernet'
}
);
if (authState.edgesSupportEnabled) {
sections.push(
{
id: 'edge_management',
name: 'edge.management',
type: 'toggle',
path: '/edgeManagement',
icon: 'settings_input_antenna',
pages: [
{
id: 'edges',
name: 'edge.instances',
fullName: 'edge.edge-instances',
type: 'link',
path: '/edgeManagement/instances',
icon: 'router'
},
{
id: 'rulechain_templates',
name: 'edge.rulechain-templates',
fullName: 'edge.edge-rulechain-templates',
type: 'link',
path: '/edgeManagement/ruleChains',
icon: 'settings_ethernet'
}
]
}
);
}
sections.push(
{
id: 'features',
name: 'feature.advanced-features',
type: 'toggle',
path: '/features',
icon: 'construction',
pages: [
{
id: 'otaUpdates',
name: 'ota-update.ota-updates',
type: 'link',
path: '/features/otaUpdates',
icon: 'memory'
},
{
id: 'version_control',
name: 'version-control.version-control',
type: 'link',
path: '/features/vc',
icon: 'history'
}
]
},
{
id: 'resources',
name: 'admin.resources',
type: 'toggle',
path: '/resources',
icon: 'folder',
pages: [
{
id: 'widget_library',
name: 'widget.widget-library',
type: 'link',
path: '/resources/widgets-library',
icon: 'now_widgets',
pages: [
{
id: 'widget_types',
name: 'widget.widgets',
type: 'link',
path: '/resources/widgets-library/widget-types',
icon: 'now_widgets'
},
{
id: 'widgets_bundles',
name: 'widgets-bundle.widgets-bundles',
type: 'link',
path: '/resources/widgets-library/widgets-bundles',
icon: 'now_widgets'
}
]
},
{
id: 'images',
name: 'image.gallery',
type: 'link',
path: '/resources/images',
icon: 'filter'
},
{
id: 'scada_symbols',
name: 'scada.symbols',
type: 'link',
path: '/resources/scada-symbols',
icon: 'view_in_ar'
},
{
id: 'resources_library',
name: 'resource.resources-library',
type: 'link',
path: '/resources/resources-library',
icon: 'mdi:rhombus-split'
}
]
},
{
id: 'notifications_center',
name: 'notification.notification-center',
type: 'link',
path: '/notification',
icon: 'mdi:message-badge',
pages: [
{
id: 'notification_inbox',
name: 'notification.inbox',
fullName: 'notification.notification-inbox',
type: 'link',
path: '/notification/inbox',
icon: 'inbox'
},
{
id: 'notification_sent',
name: 'notification.sent',
fullName: 'notification.notification-sent',
type: 'link',
path: '/notification/sent',
icon: 'outbox'
},
{
id: 'notification_recipients',
name: 'notification.recipients',
fullName: 'notification.notification-recipients',
type: 'link',
path: '/notification/recipients',
icon: 'contacts'
},
{
id: 'notification_templates',
name: 'notification.templates',
fullName: 'notification.notification-templates',
type: 'link',
path: '/notification/templates',
icon: 'mdi:message-draw'
},
{
id: 'notification_rules',
name: 'notification.rules',
fullName: 'notification.notification-rules',
type: 'link',
path: '/notification/rules',
icon: 'mdi:message-cog'
}
]
},
{
id: 'api_usage',
name: 'api-usage.api-usage',
type: 'link',
path: '/usage',
icon: 'insert_chart'
},
{
id: 'settings',
name: 'admin.settings',
type: 'link',
path: '/settings',
icon: 'settings',
pages: [
{
id: 'home_settings',
name: 'admin.home',
fullName: 'admin.home-settings',
type: 'link',
path: '/settings/home',
icon: 'settings_applications'
},
{
id: 'notification_settings',
name: 'admin.notifications',
fullName: 'admin.notifications-settings',
type: 'link',
path: '/settings/notifications',
icon: 'mdi:message-badge'
},
{
id: 'repository_settings',
name: 'admin.repository',
fullName: 'admin.repository-settings',
type: 'link',
path: '/settings/repository',
icon: 'manage_history'
},
{
id: 'auto_commit_settings',
name: 'admin.auto-commit',
fullName: 'admin.auto-commit-settings',
type: 'link',
path: '/settings/auto-commit',
icon: 'settings_backup_restore'
}
]
},
{
id: 'security_settings',
name: 'security.security',
type: 'toggle',
path: '/security-settings',
icon: 'security',
pages: [
{
id: 'audit_log',
name: 'audit-log.audit-logs',
type: 'link',
path: '/security-settings/auditLogs',
icon: 'track_changes'
}
]
}
);
return sections;
}
private buildTenantAdminHome(authState: AuthState): Array<HomeSection> {
const homeSections: Array<HomeSection> = [];
homeSections.push(
{
name: 'rulechain.management',
places: [
{
name: 'rulechain.rulechains',
icon: 'settings_ethernet',
path: '/ruleChains'
}
]
},
{
name: 'customer.management',
places: [
{
name: 'customer.customers',
icon: 'supervisor_account',
path: '/customers'
}
]
},
{
name: 'asset.management',
places: [
{
name: 'asset.assets',
icon: 'domain',
path: '/assets'
},
{
name: 'asset-profile.asset-profiles',
icon: 'mdi:alpha-a-box',
path: '/profiles/assetProfiles'
}
]
},
{
name: 'device.management',
places: [
{
name: 'device.devices',
icon: 'devices_other',
path: '/devices'
},
{
name: 'device-profile.device-profiles',
icon: 'mdi:alpha-d-box',
path: '/profiles/deviceProfiles'
},
{
name: 'ota-update.ota-updates',
icon: 'memory',
path: '/otaUpdates'
}
]
},
{
name: 'entity-view.management',
places: [
{
name: 'entity-view.entity-views',
icon: 'view_quilt',
path: '/entityViews'
}
]
}
);
if (authState.edgesSupportEnabled) {
homeSections.push(
{
name: 'edge.management',
places: [
{
name: 'edge.edge-instances',
icon: 'router',
path: '/edgeInstances'
},
{
name: 'edge.rulechain-templates',
icon: 'settings_ethernet',
path: '/edgeManagement/ruleChains'
}
]
}
);
}
homeSections.push(
{
name: 'dashboard.management',
places: [
{
name: 'widget.widget-library',
icon: 'now_widgets',
path: '/widgets-bundles'
},
{
name: 'dashboard.dashboards',
icon: 'dashboard',
path: '/dashboards'
}
]
},
{
name: 'version-control.management',
places: [
{
name: 'version-control.version-control',
icon: 'history',
path: '/vc'
}
]
},
{
name: 'audit-log.audit',
places: [
{
name: 'audit-log.audit-logs',
icon: 'track_changes',
path: '/auditLogs'
},
{
name: 'api-usage.api-usage',
icon: 'insert_chart',
path: '/usage'
}
]
},
{
name: 'admin.system-settings',
places: [
{
name: 'admin.home-settings',
icon: 'settings_applications',
path: '/settings/home'
},
{
name: 'resource.resources-library',
icon: 'folder',
path: '/settings/resources-library'
},
{
name: 'admin.repository-settings',
icon: 'manage_history',
path: '/settings/repository',
},
{
name: 'admin.auto-commit-settings',
icon: 'settings_backup_restore',
path: '/settings/auto-commit'
}
]
}
);
return homeSections;
}
private buildCustomerUserMenu(authState: AuthState): Array<MenuSection> {
const sections: Array<MenuSection> = [];
sections.push(
{
id: 'home',
name: 'home.home',
type: 'link',
path: '/home',
icon: 'home'
},
{
id: 'alarms',
name: 'alarm.alarms',
type: 'link',
path: '/alarms',
icon: 'mdi:alert-outline'
},
{
id: 'dashboards',
name: 'dashboard.dashboards',
type: 'link',
path: '/dashboards',
icon: 'dashboards'
},
{
id: 'entities',
name: 'entity.entities',
type: 'toggle',
path: '/entities',
icon: 'category',
pages: [
{
id: 'devices',
name: 'device.devices',
type: 'link',
path: '/entities/devices',
icon: 'devices_other'
},
{
id: 'assets',
name: 'asset.assets',
type: 'link',
path: '/entities/assets',
icon: 'domain'
},
{
id: 'entity_views',
name: 'entity-view.entity-views',
type: 'link',
path: '/entities/entityViews',
icon: 'view_quilt'
}
]
}
);
if (authState.edgesSupportEnabled) {
sections.push(
{
id: 'edges',
name: 'edge.edge-instances',
fullName: 'edge.edge-instances',
type: 'link',
path: '/edgeManagement/instances',
icon: 'router'
}
);
}
sections.push(
{
id: 'notifications_center',
name: 'notification.notification-center',
type: 'link',
path: '/notification',
icon: 'mdi:message-badge',
pages: [
{
id: 'notification_inbox',
name: 'notification.inbox',
fullName: 'notification.notification-inbox',
type: 'link',
path: '/notification/inbox',
icon: 'inbox'
}
]
}
);
return sections;
}
private buildCustomerUserHome(authState: AuthState): Array<HomeSection> {
const homeSections: Array<HomeSection> = [];
homeSections.push(
{
name: 'asset.view-assets',
places: [
{
name: 'asset.assets',
icon: 'domain',
path: '/assets'
}
]
},
{
name: 'device.view-devices',
places: [
{
name: 'device.devices',
icon: 'devices_other',
path: '/devices'
}
]
},
{
name: 'entity-view.management',
places: [
{
name: 'entity-view.entity-views',
icon: 'view_quilt',
path: '/entityViews'
}
]
}
);
if (authState.edgesSupportEnabled) {
homeSections.push(
{
name: 'edge.management',
places: [
{
name: 'edge.edge-instances',
icon: 'settings_input_antenna',
path: '/edgeInstances'
}
]
}
);
}
homeSections.push(
{
name: 'dashboard.view-dashboards',
places: [
{
name: 'dashboard.dashboards',
icon: 'dashboard',
path: '/dashboards'
}
]
}
);
return homeSections;
}
private allMenuLinks(sections: Array<MenuSection>): Array<MenuSection> {
const result: Array<MenuSection> = [];
for (const section of sections) {
@ -1012,6 +91,17 @@ export class MenuService {
return result;
}
private allMenuSections(sections: Array<MenuSection>): Array<MenuSection> {
const result: Array<MenuSection> = [];
for (const section of sections) {
result.push(section);
if (section.pages && section.pages.length) {
result.push(...this.allMenuSections(section.pages));
}
}
return result;
}
public menuSections(): Observable<Array<MenuSection>> {
return this.menuSections$;
}
@ -1024,7 +114,11 @@ export class MenuService {
return this.availableMenuLinks$;
}
public menuLinkById(id: string): Observable<MenuSection | undefined> {
public availableMenuSections(): Observable<Array<MenuSection>> {
return this.availableMenuSections$;
}
public menuLinkById(id: MenuId | string): Observable<MenuSection | undefined> {
return this.availableMenuLinks$.pipe(
map((links) => links.find(link => link.id === id))
);

View File

@ -107,7 +107,7 @@ export class RouterTabsComponent extends PageComponent implements OnInit {
if (found) {
const rootPath = sectionPath.substring(0, sectionPath.length - found.path.length);
const isRoot = rootPath === '';
const tabs: Array<MenuSection> = found ? found.pages.filter(page => !page.disabled && (!page.rootOnly || isRoot)) : [];
const tabs: Array<MenuSection> = found ? found.pages.filter(page => !page.rootOnly || isRoot) : [];
return tabs.map((tab) => ({...tab, path: rootPath + tab.path}));
}
return [];

View File

@ -49,6 +49,7 @@ import { PageLink } from '@shared/models/page/page-link';
import { Direction } from '@shared/models/page/sort-order';
import { emptyPageData, PageData } from '@shared/models/page/page-data';
import { deepClone } from '@core/utils';
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
@Component({
selector: 'tb-quick-link',
@ -114,6 +115,7 @@ export class QuickLinkComponent extends PageComponent implements OnInit, Control
private fb: UntypedFormBuilder,
private menuService: MenuService,
public translate: TranslateService,
private customTranslate: CustomTranslatePipe,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher) {
super(store);
}
@ -135,7 +137,8 @@ export class QuickLinkComponent extends PageComponent implements OnInit, Control
this.updateView(modelValue);
}),
map(value => value ? (typeof value === 'string' ? value :
((value as any).translated ? value.name : this.translate.instant(value.name))) : ''),
((value as any).translated ? value.name
: value.customTranslate ? this.customTranslate.transform(value.name) : this.translate.instant(value.name))) : ''),
distinctUntilChanged(),
switchMap(name => this.fetchLinks(name) ),
share()
@ -202,7 +205,8 @@ export class QuickLinkComponent extends PageComponent implements OnInit, Control
}
displayLinkFn = (link?: MenuSection): string | undefined =>
link ? ((link as any).translated ? link.name : this.translate.instant(link.fullName || link.name)) : undefined;
link ? ((link as any).translated ? link.name : link.customTranslate ? this.customTranslate.transform(link.fullName || link.name)
: this.translate.instant(link.fullName || link.name)) : undefined;
fetchLinks(searchText?: string): Observable<Array<MenuSection>> {
this.searchText = searchText;
@ -228,7 +232,8 @@ export class QuickLinkComponent extends PageComponent implements OnInit, Control
map((links) => {
const result = deepClone(links);
for (const link of result) {
link.name = this.translate.instant(link.fullName || link.name);
link.name = link.customTranslate ? this.customTranslate.transform(link.fullName || link.name)
: this.translate.instant(link.fullName || link.name);
(link as any).translated = true;
}
return result;

View File

@ -26,7 +26,7 @@
<mat-grid-tile *ngFor="let place of sectionPlaces(section)">
<a mat-raised-button color="primary" class="tb-card-button" href="{{place.path}}" (click)="navigate($event, place.path)">
<tb-icon matButtonIcon class="tb-mat-96">{{place.icon}}</tb-icon>
<span translate>{{place.name}}</span>
<span>{{place.customTranslate ? (place.name | customTranslate) : (place.name | translate)}}</span>
</a>
</mat-grid-tile>
</mat-grid-list>

View File

@ -20,7 +20,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { MenuService } from '@core/services/menu.service';
import { HomeSection, HomeSectionPlace } from '@core/services/menu.models';
import { HomeSection, MenuSection } from '@core/services/menu.models';
import { Router } from '@angular/router';
import { map } from 'rxjs/operators';
@ -38,9 +38,7 @@ export class NavigationCardsWidgetComponent extends PageComponent implements OnI
homeSections$ = this.menuService.homeSections();
showHomeSections$ = this.homeSections$.pipe(
map((sections) => {
return sections.filter((section) => this.sectionPlaces(section).length > 0);
})
map((sections) => sections.filter((section) => this.sectionPlaces(section).length > 0))
);
cols = null;
@ -85,11 +83,11 @@ export class NavigationCardsWidgetComponent extends PageComponent implements OnI
});
}
sectionPlaces(section: HomeSection): HomeSectionPlace[] {
sectionPlaces(section: HomeSection): MenuSection[] {
return section && section.places ? section.places.filter((place) => this.filterPlace(place)) : [];
}
private filterPlace(place: HomeSectionPlace): boolean {
private filterPlace(place: MenuSection): boolean {
if (this.settings.filterType === 'include') {
return this.settings.filter.includes(place.path);
} else if (this.settings.filterType === 'exclude') {

View File

@ -17,5 +17,5 @@
-->
<a mat-button routerLinkActive="tb-active" [routerLinkActiveOptions]="{paths: 'subset', queryParams: 'ignored', matrixParams: 'ignored', fragment: 'ignored'}" routerLink="{{section.path}}">
<tb-icon matButtonIcon *ngIf="section.icon !== null">{{section.icon}}</tb-icon>
<span>{{section.name | translate}}</span>
<span>{{section.customTranslate ? (section.name | customTranslate) : (section.name | translate)}}</span>
</a>

View File

@ -17,7 +17,7 @@
-->
<a mat-button class="tb-button-toggle" (click)="toggleSection($event)">
<tb-icon matButtonIcon *ngIf="section.icon !== null">{{section.icon}}</tb-icon>
<span>{{section.name | translate}}</span>
<span>{{section.customTranslate ? (section.name | customTranslate) : (section.name | translate)}}</span>
<span class=" pull-right fa fa-chevron-down tb-toggle-icon"
[ngClass]="{'tb-toggled' : section.opened}"></span>
</a>

View File

@ -45,6 +45,7 @@ import { ImageResourceType, IMAGES_URL_PREFIX, ResourceSubType } from '@shared/m
import { ScadaSymbolComponent } from '@home/pages/scada-symbol/scada-symbol.component';
import { ImageService } from '@core/http/image.service';
import { ScadaSymbolData } from '@home/pages/scada-symbol/scada-symbol-editor.models';
import { MenuId } from '@core/services/menu.models';
@Injectable()
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> {
@ -79,8 +80,7 @@ const routes: Routes = [
data: {
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
breadcrumb: {
label: 'admin.resources',
icon: 'folder'
menuId: MenuId.resources
}
},
children: [
@ -97,8 +97,7 @@ const routes: Routes = [
path: 'images',
data: {
breadcrumb: {
label: 'image.gallery',
icon: 'filter'
menuId: MenuId.images
}
},
children: [
@ -117,8 +116,7 @@ const routes: Routes = [
path: 'scada-symbols',
data: {
breadcrumb: {
label: 'scada.symbols',
icon: 'view_in_ar'
menuId: MenuId.scada_symbols
}
},
children: [
@ -153,8 +151,7 @@ const routes: Routes = [
path: 'resources-library',
data: {
breadcrumb: {
label: 'resource.resources-library',
icon: 'mdi:rhombus-split'
menuId: MenuId.resources_library
}
},
children: [
@ -196,8 +193,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
showMainLoadingBar: false,
breadcrumb: {
label: 'admin.settings',
icon: 'settings'
menuId: MenuId.settings
}
},
children: [
@ -220,8 +216,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.general-settings',
breadcrumb: {
label: 'admin.general',
icon: 'settings_applications'
menuId: MenuId.general
}
}
},
@ -233,8 +228,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.outgoing-mail-settings',
breadcrumb: {
label: 'admin.outgoing-mail',
icon: 'mail'
menuId: MenuId.mail_server
}
}
},
@ -246,8 +240,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
title: 'admin.notifications-settings',
breadcrumb: {
label: 'admin.notifications',
icon: 'mdi:message-badge'
menuId: MenuId.notification_settings
}
}
},
@ -255,8 +248,7 @@ const routes: Routes = [
path: 'queues',
data: {
breadcrumb: {
label: 'admin.queues',
icon: 'swap_calls'
menuId: MenuId.queues
}
},
children: [
@ -297,8 +289,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'admin.home-settings',
breadcrumb: {
label: 'admin.home',
icon: 'settings_applications'
menuId: MenuId.home_settings
}
}
},
@ -310,8 +301,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'admin.repository-settings',
breadcrumb: {
label: 'admin.repository',
icon: 'manage_history'
menuId: MenuId.repository_settings
}
}
},
@ -323,8 +313,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'admin.auto-commit-settings',
breadcrumb: {
label: 'admin.auto-commit',
icon: 'settings_backup_restore'
menuId: MenuId.auto_commit_settings
}
}
},
@ -336,8 +325,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.mobile-app.mobile-app',
breadcrumb: {
label: 'admin.mobile-app.mobile-app',
icon: 'smartphone'
menuId: MenuId.mobile_app_settings
}
}
},
@ -373,8 +361,7 @@ const routes: Routes = [
data: {
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
breadcrumb: {
label: 'security.security',
icon: 'security'
menuId: MenuId.security_settings
}
},
children: [
@ -397,8 +384,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.general',
breadcrumb: {
label: 'admin.general',
icon: 'settings_applications'
menuId: MenuId.security_settings_general
}
}
},
@ -410,8 +396,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.2fa.2fa',
breadcrumb: {
label: 'admin.2fa.2fa',
icon: 'mdi:two-factor-authentication'
menuId: MenuId.two_fa
}
}
},
@ -423,8 +408,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN],
title: 'admin.oauth2.oauth2',
breadcrumb: {
label: 'admin.oauth2.oauth2',
icon: 'mdi:shield-account'
menuId: MenuId.oauth2
}
},
resolve: {

View File

@ -21,6 +21,7 @@ import { Observable } from 'rxjs';
import { OAuth2Service } from '@core/http/oauth2.service';
import { AlarmTableComponent } from '@home/components/alarm/alarm-table.component';
import { AlarmsMode } from '@shared/models/alarm.models';
import { MenuId } from '@core/services/menu.models';
@Injectable()
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> {
@ -41,8 +42,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
title: 'alarm.alarms',
breadcrumb: {
label: 'alarm.alarms',
icon: 'mdi:alert-outline'
menuId: MenuId.alarms
},
isPage: true,
alarmsMode: AlarmsMode.ALL

View File

@ -21,6 +21,7 @@ import { ApiUsageComponent } from '@home/pages/api-usage/api-usage.component';
import { Dashboard } from '@shared/models/dashboard.models';
import { ResourcesService } from '@core/services/resources.service';
import { Observable } from 'rxjs';
import { MenuId } from '@core/services/menu.models';
const apiUsageDashboardJson = '/assets/dashboard/api_usage.json';
@ -38,8 +39,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'api-usage.api-usage',
breadcrumb: {
label: 'api-usage.api-usage',
icon: 'insert_chart'
menuId: MenuId.api_usage
}
},
resolve: {

View File

@ -24,14 +24,14 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { AssetProfilesTableConfigResolver } from './asset-profiles-table-config.resolver';
import { MenuId } from '@core/services/menu.models';
export const assetProfilesRoutes: Routes = [
{
path: 'assetProfiles',
data: {
breadcrumb: {
label: 'asset-profile.asset-profiles',
icon: 'mdi:alpha-a-box'
menuId: MenuId.asset_profiles
}
},
children: [

View File

@ -24,14 +24,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { MenuId } from '@core/services/menu.models';
export const assetRoutes: Routes = [
{
path: 'assets',
data: {
breadcrumb: {
label: 'asset.assets',
icon: 'domain'
menuId: MenuId.assets
}
},
children: [

View File

@ -18,6 +18,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Authority } from '@shared/models/authority.enum';
import { AuditLogTableComponent } from '@home/components/audit-log/audit-log-table.component';
import { MenuId } from '@core/services/menu.models';
export const auditLogsRoutes: Routes = [
{
@ -27,8 +28,7 @@ export const auditLogsRoutes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'audit-log.audit-logs',
breadcrumb: {
label: 'audit-log.audit-logs',
icon: 'track_changes'
menuId: MenuId.audit_log
},
isPage: true
}

View File

@ -31,14 +31,14 @@ import { EdgesTableConfigResolver } from '@home/pages/edge/edges-table-config.re
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
path: 'customers',
data: {
breadcrumb: {
label: 'customer.customers',
icon: 'supervisor_account'
menuId: MenuId.customers
}
},
children: [

View File

@ -33,6 +33,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { MenuId } from '@core/services/menu.models';
@Injectable()
export class DashboardResolver implements Resolve<Dashboard> {
@ -66,8 +67,7 @@ const routes: Routes = [
path: 'dashboards',
data: {
breadcrumb: {
label: 'dashboard.dashboards',
icon: 'dashboard'
menuId: MenuId.dashboards
}
},
children: [

View File

@ -24,14 +24,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { MenuId } from '@core/services/menu.models';
export const deviceProfilesRoutes: Routes = [
{
path: 'deviceProfiles',
data: {
breadcrumb: {
label: 'device-profile.device-profiles',
icon: 'mdi:alpha-d-box'
menuId: MenuId.device_profiles
}
},
children: [

View File

@ -26,14 +26,14 @@ import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { assetRoutes } from '@home/pages/asset/asset-routing.module';
import { entityViewRoutes } from '@home/pages/entity-view/entity-view-routing.module';
import { MenuId } from '@core/services/menu.models';
export const deviceRoutes: Routes = [
{
path: 'devices',
data: {
breadcrumb: {
label: 'device.devices',
icon: 'devices_other'
menuId: MenuId.devices
}
},
children: [

View File

@ -41,14 +41,14 @@ import {
} from '@home/pages/rulechain/rulechain-routing.module';
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
path: 'edgeManagement',
data: {
breadcrumb: {
label: 'edge.management',
icon: 'settings_input_antenna'
menuId: MenuId.edge_management
}
},
children: [
@ -64,8 +64,7 @@ const routes: Routes = [
path: 'instances',
data: {
breadcrumb: {
label: 'edge.instances',
icon: 'router'
menuId: MenuId.edges
}
},
children: [
@ -307,8 +306,7 @@ const routes: Routes = [
path: 'ruleChains',
data: {
breadcrumb: {
label: 'edge.rulechain-templates',
icon: 'settings_ethernet'
menuId: MenuId.rulechain_templates
}
},
children: [

View File

@ -24,14 +24,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { MenuId } from '@core/services/menu.models';
export const entityViewRoutes: Routes = [
{
path: 'entityViews',
data: {
breadcrumb: {
label: 'entity-view.entity-views',
icon: 'view_quilt'
menuId: MenuId.entity_views
}
},
children: [

View File

@ -19,6 +19,7 @@ import { Authority } from '@shared/models/authority.enum';
import { NgModule } from '@angular/core';
import { otaUpdatesRoutes } from '@home/pages/ota-update/ota-update-routing.module';
import { vcRoutes } from '@home/pages/vc/vc-routing.module';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
@ -26,8 +27,7 @@ const routes: Routes = [
data: {
auth: [Authority.TENANT_ADMIN],
breadcrumb: {
label: 'feature.advanced-features',
icon: 'construction'
menuId: MenuId.features
}
},
children: [

View File

@ -34,6 +34,7 @@ import {
import { EntityKeyType } from '@shared/models/query/query.models';
import { ResourcesService } from '@core/services/resources.service';
import { isDefinedAndNotNull } from '@core/utils';
import { MenuId } from '@core/services/menu.models';
const sysAdminHomePageJson = '/assets/dashboard/sys_admin_home_page.json';
const tenantAdminHomePageJson = '/assets/dashboard/tenant_admin_home_page.json';
@ -125,8 +126,7 @@ const routes: Routes = [
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
title: 'home.home',
breadcrumb: {
label: 'home.home',
icon: 'home'
menuId: MenuId.home
}
},
resolve: {

View File

@ -28,7 +28,7 @@
<mat-grid-tile *ngFor="let place of section.places">
<a mat-raised-button color="primary" class="tb-card-button" routerLink="{{place.path}}">
<tb-icon matButtonIcon class="tb-mat-96">{{place.icon}}</tb-icon>
<span translate>{{place.name}}</span>
<span>{{place.customTranslate ? (place.name | customTranslate) : (place.name | translate)}}</span>
</a>
</mat-grid-tile>
</mat-grid-list>

View File

@ -25,6 +25,7 @@ import { RecipientTableConfigResolver } from '@home/pages/notification/recipient
import { TemplateTableConfigResolver } from '@home/pages/notification/template/template-table-config.resolver';
import { RuleTableConfigResolver } from '@home/pages/notification/rule/rule-table-config.resolver';
import { SendNotificationButtonComponent } from '@home/components/notification/send-notification-button.component';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
@ -33,8 +34,7 @@ const routes: Routes = [
data: {
auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER, Authority.SYS_ADMIN],
breadcrumb: {
label: 'notification.notification-center',
icon: 'mdi:message-badge'
menuId: MenuId.notifications_center
},
routerTabsHeaderComponent: SendNotificationButtonComponent
},
@ -54,8 +54,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER, Authority.SYS_ADMIN],
title: 'notification.inbox',
breadcrumb: {
label: 'notification.inbox',
icon: 'inbox'
menuId: MenuId.notification_inbox
}
},
resolve: {
@ -69,8 +68,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN],
title: 'notification.sent',
breadcrumb: {
label: 'notification.sent',
icon: 'outbox'
menuId: MenuId.notification_sent
}
},
resolve: {
@ -84,8 +82,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN],
title: 'notification.templates',
breadcrumb: {
label: 'notification.templates',
icon: 'mdi:message-draw'
menuId: MenuId.notification_templates
}
},
resolve: {
@ -99,8 +96,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN],
title: 'notification.recipients',
breadcrumb: {
label: 'notification.recipients',
icon: 'contacts'
menuId: MenuId.notification_recipients
},
},
resolve: {
@ -114,8 +110,7 @@ const routes: Routes = [
auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN],
title: 'notification.rules',
breadcrumb: {
label: 'notification.rules',
icon: 'mdi:message-cog'
menuId: MenuId.notification_rules
}
},
resolve: {

View File

@ -23,14 +23,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { MenuId } from '@core/services/menu.models';
export const otaUpdatesRoutes: Routes = [
{
path: 'otaUpdates',
data: {
breadcrumb: {
label: 'ota-update.ota-updates',
icon: 'memory'
menuId: MenuId.otaUpdates
}
},
children: [

View File

@ -19,6 +19,7 @@ import { Authority } from '@shared/models/authority.enum';
import { NgModule } from '@angular/core';
import { deviceProfilesRoutes } from '@home/pages/device-profile/device-profile-routing.module';
import { assetProfilesRoutes } from '@home/pages/asset-profile/asset-profile-routing.module';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
@ -26,8 +27,7 @@ const routes: Routes = [
data: {
auth: [Authority.TENANT_ADMIN],
breadcrumb: {
label: 'profiles.profiles',
icon: 'badge'
menuId: MenuId.profiles
}
},
children: [

View File

@ -39,7 +39,7 @@ import { RuleChainService } from '@core/http/rule-chain.service';
import { RuleChainPageComponent } from '@home/pages/rulechain/rulechain-page.component';
import { RuleNodeComponentDescriptor } from '@shared/models/rule-node.models';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { ItemBufferService } from '@core/public-api';
import { ItemBufferService, MenuId } from '@core/public-api';
import { MODULES_MAP } from '@shared/public-api';
import { IModulesMap } from '@modules/common/modules-map.models';
@ -127,8 +127,7 @@ const routes: Routes = [
path: 'ruleChains',
data: {
breadcrumb: {
label: 'rulechain.rulechains',
icon: 'settings_ethernet'
menuId: MenuId.rule_chains
}
},
children: [

View File

@ -24,14 +24,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
path: 'tenantProfiles',
data: {
breadcrumb: {
label: 'tenant-profile.tenant-profiles',
icon: 'mdi:alpha-t-box'
menuId: MenuId.tenant_profiles
}
},
children: [

View File

@ -25,14 +25,14 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { MenuId } from '@core/services/menu.models';
const routes: Routes = [
{
path: 'tenants',
data: {
breadcrumb: {
label: 'tenant.tenants',
icon: 'supervisor_account'
menuId: MenuId.tenants
}
},
children: [

View File

@ -19,6 +19,7 @@ import { RouterModule, Routes } from '@angular/router';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { Authority } from '@shared/models/authority.enum';
import { VersionControlComponent } from '@home/components/vc/version-control.component';
import { MenuId } from '@core/services/menu.models';
export const vcRoutes: Routes = [
{
@ -29,8 +30,7 @@ export const vcRoutes: Routes = [
auth: [Authority.TENANT_ADMIN],
title: 'version-control.version-control',
breadcrumb: {
label: 'version-control.version-control',
icon: 'history'
menuId: MenuId.version_control
}
}
}

View File

@ -33,6 +33,7 @@ import { WidgetTypesTableConfigResolver } from '@home/pages/widget/widget-types-
import { WidgetsBundleWidgetsComponent } from '@home/pages/widget/widgets-bundle-widgets.component';
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { MenuId } from '@core/services/menu.models';
export interface WidgetEditorData {
widgetTypeDetails: WidgetTypeDetails;
@ -108,8 +109,7 @@ const widgetTypesRoutes: Routes = [
path: 'widget-types',
data: {
breadcrumb: {
label: 'widget.widgets',
icon: 'now_widgets'
menuId: MenuId.widget_types
}
},
children: [
@ -157,8 +157,7 @@ const widgetsBundlesRoutes: Routes = [
path: 'widgets-bundles',
data: {
breadcrumb: {
label: 'widgets-bundle.widgets-bundles',
icon: 'now_widgets'
menuId: MenuId.widgets_bundles
}
},
children: [
@ -235,8 +234,7 @@ export const widgetsLibraryRoutes: Routes = [
data: {
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
breadcrumb: {
label: 'widget.widget-library',
icon: 'now_widgets'
menuId: MenuId.widget_library
}
},
children: [

View File

@ -17,9 +17,7 @@
-->
<div fxFlex class="tb-breadcrumb" fxLayout="row">
<h1 fxFlex fxHide.gt-sm *ngIf="lastBreadcrumb$ | async; let breadcrumb">
{{ breadcrumb.ignoreTranslate
? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : utils.customTranslation(breadcrumb.label, breadcrumb.label))
: (breadcrumb.label | translate) }}
{{ breadcrumb.labelFunction ? breadcrumb.labelFunction() : (breadcrumb.customTranslate ? (breadcrumb.label | customTranslate) : (breadcrumb.label | translate)) }}
</h1>
<span fxHide.lt-md fxLayout="row" *ngFor="let breadcrumb of breadcrumbs$ | async; trackBy: trackByBreadcrumbs; last as isLast;" [ngSwitch]="isLast">
<a *ngSwitchCase="false" [routerLink]="breadcrumb.link" [queryParams]="breadcrumb.queryParams">
@ -40,7 +38,5 @@
<tb-icon *ngIf="!breadcrumb.iconUrl">
{{ breadcrumb.icon }}
</tb-icon>
{{ breadcrumb.ignoreTranslate
? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : utils.customTranslation(breadcrumb.label, breadcrumb.label))
: (breadcrumb.label | translate) }}
{{ breadcrumb.labelFunction ? breadcrumb.labelFunction() : (breadcrumb.customTranslate ? (breadcrumb.label | customTranslate) : (breadcrumb.label | translate)) }}
</ng-template>

View File

@ -14,16 +14,18 @@
/// limitations under the License.
///
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { BehaviorSubject, Subject, Subscription } from 'rxjs';
import { BreadCrumb, BreadCrumbConfig } from './breadcrumb';
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router';
import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators';
import { distinctUntilChanged, filter, first, map, switchMap } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { guid } from '@core/utils';
import { BroadcastService } from '@core/services/broadcast.service';
import { ActiveComponentService } from '@core/services/active-component.service';
import { UtilsService } from '@core/services/utils.service';
import { MenuSection, menuSectionMap } from '@core/services/menu.models';
import { MenuService } from '@core/services/menu.service';
@Component({
selector: 'tb-breadcrumb',
@ -44,7 +46,9 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
this.activeComponentValue = activeComponent;
if (this.activeComponentValue && this.activeComponentValue.updateBreadcrumbs) {
this.updateBreadcrumbsSubscription = this.activeComponentValue.updateBreadcrumbs.subscribe(() => {
this.breadcrumbs$.next(this.buildBreadCrumbs(this.activatedRoute.snapshot));
this.menuService.availableMenuSections().pipe(first()).subscribe((sections) => {
this.breadcrumbs$.next(this.buildBreadCrumbs(this.activatedRoute.snapshot, sections));
});
});
}
}
@ -54,7 +58,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
routerEventsSubscription = this.router.events.pipe(
filter((event) => event instanceof NavigationEnd ),
distinctUntilChanged(),
map( () => this.buildBreadCrumbs(this.activatedRoute.snapshot) )
switchMap(() => this.menuService.availableMenuSections().pipe(first())),
map( (sections) => this.buildBreadCrumbs(this.activatedRoute.snapshot, sections) )
).subscribe(breadcrumns => this.breadcrumbs$.next(breadcrumns) );
activeComponentSubscription = this.activeComponentService.onActiveComponentChanged().subscribe(comp => this.setActiveComponent(comp));
@ -69,6 +74,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
private activeComponentService: ActiveComponentService,
private cd: ChangeDetectorRef,
private translate: TranslateService,
private menuService: MenuService,
public utils: UtilsService) {
}
@ -96,7 +102,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
return child;
}
buildBreadCrumbs(route: ActivatedRouteSnapshot, breadcrumbs: Array<BreadCrumb> = [],
buildBreadCrumbs(route: ActivatedRouteSnapshot, availableMenuSections: MenuSection[],
breadcrumbs: Array<BreadCrumb> = [],
lastChild?: ActivatedRouteSnapshot): Array<BreadCrumb> {
if (!lastChild) {
lastChild = this.lastChild(route);
@ -105,24 +112,27 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
if (route.routeConfig && route.routeConfig.data) {
const breadcrumbConfig = route.routeConfig.data.breadcrumb as BreadCrumbConfig<any>;
if (breadcrumbConfig && !breadcrumbConfig.skip) {
let label;
let labelFunction;
let ignoreTranslate;
let labelFunction: () => string;
let section: MenuSection = null;
if (breadcrumbConfig.menuId) {
section = availableMenuSections.find(menu => menu.id === breadcrumbConfig.menuId);
if (!section) {
section = menuSectionMap.get(breadcrumbConfig.menuId);
}
}
const label = section?.name || breadcrumbConfig.label || 'home.home';
const customTranslate = section?.customTranslate || false;
if (breadcrumbConfig.labelFunction) {
labelFunction = () => this.activeComponentValue ?
breadcrumbConfig.labelFunction(route, this.translate, this.activeComponentValue, lastChild.data) : breadcrumbConfig.label;
ignoreTranslate = true;
} else {
label = breadcrumbConfig.label || 'home.home';
ignoreTranslate = false;
breadcrumbConfig.labelFunction(route, this.translate, this.activeComponentValue, lastChild.data) : label;
}
const icon = breadcrumbConfig.icon || 'home';
const icon = section?.icon || breadcrumbConfig.icon || 'home';
const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ];
const breadcrumb = {
id: guid(),
label,
customTranslate,
labelFunction,
ignoreTranslate,
icon,
link,
queryParams: null
@ -131,12 +141,12 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
}
}
if (route.firstChild) {
return this.buildBreadCrumbs(route.firstChild, newBreadcrumbs, lastChild);
return this.buildBreadCrumbs(route.firstChild, availableMenuSections, newBreadcrumbs, lastChild);
}
return newBreadcrumbs;
}
trackByBreadcrumbs(index: number, breadcrumb: BreadCrumb){
trackByBreadcrumbs(_index: number, breadcrumb: BreadCrumb){
return breadcrumb.id;
}
}

View File

@ -17,11 +17,12 @@
import { ActivatedRouteSnapshot, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { HasUUID } from '@shared/models/id/has-uuid';
import { MenuId } from '@core/services/menu.models';
export interface BreadCrumb extends HasUUID{
label: string;
customTranslate: boolean;
labelFunction?: () => string;
ignoreTranslate: boolean;
icon: string;
link: any[];
queryParams: Params;
@ -31,7 +32,8 @@ export type BreadCrumbLabelFunction<C> = (route: ActivatedRouteSnapshot, transla
export interface BreadCrumbConfig<C> {
labelFunction: BreadCrumbLabelFunction<C>;
label: string;
icon: string;
menuId?: MenuId;
label?: string;
icon?: string;
skip: boolean;
}