From f51bd5644d1f064f355ad8d866cbc8d4808a4f82 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 23 Oct 2024 16:37:39 +0530 Subject: [PATCH 01/10] feat: add settings nav menu --- .../settings-nav-menu.component.html | 1 + .../settings-nav-menu.component.scss | 0 .../settings-nav-menu.component.ts | 24 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.html create mode 100644 packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.scss create mode 100644 packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.ts diff --git a/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.html b/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.html new file mode 100644 index 00000000000..f9bc7901699 --- /dev/null +++ b/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.html @@ -0,0 +1 @@ + diff --git a/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.scss b/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.ts b/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.ts new file mode 100644 index 00000000000..153361b7698 --- /dev/null +++ b/packages/ui-core/core/src/lib/components/settings-nav-menu/settings-nav-menu.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit } from '@angular/core'; +import { Observable, map } from 'rxjs'; +import { NavMenuSectionItem } from '../../services/nav-builder/nav-builder-types'; +import { BaseNavMenuComponent } from '../base-nav-menu/base-nav-menu.component'; + +@Component({ + selector: 'ga-settings-nav-menu', + templateUrl: './settings-nav-menu.component.html', + styleUrls: ['./settings-nav-menu.component.scss'] +}) +export class SettingsNavMenuComponent extends BaseNavMenuComponent implements OnInit { + public settingsMenuConfig$: Observable; + + override ngOnInit(): void { + super.ngOnInit(); // Call the parent class's ngOnInit function + + // Subscribe to the menuConfig$ observable provided by _navMenuBuilderService + this.settingsMenuConfig$ = this._navMenuBuilderService.menuConfig$.pipe( + map((sections: NavMenuSectionItem[]) => + this.mapMenuSections(sections).filter((s) => s.menuCategory === 'settings') + ) + ); + } +} From 7076fcd0d5f24a3c6d53664269fa5e667157b1bf Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 23 Oct 2024 17:01:45 +0530 Subject: [PATCH 02/10] fix: prettier formatting --- .../server/src/assets/styles/gauzy/_gauzy-dialogs.scss | 2 +- apps/server/src/assets/styles/gauzy/_gauzy-table.scss | 2 +- apps/server/src/assets/styles/gauzy/index.ts | 2 +- .../server/src/assets/styles/gauzy/theme.gauzy-dark.ts | 10 ++-------- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/apps/server/src/assets/styles/gauzy/_gauzy-dialogs.scss b/apps/server/src/assets/styles/gauzy/_gauzy-dialogs.scss index b5c00201c50..b3b2a2c797b 100644 --- a/apps/server/src/assets/styles/gauzy/_gauzy-dialogs.scss +++ b/apps/server/src/assets/styles/gauzy/_gauzy-dialogs.scss @@ -113,4 +113,4 @@ $shadow: 0 0 0 nb-theme(button-outline-width) rgba($color: $green, } @include dialog(var(--gauzy-card-1), var(--gauzy-sidebar-background-4)); -} \ No newline at end of file +} diff --git a/apps/server/src/assets/styles/gauzy/_gauzy-table.scss b/apps/server/src/assets/styles/gauzy/_gauzy-table.scss index ad4334cda60..a66381765ad 100644 --- a/apps/server/src/assets/styles/gauzy/_gauzy-table.scss +++ b/apps/server/src/assets/styles/gauzy/_gauzy-table.scss @@ -110,4 +110,4 @@ button { border-radius: nb-theme(border-radius); box-shadow: var(--gauzy-shadow) inset; } -} \ No newline at end of file +} diff --git a/apps/server/src/assets/styles/gauzy/index.ts b/apps/server/src/assets/styles/gauzy/index.ts index 178f1f36dbc..368e51a156c 100644 --- a/apps/server/src/assets/styles/gauzy/index.ts +++ b/apps/server/src/assets/styles/gauzy/index.ts @@ -1,2 +1,2 @@ export * from './theme.gauzy-dark'; -export * from './theme.gauzy-light'; \ No newline at end of file +export * from './theme.gauzy-light'; diff --git a/apps/server/src/assets/styles/gauzy/theme.gauzy-dark.ts b/apps/server/src/assets/styles/gauzy/theme.gauzy-dark.ts index 4ec88895401..698f56a65a1 100644 --- a/apps/server/src/assets/styles/gauzy/theme.gauzy-dark.ts +++ b/apps/server/src/assets/styles/gauzy/theme.gauzy-dark.ts @@ -45,18 +45,12 @@ const theme = { export const GAUZY_DARK = { name: 'gauzy-dark', - base: 'dark', + base: 'dark', variables: { ...theme, temperature: { - arcFill: [ - theme.primary, - theme.primary, - theme.primary, - theme.primary, - theme.primary - ], + arcFill: [theme.primary, theme.primary, theme.primary, theme.primary, theme.primary], arcEmpty: theme.bg2, thumbBg: theme.bg2, thumbBorder: theme.primary From 72b2cf8aace7a9aacf9adc34e63f119a3f66e6d1 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 23 Oct 2024 17:05:55 +0530 Subject: [PATCH 03/10] feat: registered settings menu into base nan menu component --- .../base-nav-menu/base-nav-menu.component.ts | 221 +++++++++++++++++- .../src/lib/components/common-nav.module.ts | 14 +- 2 files changed, 225 insertions(+), 10 deletions(-) diff --git a/packages/ui-core/core/src/lib/components/base-nav-menu/base-nav-menu.component.ts b/packages/ui-core/core/src/lib/components/base-nav-menu/base-nav-menu.component.ts index 2c34b3ad464..00ccaa192c4 100644 --- a/packages/ui-core/core/src/lib/components/base-nav-menu/base-nav-menu.component.ts +++ b/packages/ui-core/core/src/lib/components/base-nav-menu/base-nav-menu.component.ts @@ -46,6 +46,18 @@ export class BaseNavMenuComponent extends TranslationBaseComponent implements On */ private defineBaseNavMenus() { this._navMenuBuilderService.defineNavMenuSections([ + ...this._getMainMenu(), + ...this._getAccordionMenu(), + ...this._getSettingsMenu() + ]); + } + + /** + * Retrieves the main navigation menu configuration. + * @returns An array of NavMenuSectionItem objects representing the main menu. + */ + private _getMainMenu(): NavMenuSectionItem[] { + return [ { id: 'dashboards', title: 'Dashboards', @@ -877,7 +889,214 @@ export class BaseNavMenuComponent extends TranslationBaseComponent implements On } ] } - ]); + ]; + } + + /** + * Retrieves the accordion menu configuration based on user permissions. + * Each menu item includes an ID, title, icon, link, and additional data such as translation keys, + * permission keys, and feature keys. + * + * @returns An array of NavMenuSectionItem objects representing the accordion menu. + */ + private _getAccordionMenu(): NavMenuSectionItem[] { + return [ + { + id: 'invite-people', + title: 'Invite people', + icon: 'fas fa-user-plus', + link: '/pages/employees/invites', + menuCategory: 'accordion', + data: { + translationKey: 'MENU.INVITE_PEOPLE', + permissionKeys: [PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_INVITE_VIEW], + featureKey: FeatureEnum.FEATURE_MANAGE_INVITE + } + }, + { + id: 'users', + title: 'Users', + icon: 'fas fa-users', + link: '/pages/users', + menuCategory: 'accordion', + data: { + translationKey: 'MENU.USERS', + permissionKeys: [PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_USERS_VIEW], + featureKey: FeatureEnum.FEATURE_USER + } + }, + { + id: 'import-export', + title: 'Import/Export', + icon: 'fas fa-exchange-alt', + link: '/pages/settings/import-export', + menuCategory: 'accordion', + data: { + translationKey: 'MENU.IMPORT_EXPORT.IMPORT_EXPORT', + permissionKeys: [ + PermissionsEnum.ALL_ORG_VIEW, + PermissionsEnum.IMPORT_ADD, + PermissionsEnum.EXPORT_ADD + ], + featureKey: FeatureEnum.FEATURE_IMPORT_EXPORT + } + }, + { + id: 'organizations', + title: 'Organizations', + icon: 'fas fa-globe', + link: '/pages/organizations', + menuCategory: 'accordion', + data: { + translationKey: 'MENU.ORGANIZATIONS', + permissionKeys: [PermissionsEnum.ALL_ORG_VIEW, PermissionsEnum.ORG_EXPENSES_EDIT], + featureKey: FeatureEnum.FEATURE_ORGANIZATIONS + } + }, + { + id: 'integrations', + title: 'Integrations', + icon: 'fas fa-swatchbook', + link: '/pages/integrations', + menuCategory: 'accordion', + pathMatch: 'prefix', + data: { + translationKey: 'MENU.INTEGRATIONS', + permissionKeys: [PermissionsEnum.INTEGRATION_ADD, PermissionsEnum.INTEGRATION_EDIT], + featureKey: FeatureEnum.FEATURE_APP_INTEGRATION + } + } + ]; + } + + /** + * Retrieves the settings menu configuration. + * + * @returns An array containing a single NavMenuSectionItem for settings. + */ + private _getSettingsMenu(): NavMenuSectionItem[] { + return [ + { + id: 'settings', + title: 'Settings', + icon: 'fas fa-cog', + menuCategory: 'settings', + data: { + translationKey: 'MENU.SETTINGS' + }, + items: [ + { + id: 'settings-general', + title: 'General', + icon: 'fas fa-pen', + link: '/pages/settings/general', + data: { + translationKey: 'MENU.GENERAL', + featureKey: FeatureEnum.FEATURE_SETTING + } + }, + { + id: 'settings-features', + title: 'Features', + icon: 'fas fa-swatchbook', + link: '/pages/settings/features', + data: { + translationKey: 'MENU.FEATURES', + permissionKeys: [PermissionsEnum.ALL_ORG_EDIT, PermissionsEnum.ALL_ORG_VIEW] + } + }, + { + id: 'settings-email-history', + title: 'Email History', + icon: 'fas fa-envelope-open', + link: '/pages/settings/email-history', + data: { + translationKey: 'MENU.EMAIL_HISTORY', + permissionKeys: [PermissionsEnum.VIEW_ALL_EMAILS], + featureKey: FeatureEnum.FEATURE_EMAIL_HISTORY + } + }, + { + id: 'settings-email-templates', + title: 'Email Templates', + icon: 'fas fa-envelope', + link: '/pages/settings/email-templates', + data: { + translationKey: 'MENU.EMAIL_TEMPLATES', + permissionKeys: [PermissionsEnum.VIEW_ALL_EMAIL_TEMPLATES], + featureKey: FeatureEnum.FEATURE_EMAIL_TEMPLATE + } + }, + { + id: 'settings-accounting-templates', + title: 'Accounting Templates', + icon: 'fas fa-address-card', + link: '/pages/settings/accounting-templates', + data: { + translationKey: 'MENU.ACCOUNTING_TEMPLATES', + permissionKeys: [PermissionsEnum.VIEW_ALL_ACCOUNTING_TEMPLATES] + } + }, + { + id: 'settings-file-storage', + title: 'File storage', + icon: 'fas fa-database', + link: '/pages/settings/file-storage', + data: { + translationKey: 'MENU.FILE_STORAGE', + permissionKeys: [PermissionsEnum.FILE_STORAGE_VIEW], + featureKey: FeatureEnum.FEATURE_FILE_STORAGE + } + }, + { + id: 'settings-sms-gateways', + title: 'SMS Gateways', + icon: 'fas fa-at', + link: '/pages/settings/sms-gateway', + data: { + translationKey: 'MENU.SMS_GATEWAYS', + permissionKeys: [PermissionsEnum.SMS_GATEWAY_VIEW], + featureKey: FeatureEnum.FEATURE_SMS_GATEWAY + } + }, + { + id: 'settings-custom-smtp', + title: 'Custom SMTP', + icon: 'fas fa-at', + link: '/pages/settings/custom-smtp', + data: { + translationKey: 'MENU.CUSTOM_SMTP', + permissionKeys: [PermissionsEnum.CUSTOM_SMTP_VIEW], + featureKey: FeatureEnum.FEATURE_SMTP + } + }, + { + id: 'settings-roles-permissions', + title: 'Roles & Permissions', + link: '/pages/settings/roles-permissions', + icon: 'fas fa-award', + data: { + translationKey: 'MENU.ROLES', + permissionKeys: [PermissionsEnum.CHANGE_ROLES_PERMISSIONS], + featureKey: FeatureEnum.FEATURE_ROLES_PERMISSION + } + }, + { + id: 'settings-danger-zone', + title: 'Danger Zone', + link: '/pages/settings/danger-zone', + icon: 'fas fa-radiation-alt', + data: { + translationKey: 'MENU.DANGER_ZONE', + permissionKeys: [ + PermissionsEnum.ACCESS_DELETE_ACCOUNT, + PermissionsEnum.ACCESS_DELETE_ALL_DATA + ] + } + } + ] + } + ]; } /** diff --git a/packages/ui-core/core/src/lib/components/common-nav.module.ts b/packages/ui-core/core/src/lib/components/common-nav.module.ts index f4f7956118b..f49ff65e6c2 100644 --- a/packages/ui-core/core/src/lib/components/common-nav.module.ts +++ b/packages/ui-core/core/src/lib/components/common-nav.module.ts @@ -4,18 +4,14 @@ import { NgxPermissionsModule } from 'ngx-permissions'; import { NbAccordionModule, NbButtonModule, NbTooltipModule } from '@nebular/theme'; import { BaseNavMenuComponent } from './base-nav-menu/base-nav-menu.component'; import { MainNavMenuComponent } from './main-nav-menu/main-nav-menu.component'; +import { SettingsNavMenuComponent } from './settings-nav-menu/settings-nav-menu.component'; import { MenuItemComponent, SidebarMenuComponent, ChildrenMenuItemComponent, TooltipDirective } from './sidebar-menu'; +const COMPONENTS = [BaseNavMenuComponent, MainNavMenuComponent, SidebarMenuComponent, SettingsNavMenuComponent]; + @NgModule({ - declarations: [ - BaseNavMenuComponent, - MainNavMenuComponent, - SidebarMenuComponent, - MenuItemComponent, - ChildrenMenuItemComponent, - TooltipDirective - ], imports: [CommonModule, NbAccordionModule, NbTooltipModule, NbButtonModule, NgxPermissionsModule.forChild()], - exports: [BaseNavMenuComponent, MainNavMenuComponent, SidebarMenuComponent] + declarations: [...COMPONENTS, MenuItemComponent, ChildrenMenuItemComponent, TooltipDirective], + exports: [...COMPONENTS] }) export class CommonNavModule {} From bfb62a25df595a719b49443e6b351b0ee8910881 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 23 Oct 2024 17:11:45 +0530 Subject: [PATCH 04/10] fix: missing translation for bg.json --- packages/ui-core/i18n/assets/i18n/bg.json | 171 ++++++++++++---------- 1 file changed, 94 insertions(+), 77 deletions(-) diff --git a/packages/ui-core/i18n/assets/i18n/bg.json b/packages/ui-core/i18n/assets/i18n/bg.json index 65118a4ddf2..222b4e8d9c2 100644 --- a/packages/ui-core/i18n/assets/i18n/bg.json +++ b/packages/ui-core/i18n/assets/i18n/bg.json @@ -178,45 +178,45 @@ }, "SM_TABLE": { "NO_DATA": { - "LOADING": "Зареждане, моля, изчакайте...", + "LOADING": "Зареждане, моля изчакайте...", "RECEIVE_ESTIMATE": "Не сте получили никакви оценки.", - "INCOME": "Не сте създали никакви доходи.", + "INCOME": "Не сте създали никакви приходи.", "EXPENSE_CATEGORY": "Не сте създали никакви категории разходи.", "REPORT": "Не сте създали никакви отчети.", "CONTRACT": "Не сте създали никакви договори.", "TEAM": "Не сте създали никакви екипи.", "HISTORY_RECORD": "Не сте създали никакви записи.", - "PROFIT_HISTORY": "Не сте създали никаква история на печалбата.", + "PROFIT_HISTORY": "Не сте създали никаква история на печалбите.", "EMPLOYEE": "Не сте създали никакви служители.", "EXPENSE": "Не сте създали никакви разходи.", "PAYMENT": "Не сте получили никакви плащания.", "PROPOSAL_TEMPLATE": "Не сте създали никакви шаблони за предложения.", "PROPOSAL": "Не сте създали никакви предложения.", - "PIPELINE": "Не сте създали никакви тръбопроводи.", + "PIPELINE": "Не сте създали никакви канали.", "TASK": "Не сте създали никакви задачи.", "INVITE": "Не сте поканили никакви потребители.", "APPROVAL_REQUEST": "Не сте създали никакви заявки за одобрение.", "APPROVAL_POLICY": "Не сте създали никакви политики за одобрение.", - "TIME_OFF": "Не сте създали никакво време за отпуск.", - "TIME_OFF_POLICY": "Не сте създали политики за отпуск.", + "TIME_OFF": "Не сте създали никакви отпуски.", + "TIME_OFF_POLICY": "Не сте създали никакви политики за отпуск.", "CANDIDATE": "Не сте създали никакви кандидати.", "INTERVIEW": "Не сте създали никакви интервюта.", "EQUIPMENT": "Не сте създали никакво оборудване.", "EQUIPMENT_SHARING": "Не сте създали никакви записи за споделяне на оборудване.", "EQUIPMENT_SHARING_POLICY": "Не сте създали никакви политики за споделяне на оборудване.", - "INVENTORY": "Не сте създали никакви инвентари.", + "INVENTORY": "Не сте създали никакви инвентаризации.", "MERCHANT": "Не сте създали никакви търговци.", "WAREHOUSE": "Не сте създали никакви складове.", - "WAREHOUSE_PRODUCT": "Не сте създали никакви складови продукти.", - "PRODUCT_CATEGORY": "Не сте създали никакви категории продукти.", + "WAREHOUSE_PRODUCT": "Не сте създали никакви продукти за склад.", + "PRODUCT_CATEGORY": "Не сте създали никакви продуктови категории.", "TAGS": "Не сте създали никакви етикети.", "PROJECT": "Не сте създали никакви проекти.", "DEPARTMENT": "Не сте създали никакви отдели.", "CONTACT": "Не сте създали никакви контакти.", "CLIENT": "Не сте създали никакви клиенти.", "LEAD": "Не сте създали никакви потенциални клиенти.", - "TIME_FRAME": "Не сте създали никакви времеви периоди.", - "KPI": "Не сте създали никакви КПИ.", + "TIME_FRAME": "Не сте създали никакви времеви рамки.", + "KPI": "Не сте създали никакви KPI.", "INVOICE": "Не сте създали никакви фактури.", "ESTIMATE": "Не сте създали никакви оценки.", "EVENT_TYPE": "Не сте създали никакви типове събития.", @@ -229,10 +229,10 @@ "DATE": "Дата", "TITLE": "Заглавие", "STAGE": "Етап", - "START_DATE": "Начална дата", - "END_DATE": "Крайна дата", - "CLIENT_NAME": "Клиентско име", - "CONTACT_NAME": "Име на контакт", + "START_DATE": "Начална Дата", + "END_DATE": "Крайна Дата", + "CLIENT_NAME": "Име на Клиента", + "CONTACT_NAME": "Име на Контакта", "NAME": "Име", "VENDOR": "Доставчик", "CATEGORY": "Категория", @@ -241,26 +241,25 @@ "NOTES": "Бележки", "EMPLOYEE": "Служител", "EMPLOYEES": "Служители", - "FULL_NAME": "Пълно име", - "EMAIL": "Електронна поща", - "INCOME": "Доход (Средно)", + "FULL_NAME": "Пълно Име", + "EMAIL": "Имейл", + "INCOME": "Приходи (Средно)", "EXPENSES": "Разходи (Средно)", "BONUS": "Бонус", "BONUS_AVG": "Бонус (Средно)", - "PROFIT_BASED_BONUS": "Бонус въз основа на печалбата", - "REVENUE_BASED_BONUS": "Бонус въз основа на приходите", + "PROFIT_BASED_BONUS": "Бонус на база печалба", + "REVENUE_BASED_BONUS": "Бонус на база приходи", "STATUS": "Статус", "SOURCE": "Източник", - "WORK_STATUS": "Работен статус", "TODAY": "Днес", - "END_OF_MONTH": "Края на месеца", - "START_OF_MONTH": "Началото на месеца", - "RATE": "Почасова ставка", - "FLAT_FEE": "Фиксирана такса", - "MILESTONES": "Етапи", - "JOB_TITLE": "Заглавие на работа", - "JOB_POST_URL": "URL на работната обява", - "LINK_TO_JOBPOST": "Връзка към работната обява", + "END_OF_MONTH": "Край на Месеца", + "START_OF_MONTH": "Начало на Месеца", + "RATE": "Ставка", + "FLAT_FEE": "Фиксирана Такса", + "MILESTONES": "Милстоунове", + "JOB_TITLE": "Заглавие на Работата", + "JOB_POST_URL": "URL на Работното Обявление", + "LINK_TO_JOBPOST": "Връзка към Работното Обявление", "AUTHOR": "Автор", "MONDAY": "Понеделник", "TUESDAY": "Вторник", @@ -269,12 +268,12 @@ "FRIDAY": "Петък", "SATURDAY": "Събота", "SUNDAY": "Неделя", - "NONE": "Нито един", + "NONE": "Няма", "ROLE": "Роля", "PROJECTS": "Проекти", "PROJECT": "Проект", "INVITED_BY": "Поканен от", - "EXPIRE_DATE": "Дата на изтичане", + "EXPIRE_DATE": "Изтича на", "CLIENTS": "Клиенти", "CONTACTS": "Контакти", "CONTACT": "Контакт", @@ -284,12 +283,12 @@ "APPLIED": "Кандидатствал", "HIRED": "Нает", "REJECTED": "Отхвърлен", - "NO_RESULT": "Няма резултат", + "NO_RESULT": "Няма Резултат", "CLIENT": "Клиент", "INTERNAL": "Вътрешен", "START": "Начало", "END": "Край", - "REQUEST_DATE": "Дата на заявка", + "REQUEST_DATE": "Дата на Заявка", "REGION": { "BG": "Български (България)", "EN": "English (United States)", @@ -307,16 +306,28 @@ }, "CURRENT_VALUE": "Текуща стойност", "TARGET_VALUE": "Целева стойност", - "LAST_UPDATED": "Последна актуализация", + "LAST_UPDATED": "Последно обновено", + "LAST_SYNC_DATE": "Дата на последна синхронизация", "CREATED_BY": "Създадено от", "NO_DATA_MESSAGE": "Няма данни", "TAGS": "Тагове", + "LABELS": "Етикети", "CREATED": "Създадено", "APPLIED_DATE": "Дата на кандидатстване", "HIRED_DATE": "Дата на наемане", "REJECTED_DATE": "Дата на отхвърляне", "TIME_TRACKING": "Проследяване на време", - "CREATED_AT": "Създадено на" + "CREATED_AT": "Създадено на", + "SCREEN_CAPTURE": "Заснемане на екрана", + "NUMBER": "Номер", + "PROVIDER": "Доставчик", + "GITHUB_REPOSITORY": "GitHub Репозитори", + "ISSUES_SYNC": "Синхронизиране на проблеми", + "ISSUES_SYNC_COUNT": "{{ count }} Проблеми синхронизирани", + "RESYNC_ISSUES": "Повторна синхронизация на проблеми", + "ENABLED_DISABLED_SYNC": "Активирана / Деактивирана синхронизация", + "ENABLE_DISABLE_INTEGRATION": "Активиране / Деактивиране на интеграция", + "ACTIONS": "Действия" }, "FORM": { "USERNAME": "Потребителско име", @@ -1210,46 +1221,49 @@ "STANDARD_WORK_HOURS": "Стандартни работни часове ({{hours}})" }, "INTEGRATIONS": { + "TITLE": "Интеграции", "AVAILABLE_INTEGRATIONS": "Налични приложения и интеграции", - "ADDED_UPWORK_TRANSACTION": "Добавена транзакция от Upwork", - "TOTAL_UPWORK_TRANSACTIONS_SUCCEED": "Общо успешни транзакции за разходи: {{ totalExpenses }}. Общо успешни транзакции за приходи: {{ totalIncomes }}", + "ADDED_UPWORK_TRANSACTION": "Добавена Upwork транзакция", + "TOTAL_UPWORK_TRANSACTIONS_SUCCEED": "Общо успешни разходни транзакции: {{ totalExpenses }}. Общо успешни приходи транзакции: {{ totalIncomes }}", "HUBSTAFF_PAGE": { "TITLE": "Hubstaff", "SELECT_ORGANIZATION": "Изберете организация", "SYNCED_PROJECTS": "Синхронизирани проекти", - "SETTINGS_UPDATED": "Актуализирани настройки за интеграция", - "SYNCED_ENTITIES": "Автоматично синхронизирани единици", - "TOOLTIP_ACTIVITY_INFO": "Ограничение на периода: 7 дни Най-ранна дата: 6 пълни месеца", + "SETTINGS_UPDATED": "Настройките за интеграцията са актуализирани", + "SYNCED_ENTITIES": "Автоматично синхронизирани обекти", + "TOOLTIP_ACTIVITY_INFO": "Ограничение на обхвата на датите: 7 дни Най-ранна дата: 6 пълни месеца", "DATE_RANGE_PLACEHOLDER": "Изберете дата между", "CLIENT_ID": "Hubstaff клиентски идентификатор", - "CLIENT_SECRET": "Hubstaff клиентска тайна", - "GRANT_PERMISSION": "След това ще бъдете пренасочени към Hubstaff, за да предоставите разрешение на Gauzy.", - "ENTER_CLIENT_SECRET": "Въведете клиентския тайния ключ, за да получите достъп до токен." + "CLIENT_SECRET": "Hubstaff клиентски таен ключ", + "GRANT_PERMISSION": "Следващата стъпка е да бъдете прехвърлени в Hubstaff за предоставяне на разрешение на Gauzy.", + "ENTER_CLIENT_SECRET": "Въведете таен ключ, за да получите достъп до токен.", + "DESCRIPTION": "Активирайте Hubstaff интеграцията за подобрено управление на работната сила." }, "UPWORK_PAGE": { - "ACTIVITIES": "Активности", - "REPORTS": "Доклади", + "ACTIVITIES": "Дейности", + "REPORTS": "Отчети", "TRANSACTIONS": "Транзакции", - "SUCCESSFULLY_AUTHORIZED": "Успешно упълномощен", + "SUCCESSFULLY_AUTHORIZED": "Успешно оторизиран", "API_KEY": "Upwork API ключ", "SECRET": "Upwork таен ключ", - "NEXT_STEP_INFO": "След това ще бъдете пренасочени към Upwork, за да предоставите разрешение на Gauzy.", + "NEXT_STEP_INFO": "Следващата стъпка е да бъдете прехвърлени в Upwork за предоставяне на разрешение на Gauzy.", "CONTRACTS": "Договори", "SYNCED_CONTRACTS": "Синхронизирани договори", "SELECT_DATE": "Изберете дата", "ONLY_CONTRACTS": "Само договори", - "CONTRACTS_RELATED_DATA": "Синхронизирани данни, свързани с договори", + "CONTRACTS_RELATED_DATA": "Синхронизирани обекти, свързани с договори", "DATE_RANGE_PLACEHOLDER": "Изберете дата между", - "HOURLY": "Часов" + "HOURLY": "По час", + "DESCRIPTION": "Активирайте Upwork интеграцията за управление на фрийланс работна сила." }, "GAUZY_AI_PAGE": { - "TITLE": "Интеграция на Gauzy AI", + "TITLE": "Gauzy AI Интеграция", "API_KEY": "Gauzy AI ключ", "API_SECRET": "Gauzy AI таен ключ", - "OPEN_AI_API_SECRET_KEY": "Тайният ключ на OpenAI", - "OPEN_AI_ORGANIZATION_ID": "ID на OpenAI организация", - "DESCRIPTION": "Активирайте интеграцията с Gauzy AI за по-интелигентно търсене на работа.", - "CONSUMER_KEYS": "Потребителски ключове", + "OPEN_AI_API_SECRET_KEY": "Open AI таен ключ", + "OPEN_AI_ORGANIZATION_ID": "Open AI идентификатор на организация", + "DESCRIPTION": "Активирайте Gauzy AI интеграцията за по-умно търсене на работа.", + "CONSUMER_KEYS": "Ключове на потребители", "OPEN_AI_API_KEYS": "Open AI API ключове", "GENERATED": "Генерирани", "TAB": { @@ -1257,43 +1271,46 @@ "SETTINGS": "Настройки" }, "TOOLTIP": { - "API_KEY": "API ключът служи като идентификатор на вашето приложение за API заявки, оставайки постоянно скрит с някои видими символи.", - "API_SECRET": "API тайният ключ служи като идентификатор на вашето приложение за API заявки, оставайки постоянно скрит с някои видими символи.", - "OPEN_AI_API_SECRET_KEY": "Тайният API ключ на OpenAI служи като идентификатор на вашето приложение за API заявки, оставайки постоянно скрит с някои видими символи.", - "OPEN_AI_ORGANIZATION_ID": "Незадължителен идентификатор за организационни цели при взаимодействие с OpenAI API. Помага за организиране и разграничаване на различни обекти или проекти във вашата организация.", - "ENABLE_JOBS_SEARCH_MATCHING_ANALYSIS": "Активира разширен анализ на търсенето на работа и съвпадение за по-голяма точност. При изключване скрива пунктовете 'Преглед' и 'Съвпадение' за по-лесен интерфейс.", - "ENABLE_EMPLOYEE_PERFORMANCE_ANALYSIS": "Управлява предаването на метрики за работата на служителите, включително клавишни въвеждания, движения на мишката и снимки на екрана, за анализ от Gauzy AI. Включването позволява изчерпателен анализ на производителността. При изключване Gauzy AI няма да получава и анализира снимки или други подробни данни, за да гарантира строга конфиденциалност и контрол върху споделянето на данни." + "API_KEY": "API ключът служи като идентификатор на вашето приложение за API заявки и остава скрит, с видими само някои символи.", + "API_SECRET": "API тайният ключ служи като идентификатор на вашето приложение за API заявки и остава скрит, с видими само някои символи.", + "OPEN_AI_API_SECRET_KEY": "OpenAI API тайният ключ служи като идентификатор на вашето приложение за API заявки и остава скрит, с видими само някои символи.", + "OPEN_AI_ORGANIZATION_ID": "Незадължителен идентификатор за организационни цели при взаимодействие с OpenAI API. Той помага за организиране и разграничаване на различни обекти или проекти във вашата организация.", + "ENABLE_JOBS_SEARCH_MATCHING_ANALYSIS": "Активира анализ на търсенето и съвпадението на работни места за по-голяма точност. Деактивирането скрива елементите от менюто 'Browse' и 'Matching' за по-опростен интерфейс.", + "ENABLE_EMPLOYEE_PERFORMANCE_ANALYSIS": "Управлява предаването на работните метрики на служителите, включително клавиатурни въведения, движения на мишката и екранни снимки, за анализ от Gauzy AI. Активирайте за всеобхватен анализ на ефективността; деактивирайте за строга поверителност и контрол на данните." + }, + "MESSAGE": { + "JOBS_SEARCH_MATCHING_ENABLED": "Анализът на търсенето и съвпадението на работни места е активиран." } }, "GITHUB_PAGE": { - "TITLE": "GitHub Интеграция", - "AUTO_SYNC_TABLE_LABEL": "Синхронизиране на GitHub репозитории и проекти", - "SELECT_REPOSITORY": "Изберете репозитория", - "SEARCH_REPOSITORY": "Напишете, за да търсите репозитория", - "SYNCED_ISSUES": "'{{repository}}' проблеми и етикети успешно синхронизирани", - "HAS_SYNCED_ENABLED": "'{{repository}}' синхронизация успешно активирана", - "HAS_SYNCED_DISABLED": "'{{repository}}' синхронизация успешно деактивирана", - "DESCRIPTION": "Активирайте интеграцията с GitHub за синхронизиране на проекти и репозитории.", + "TITLE": "Интеграция с GitHub", + "AUTO_SYNC_TABLE_LABEL": "Синхронизиране на GitHub хранилища и проекти", + "SELECT_REPOSITORY": "Изберете хранилище", + "SEARCH_REPOSITORY": "Въведете за търсене на хранилище", + "SYNCED_ISSUES": "Задачи и етикети на '{{repository}}' синхронизирани успешно", + "HAS_SYNCED_ENABLED": "Синхронизацията на '{{repository}}' е успешно активирана", + "HAS_SYNCED_DISABLED": "Синхронизацията на '{{repository}}' е успешно деактивирана", + "DESCRIPTION": "Активирайте GitHub интеграцията за синхронизация на проекти и хранилища.", "TAB": { - "AUTO_SYNC": "Автоматична синхронизация", + "AUTO_SYNC": "Авто синхронизация", "MANUAL_SYNC": "Ръчна синхронизация" } }, - "COMING_SOON": "Скоро", - "RE_INTEGRATE": "Реинтеграция", + "COMING_SOON": "Очаквайте скоро", + "RE_INTEGRATE": "Повторно интегриране", "SETTINGS": "Настройки", "SELECT_GROUPS": "Изберете групи", - "FILTER_INTEGRATIONS": "Филтрирай интеграции", + "FILTER_INTEGRATIONS": "Филтриране на интеграции", "SEARCH_INTEGRATIONS": "Търсене на интеграции", "PAID": "Платено", "INTEGRATION": "Интеграция", "MESSAGE": { - "SETTINGS_UPDATED": "Актуализирани настройки за интеграция '{{provider}}'", - "INTEGRATION_DELETED": "Интеграция '{{provider}}' успешно изтрита", + "SETTINGS_UPDATED": "Настройките за интеграцията с '{{provider}}' бяха актуализирани", + "INTEGRATION_DELETED": "Интеграцията с '{{provider}}' беше успешно изтрита", "NO_INTEGRATIONS": "Не сте конфигурирали никакви интеграции", - "INTEGRATION_ENABLED": "Интеграция '{{provider}}' успешно активирана", - "INTEGRATION_DISABLED": "Интеграция '{{provider}}' успешно деактивирана", - "INTEGRATION_ADDED": "Интеграция '{{provider}}' е добавена към '{{organization}}'" + "INTEGRATION_ENABLED": "Интеграцията с '{{provider}}' беше успешно активирана", + "INTEGRATION_DISABLED": "Интеграцията с '{{provider}}' беше успешно деактивирана", + "INTEGRATION_ADDED": "Интеграцията с '{{provider}}' беше добавена към '{{organization}}'" }, "ENABLED": "Активирано", "DISABLED": "Деактивирано" From a222b27da56a440da26c35dc021fb090fe987cdf Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 23 Oct 2024 17:31:37 +0530 Subject: [PATCH 05/10] feat: add dynamic menus for settings/accordion --- .../main-nav-menu/main-nav-menu.component.ts | 14 +- .../menu-item/menu-item.component.html | 11 +- .../interface/menu-item.interface.ts | 1 + .../sidebar-menu/sidebar-menu.component.html | 1 + .../services/nav-builder/nav-builder-types.ts | 40 +-- .../nav-builder/nav-menu-builder.service.ts | 29 +-- .../gauzy-logo/gauzy-logo.component.html | 23 +- .../gauzy-logo/gauzy-logo.component.ts | 235 ++++-------------- 8 files changed, 123 insertions(+), 231 deletions(-) diff --git a/packages/ui-core/core/src/lib/components/main-nav-menu/main-nav-menu.component.ts b/packages/ui-core/core/src/lib/components/main-nav-menu/main-nav-menu.component.ts index b9f2641b18e..3e93f0c515a 100644 --- a/packages/ui-core/core/src/lib/components/main-nav-menu/main-nav-menu.component.ts +++ b/packages/ui-core/core/src/lib/components/main-nav-menu/main-nav-menu.component.ts @@ -1,7 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { NavMenuSectionItem } from '../../services/nav-builder/nav-builder-types'; +import { NavMenuCategory, NavMenuSectionItem } from '../../services/nav-builder/nav-builder-types'; import { BaseNavMenuComponent } from '../base-nav-menu/base-nav-menu.component'; @Component({ @@ -10,6 +10,10 @@ import { BaseNavMenuComponent } from '../base-nav-menu/base-nav-menu.component'; styleUrls: ['./main-nav-menu.component.scss'] }) export class MainNavMenuComponent extends BaseNavMenuComponent implements OnInit { + // Define the input property menuCategory of type NavMenuCategory | undefined + @Input() menuCategory: NavMenuCategory | undefined; + + // Define the observable property menuConfig$ of type Observable public mainMenuConfig$: Observable; override ngOnInit(): void { @@ -17,7 +21,11 @@ export class MainNavMenuComponent extends BaseNavMenuComponent implements OnInit // Subscribe to the menuConfig$ observable provided by _navMenuBuilderService this.mainMenuConfig$ = this._navMenuBuilderService.menuConfig$.pipe( - map((sections: NavMenuSectionItem[]) => this.mapMenuSections(sections)) + map((sections: NavMenuSectionItem[]) => + this.mapMenuSections(sections).filter((section) => + this.menuCategory ? section.menuCategory === this.menuCategory : !section.menuCategory + ) + ) ); } } diff --git a/packages/ui-core/core/src/lib/components/sidebar-menu/menu-items/concrete/menu-item/menu-item.component.html b/packages/ui-core/core/src/lib/components/sidebar-menu/menu-items/concrete/menu-item/menu-item.component.html index df94aca76cc..9674e3e1880 100644 --- a/packages/ui-core/core/src/lib/components/sidebar-menu/menu-items/concrete/menu-item/menu-item.component.html +++ b/packages/ui-core/core/src/lib/components/sidebar-menu/menu-items/concrete/menu-item/menu-item.component.html @@ -24,15 +24,18 @@ [ngClass]="onCollapse ? 'collapsed' : ''" (click)="redirectTo()" > - {{ item?.title }} + + + + {{ item?.title }} + +
void; // Function to be called when the menu item is clicked (optional) - data: NavMenuItemData; // Data associated with the section + id: string; // Unique identifier for the section + class?: string; // Additional class for styling (optional) + items?: NavMenuSectionItem[]; // Array of NavMenuItem objects representing the links within the section (optional) + onClick?: (event: MouseEvent) => void; // Function to be called when the menu item is clicked (optional) + data: NavMenuItemData; // Data associated with the section + menuCategory?: NavMenuCategory; // Category of the menu (optional) } /** * Data associated with a NavMenuItem or NavMenuSection. */ export interface NavMenuItemData { - translationKey: string; // Translation key for the title, mandatory for all items - permissionKeys?: PermissionsEnum[]; // Permissions required to display the item (optional) - featureKey?: FeatureEnum; // Feature key required to display the item (optional) - hide?: () => boolean | boolean; // Function to determine if the item should be hidden (optional) - add?: string; + translationKey: string; // Translation key for the title, mandatory for all items + permissionKeys?: PermissionsEnum[]; // Permissions required to display the item (optional) + featureKey?: FeatureEnum; // Feature key required to display the item (optional) + hide?: () => boolean | boolean; // Function to determine if the item should be hidden (optional) + add?: string; } /** * Represents the configuration for navigation menu sections. */ export interface NavMenuSectionConfig { - config: NavMenuSectionItem; // Configuration for the navigation menu section - before?: string; // (Optional) Identifier of the section before which this section should be inserted + config: NavMenuSectionItem; // Configuration for the navigation menu section + before?: string; // (Optional) Identifier of the section before which this section should be inserted } /** * Represents the configuration for navigation menu items. */ export interface NavMenuItemsConfig { - config: NavMenuSectionItem; // Configuration for the navigation menu item - sectionId: string; // Identifier of the section to which this item belongs - before?: string; // (Optional) Identifier of the item before which this item should be inserted + config: NavMenuSectionItem; // Configuration for the navigation menu item + sectionId: string; // Identifier of the section to which this item belongs + before?: string; // (Optional) Identifier of the item before which this item should be inserted } /** diff --git a/packages/ui-core/core/src/lib/services/nav-builder/nav-menu-builder.service.ts b/packages/ui-core/core/src/lib/services/nav-builder/nav-menu-builder.service.ts index fce44168ed4..fb97a0df9f9 100644 --- a/packages/ui-core/core/src/lib/services/nav-builder/nav-menu-builder.service.ts +++ b/packages/ui-core/core/src/lib/services/nav-builder/nav-menu-builder.service.ts @@ -1,16 +1,11 @@ import { Injectable } from '@angular/core'; import { BehaviorSubject, combineLatest, map, Observable, of, shareReplay } from 'rxjs'; -import { - NavMenuSectionItem, - NavMenuItemsConfig, - NavMenuSectionConfig, -} from './nav-builder-types'; +import { NavMenuSectionItem, NavMenuItemsConfig, NavMenuSectionConfig } from './nav-builder-types'; @Injectable({ providedIn: 'root' }) export class NavMenuBuilderService { - // Declare an observable property menuConfig$ of type Observable public menuConfig$: Observable; @@ -78,8 +73,8 @@ export class NavMenuBuilderService { */ addNavMenuItem(config: NavMenuSectionItem, sectionId: string, before?: string) { // Check if the item already exists - const existingIndex = this.addedNavMenuItems.findIndex(item => - item.config.id === config.id && item.sectionId === sectionId + const existingIndex = this.addedNavMenuItems.findIndex( + (item) => item.config.id === config.id && item.sectionId === sectionId ); if (existingIndex !== -1) { @@ -103,8 +98,8 @@ export class NavMenuBuilderService { addNavMenuItems(configs: NavMenuSectionItem[], sectionId: string, before?: string) { configs.forEach((config: NavMenuSectionItem) => { // Check if the item already exists - const existingIndex = this.addedNavMenuItems.findIndex((item) => - item.config.id === config.id && item.sectionId === sectionId + const existingIndex = this.addedNavMenuItems.findIndex( + (item) => item.config.id === config.id && item.sectionId === sectionId ); if (existingIndex !== -1) { @@ -127,10 +122,14 @@ export class NavMenuBuilderService { * @param sectionId The identifier of the section from which the item should be removed. */ removeNavMenuItem(itemId: string, sectionId: string): void { - const itemIndex = this.addedNavMenuItems.findIndex((item) => item.config.id === itemId && item.sectionId === sectionId); + const itemIndex = this.addedNavMenuItems.findIndex( + (item) => item.config.id === itemId && item.sectionId === sectionId + ); if (itemIndex !== -1) { // Check if the item is already present in the removedNavMenuItems array - const existingIndex = this.removedNavMenuItems.findIndex((item) => item.config.id === itemId && item.sectionId === sectionId); + const existingIndex = this.removedNavMenuItems.findIndex( + (item) => item.config.id === itemId && item.sectionId === sectionId + ); if (existingIndex === -1) { // Push the removed item into the removedNavMenuItems array this.removedNavMenuItems.push(this.addedNavMenuItems[itemIndex]); @@ -188,7 +187,7 @@ export class NavMenuBuilderService { return [...configMap.values()]; }), - shareReplay(1), + shareReplay(1) ); // Combine the combined configuration with item additions to produce the final menu configuration @@ -230,7 +229,9 @@ export class NavMenuBuilderService { } } } else { - console.error(`Could not add menu item "${item.config.id}", section "${item.sectionId}" does not exist`); + console.error( + `Could not add menu item "${item.config.id}", section "${item.sectionId}" does not exist` + ); } }); diff --git a/packages/ui-core/theme/src/lib/components/gauzy-logo/gauzy-logo.component.html b/packages/ui-core/theme/src/lib/components/gauzy-logo/gauzy-logo.component.html index 5c347691c48..aba74b3f00c 100644 --- a/packages/ui-core/theme/src/lib/components/gauzy-logo/gauzy-logo.component.html +++ b/packages/ui-core/theme/src/lib/components/gauzy-logo/gauzy-logo.component.html @@ -1,37 +1,38 @@ - +
-
{{ organization?.name }}
-
{{ organization?.website }}
+
+ {{ organization?.name }} +
+
+ {{ organization?.website }} +
- + - +
- +
- +