@acorex/modules 20.8.6 → 20.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { AXPEntityCommandScope, createQueryView, AXPRefreshEvent, AXPSettingsService, AXPCommonSettings, createAllQueryView, AXPEntityQueryType, AXPVersioningService, AXPSearchService, AXPLockService, AXPStatusDefinitionProviderService, AXPStatusProvider, AXPSystemStatuses, AXPSystemStatusType, AXPHomePageService, ALL_DEFAULT_OPERATORS, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_STATUS_PROVIDERS } from '@acorex/platform/common';
1
+ import { AXPEntityCommandScope, createQueryView, AXPRefreshEvent, AXPSettingsService, AXPCommonSettings, createAllQueryView, AXPEntityQueryType, AXPVersioningService, AXPLockService, AXPStatusDefinitionProviderService, AXPStatusProvider, AXPSystemStatuses, AXPSystemStatusType, AXPHomePageService, ALL_DEFAULT_OPERATORS, AXP_MENU_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER, AXP_STATUS_PROVIDERS, AXPSearchService } from '@acorex/platform/common';
2
2
  import * as i1$5 from '@acorex/platform/core';
3
- import { AXPExpressionEvaluatorService, getSmart, AXPComponentSlotModule, AXPPlatformScope, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPBroadcastEventService, AXP_MODULE_MANIFEST_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER } from '@acorex/platform/core';
3
+ import { AXPExpressionEvaluatorService, getSmart, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPBroadcastEventService, AXP_MODULE_MANIFEST_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXPComponentSlotModule, AXPPlatformScope } from '@acorex/platform/core';
4
4
  import { AXPWidgetsModule } from '@acorex/platform/layout/widgets';
5
5
  import * as i0 from '@angular/core';
6
6
  import { inject, Injectable, NgModule, viewChild, ElementRef, signal, computed, ChangeDetectionStrategy, Component, Injector, runInInjectionContext, input, ViewEncapsulation, InjectionToken, HostListener } from '@angular/core';
@@ -19,23 +19,23 @@ import { AXButtonModule } from '@acorex/components/button';
19
19
  import * as i2 from '@acorex/components/popover';
20
20
  import { AXPopoverModule } from '@acorex/components/popover';
21
21
  import { AXFormatService } from '@acorex/core/format';
22
- import * as i1$3 from '@angular/common';
22
+ import * as i3 from '@angular/common';
23
23
  import { CommonModule } from '@angular/common';
24
24
  import { AXP_PERMISSION_DEFINITION_PROVIDER, AXPSessionService } from '@acorex/platform/auth';
25
25
  import { AXBasePageComponent } from '@acorex/components/page';
26
- import * as i1$4 from '@acorex/components/decorators';
26
+ import * as i1$3 from '@acorex/components/decorators';
27
27
  import { AXDecoratorModule } from '@acorex/components/decorators';
28
28
  import { AXPCompareViewComponent, AXPThemeLayoutBlockComponent, AXPResourceAppointmentComponent } from '@acorex/platform/layout/components';
29
29
  import { AXPopupService } from '@acorex/components/popup';
30
30
  import { get, set } from 'lodash-es';
31
- import { AXTextBoxModule } from '@acorex/components/text-box';
32
- import { Subject, firstValueFrom } from 'rxjs';
33
31
  import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
34
- import * as i1$6 from '@acorex/core/validation';
32
+ import * as i1$4 from '@acorex/core/validation';
35
33
  import { AXValidationModule } from '@acorex/core/validation';
36
34
  import { AXCalendarService } from '@acorex/core/date-time';
37
35
  import { provideCommandMiddleware } from '@acorex/platform/runtime';
38
36
  import { AXToastService } from '@acorex/components/toast';
37
+ import { firstValueFrom, Subject } from 'rxjs';
38
+ import { AXTextBoxModule } from '@acorex/components/text-box';
39
39
  import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
40
40
  import { ActivatedRoute } from '@angular/router';
41
41
 
@@ -1410,7 +1410,7 @@ class AXPAuditInfoColumnComponent extends AXPColumnWidgetComponent {
1410
1410
  });
1411
1411
  }
1412
1412
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPAuditInfoColumnComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1413
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AXPAuditInfoColumnComponent, isStandalone: true, selector: "axp-audit-info-column", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "infoButton", first: true, predicate: ["infoButton"], descendants: true, isSignal: true }, { propertyName: "infoPopover", first: true, predicate: ["infoPopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-flex ax-items-center ax-gap-1.5\">\n @if (hasAuditInfo()) {\n <div class=\"ax-flex ax-items-center ax-gap-1.5 ax-cursor-pointer hover:ax-opacity-80 ax-transition-opacity\"\n (click)=\"showInfo()\" [title]=\"displayText()\" #infoButton>\n <i class=\"fa-light fa-calendar-circle-exclamation\"></i>\n <span class=\"ax-text-xs \" [dir]=\"'ltr'\">{{ displayDate() }}</span>\n </div>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n\n<!-- Audit Info Popover -->\n<ax-popover [openOn]=\"'manual'\" #infoPopover (openChange)=\"onPopoverOpenChange($event)\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-3 ax-min-w-[280px]\">\n <div class=\"ax-mb-3 ax-pb-2 ax-border-b\">\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ '@general:terms.audit.section-title' | translate | async }}\n </h3>\n </div>\n <div class=\"ax-space-y-2.5\">\n <!-- Created -->\n @if (createdEvent()) {\n <div>\n <div class=\"ax-text-xs ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.created' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (createdEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(createdEvent()?.at) }}</span>\n @if (createdEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(createdEvent()?.by) }}</span>\n }\n </div>\n }\n @if (createdEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ createdEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n\n <!-- Updated -->\n @if (updatedEvent()) {\n <div>\n <div class=\"ax-text-xs ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.updated' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (updatedEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(updatedEvent()?.at) }}</span>\n @if (updatedEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(updatedEvent()?.by) }}</span>\n }\n </div>\n }\n @if (updatedEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ updatedEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n\n <!-- Deleted -->\n @if (deletedEvent()) {\n <div>\n <div class=\"ax-text-xs ax-text-muted ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.deleted' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (deletedEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(deletedEvent()?.at) }}</span>\n @if (deletedEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(deletedEvent()?.by) }}</span>\n }\n </div>\n }\n @if (deletedEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ deletedEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n </div>\n @if (hasHistoryPlugin()) {\n <div class=\"ax-mt-3 ax-pt-3 ax-border-t ax-sm\">\n <ax-button [text]=\"'@general:terms.audit.history' | translate | async\" (click)=\"showHistory()\" class=\"ax-w-full\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "repositionOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1413
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AXPAuditInfoColumnComponent, isStandalone: true, selector: "axp-audit-info-column", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "infoButton", first: true, predicate: ["infoButton"], descendants: true, isSignal: true }, { propertyName: "infoPopover", first: true, predicate: ["infoPopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-flex ax-items-center ax-gap-1.5\">\n @if (hasAuditInfo()) {\n <div class=\"ax-flex ax-items-center ax-gap-1.5 ax-cursor-pointer hover:ax-opacity-80 ax-transition-opacity\"\n (click)=\"showInfo()\" [title]=\"displayText()\" #infoButton>\n <i class=\"fa-light fa-calendar-circle-exclamation\"></i>\n <span class=\"ax-text-xs \" [dir]=\"'ltr'\">{{ displayDate() }}</span>\n </div>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n\n<!-- Audit Info Popover -->\n<ax-popover [openOn]=\"'manual'\" #infoPopover (openChange)=\"onPopoverOpenChange($event)\" [adaptivityEnabled]=\"true\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-3 ax-min-w-[280px]\">\n <div class=\"ax-mb-3 ax-pb-2 ax-border-b\">\n <h3 class=\"ax-text-sm ax-font-semibold\">\n {{ '@general:terms.audit.section-title' | translate | async }}\n </h3>\n </div>\n <div class=\"ax-space-y-2.5\">\n <!-- Created -->\n @if (createdEvent()) {\n <div>\n <div class=\"ax-text-xs ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.created' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (createdEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(createdEvent()?.at) }}</span>\n @if (createdEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(createdEvent()?.by) }}</span>\n }\n </div>\n }\n @if (createdEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ createdEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n\n <!-- Updated -->\n @if (updatedEvent()) {\n <div>\n <div class=\"ax-text-xs ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.updated' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (updatedEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(updatedEvent()?.at) }}</span>\n @if (updatedEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(updatedEvent()?.by) }}</span>\n }\n </div>\n }\n @if (updatedEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ updatedEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n\n <!-- Deleted -->\n @if (deletedEvent()) {\n <div>\n <div class=\"ax-text-xs ax-text-muted ax-mb-1 ax-font-semibold\">\n {{ '@general:terms.audit.deleted' | translate | async }}\n </div>\n <div class=\"ax-text-xs ax-space-y-0.5\">\n @if (deletedEvent()?.at) {\n <div>\n <span [dir]=\"'ltr'\">{{ formatDate(deletedEvent()?.at) }}</span>\n @if (deletedEvent()?.by) {\n <span class=\"ax-text-muted\"> \u2022 {{ formatUser(deletedEvent()?.by) }}</span>\n }\n </div>\n }\n @if (deletedEvent()?.reason) {\n <div class=\"ax-text-muted\">{{ deletedEvent()?.reason }}</div>\n }\n </div>\n </div>\n }\n </div>\n @if (hasHistoryPlugin()) {\n <div class=\"ax-mt-3 ax-pt-3 ax-border-t ax-sm\">\n <ax-button [text]=\"'@general:terms.audit.history' | translate | async\" (click)=\"showHistory()\" class=\"ax-w-full\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "repositionOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1414
1414
  }
1415
1415
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPAuditInfoColumnComponent, decorators: [{
1416
1416
  type: Component,
@@ -1495,7 +1495,7 @@ class AXPAuditInfoViewComponent extends AXPValueWidgetComponent {
1495
1495
  }
1496
1496
  </div>
1497
1497
  }
1498
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1498
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1499
1499
  }
1500
1500
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPAuditInfoViewComponent, decorators: [{
1501
1501
  type: Component,
@@ -1618,7 +1618,7 @@ class AXPAuditInfoEditComponent extends AXPValueWidgetComponent {
1618
1618
  }
1619
1619
  </div>
1620
1620
  }
1621
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1621
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1622
1622
  }
1623
1623
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPAuditInfoEditComponent, decorators: [{
1624
1624
  type: Component,
@@ -2532,9 +2532,9 @@ class AXPComparePopupComponent extends AXBasePageComponent {
2532
2532
  // Angular
2533
2533
  CommonModule }, { kind: "ngmodule", type:
2534
2534
  // ACoreX
2535
- AXDecoratorModule }, { kind: "component", type: i1$4.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
2535
+ AXDecoratorModule }, { kind: "component", type: i1$3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type:
2536
2536
  // Compare View
2537
- AXPCompareViewComponent, selector: "axp-compare-view", inputs: ["inputs", "mode"] }, { kind: "pipe", type: i1$3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
2537
+ AXPCompareViewComponent, selector: "axp-compare-view", inputs: ["inputs", "mode"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
2538
2538
  }
2539
2539
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPComparePopupComponent, decorators: [{
2540
2540
  type: Component,
@@ -4157,860 +4157,581 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
4157
4157
  }]
4158
4158
  }] });
4159
4159
 
4160
- const AXP_GLOBAL_SEARCH_CONFIG_TOKEN = new InjectionToken('AXP_GLOBAL_SEARCH_CONFIG_TOKEN');
4161
-
4162
- class AXPGlobalSearchSlotComponent {
4163
- constructor() {
4164
- this.workflow = inject(AXPWorkflowService);
4165
- }
4166
- async startSearch() {
4167
- await this.workflow.execute('global-search');
4168
- }
4169
- async handleKeyboardEvent(event) {
4170
- if (event.ctrlKey) {
4171
- switch (event.code) {
4172
- case 'KeyK':
4173
- event.preventDefault();
4174
- event.stopPropagation();
4175
- await this.startSearch();
4176
- break;
4160
+ const iconPlugin = {
4161
+ name: 'icon',
4162
+ order: 75,
4163
+ apply: (ctx, options) => {
4164
+ ensureListActions(ctx);
4165
+ const groupId = 'appearance';
4166
+ const groups = ctx.groups.list() ?? [];
4167
+ if (!groups.some((g) => g.id === groupId)) {
4168
+ ctx.groups.add({ id: groupId, title: '@general:terms.interface.appearance' });
4169
+ }
4170
+ const props = ctx.properties.list();
4171
+ if (!props.some((p) => p.name === 'icon')) {
4172
+ ctx.properties.add({
4173
+ name: 'icon',
4174
+ title: '@general:terms.common.icon',
4175
+ groupId,
4176
+ schema: {
4177
+ dataType: 'string',
4178
+ interface: {
4179
+ type: AXPWidgetsList.Theme.IconChooser,
4180
+ options: {},
4181
+ },
4182
+ },
4183
+ validations: [],
4184
+ options: {
4185
+ sort: { enabled: false },
4186
+ filter: {
4187
+ advance: { enabled: false },
4188
+ inline: { enabled: false },
4189
+ },
4190
+ },
4191
+ });
4192
+ }
4193
+ //#region ---- Add Column to List View ----
4194
+ // Add icon column to list view if enabled (default: true)
4195
+ const columnEnabled = options?.column?.enabled ?? true;
4196
+ if (columnEnabled) {
4197
+ const columns = ctx.columns.list() ?? [];
4198
+ if (!columns.some((c) => c.name === 'icon')) {
4199
+ ctx.columns.add({
4200
+ name: 'icon',
4201
+ title: '@general:terms.common.icon',
4202
+ sort: { enabled: false },
4203
+ options: {
4204
+ visible: options?.column?.visible ?? false,
4205
+ width: `${options?.column?.width ?? 120}px`,
4206
+ },
4207
+ });
4177
4208
  }
4178
4209
  }
4179
- }
4180
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4181
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: AXPGlobalSearchSlotComponent, isStandalone: true, selector: "ng-component", host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, ngImport: i0, template: `
4182
- <ax-button color="primary" class="ax-flex md:ax-hidden" (onClick)="startSearch()">
4183
- <ax-icon class="fa-regular fa-search">
4184
- </ax-icon>
4185
- </ax-button>
4186
- <div class="ax-bg-primary-200/15 ax-h-10 ax-w-72 ax-rounded-default ax-cursor-pointer ax-justify-between ax-hidden md:ax-flex ax-items-center ax-px-3 hover:ax-bg-primary-200/30 ax-text-primary-text" (click)="startSearch()">
4187
- <div class="ax-flex ax-items-center ax-gap-2">
4188
- <i class="fa-light fa-search ax-text-xl"></i>
4189
- <span>{{ '@global-search:terms.search-placeholder' | translate | async}}</span>
4190
- </div>
4191
- <kbd class="ax-text-sm">Ctrl+K</kbd>
4192
- </div>
4193
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "pipe", type: i1$3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }] }); }
4210
+ //#endregion
4211
+ //#region ---- Update Interface Layouts ----
4212
+ // Ensure layout includes property in create/modify/single
4213
+ const applyLayoutPatch = (layout) => {
4214
+ const next = cloneLayoutArrays(layout);
4215
+ ensureLayoutSection(next, { id: groupId, order: 150 });
4216
+ ensureLayoutPropertyView(next, { name: 'icon', layout: { positions: { lg: { colSpan: 6 } } } });
4217
+ return next;
4218
+ };
4219
+ ctx.interfaces.master.create.update((create) => applyLayoutPatch(create ?? { sections: [], properties: [] }));
4220
+ ctx.interfaces.master.modify.update((modify) => applyLayoutPatch(modify ?? { sections: [], properties: [] }));
4221
+ ctx.interfaces.master.single.update((single) => applyLayoutPatch(single ?? { title: ctx.entity.title, sections: [], properties: [] }));
4222
+ //#endregion
4223
+ },
4224
+ };
4225
+
4226
+ class AXPIconPluginModule {
4227
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4228
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule }); }
4229
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: iconPlugin }] }); }
4194
4230
  }
4195
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchSlotComponent, decorators: [{
4196
- type: Component,
4231
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, decorators: [{
4232
+ type: NgModule,
4197
4233
  args: [{
4198
- template: `
4199
- <ax-button color="primary" class="ax-flex md:ax-hidden" (onClick)="startSearch()">
4200
- <ax-icon class="fa-regular fa-search">
4201
- </ax-icon>
4202
- </ax-button>
4203
- <div class="ax-bg-primary-200/15 ax-h-10 ax-w-72 ax-rounded-default ax-cursor-pointer ax-justify-between ax-hidden md:ax-flex ax-items-center ax-px-3 hover:ax-bg-primary-200/30 ax-text-primary-text" (click)="startSearch()">
4204
- <div class="ax-flex ax-items-center ax-gap-2">
4205
- <i class="fa-light fa-search ax-text-xl"></i>
4206
- <span>{{ '@global-search:terms.search-placeholder' | translate | async}}</span>
4207
- </div>
4208
- <kbd class="ax-text-sm">Ctrl+K</kbd>
4209
- </div>
4210
- `,
4211
- imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXTranslationModule, AXTextBoxModule]
4234
+ declarations: [],
4235
+ imports: [],
4236
+ exports: [],
4237
+ providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: iconPlugin }],
4212
4238
  }]
4213
- }], propDecorators: { handleKeyboardEvent: [{
4214
- type: HostListener,
4215
- args: ['document:keydown', ['$event']]
4216
- }] } });
4239
+ }] });
4217
4240
 
4218
- class AXPGlobalSearchStartAction extends AXPWorkflowAction {
4241
+ const lockGuardMiddleware = {
4242
+ target: { ops: ['update', 'delete'], order: 10 },
4243
+ execute: async (ctx, next) => {
4244
+ const lockService = inject(AXPLockService);
4245
+ const session = inject(AXPSessionService);
4246
+ const lock = await lockService.check({ refId: ctx.id, refType: ctx.entityName });
4247
+ if (lock) {
4248
+ const info = await lockService.getInfo({ refId: ctx.id, refType: ctx.entityName });
4249
+ if (info && session.user && info.lockedBy.id !== session.user.id) {
4250
+ throw new Error('This record is locked and cannot be edited.');
4251
+ }
4252
+ }
4253
+ await next();
4254
+ },
4255
+ };
4256
+
4257
+ class AXMLockPopupWorkflowAction extends AXPWorkflowAction {
4219
4258
  constructor() {
4220
4259
  super(...arguments);
4221
- this.popupService = inject(AXPopupService);
4222
- this.workflow = inject(AXPWorkflowService);
4223
- this.config = inject(AXP_GLOBAL_SEARCH_CONFIG_TOKEN);
4260
+ this.translationService = inject(AXTranslationService);
4261
+ this.layoutBuilder = inject(AXPLayoutBuilderService);
4262
+ this.lockService = inject(AXPLockService);
4263
+ this.sessionService = inject(AXPSessionService);
4224
4264
  }
4225
4265
  async execute(context) {
4226
- const component = await this.config.window();
4227
- const popup = await this.popupService.open(component, {
4228
- title: 'Search...',
4229
- size: 'fit',
4230
- closeOnBackdropClick: true,
4231
- data: {
4232
- text: context.getVariable('text'),
4266
+ const refId = context.getVariable('options.refId');
4267
+ const refType = context.getVariable('options.refType');
4268
+ const durationOptions = [
4269
+ {
4270
+ value: '1h',
4271
+ text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.1h'),
4272
+ hours: 1,
4233
4273
  },
4234
- header: false,
4235
- });
4236
- if (popup.data) {
4237
- const result = popup.data;
4238
- if (result && result.command) {
4239
- this.workflow.execute(result.command?.name, result.command?.options);
4240
- }
4274
+ {
4275
+ value: '1d',
4276
+ text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.1d'),
4277
+ hours: 24,
4278
+ },
4279
+ {
4280
+ value: 'infinite',
4281
+ text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.infinite'),
4282
+ },
4283
+ ];
4284
+ const dialogTitle = await this.translationService.translateAsync('@lock-system:components.lock-dialog.title');
4285
+ const dialogRef = await this.layoutBuilder
4286
+ .create()
4287
+ .dialog(dialog => {
4288
+ dialog
4289
+ .setTitle(dialogTitle)
4290
+ .setContext({ duration: '1h', reason: '' })
4291
+ .content(flex => {
4292
+ flex
4293
+ .setDirection('column')
4294
+ .formField('@lock-system:components.lock-dialog.fields.duration.title', field => {
4295
+ field.path('duration');
4296
+ field.selectBox({
4297
+ valueField: 'value',
4298
+ textField: 'text',
4299
+ dataSource: durationOptions,
4300
+ validations: [{ rule: 'required' }],
4301
+ });
4302
+ })
4303
+ .formField('@lock-system:components.lock-dialog.fields.reason.title', field => {
4304
+ field.path('reason');
4305
+ field.largeTextBox({
4306
+ rows: 3,
4307
+ placeholder: '@lock-system:components.lock-dialog.fields.reason.placeholder',
4308
+ });
4309
+ });
4310
+ })
4311
+ .setActions(actions => {
4312
+ actions.cancel('@lock-system:components.lock-dialog.actions.cancel');
4313
+ const confirmAction = {
4314
+ title: '@lock-system:components.lock-dialog.actions.confirm',
4315
+ color: 'primary',
4316
+ command: { name: 'submit', options: { validate: true } },
4317
+ };
4318
+ actions.custom(confirmAction);
4319
+ });
4320
+ })
4321
+ .show();
4322
+ const action = dialogRef.action();
4323
+ if (action === 'cancel') {
4324
+ context.setOutput('isCanceled', true);
4325
+ dialogRef.close();
4326
+ return;
4241
4327
  }
4328
+ const form = dialogRef.context();
4329
+ const selected = form?.duration ?? '1h';
4330
+ const selectedDuration = durationOptions.find((d) => d.value === selected);
4331
+ const expireAt = selectedDuration?.hours
4332
+ ? new Date(Date.now() + selectedDuration.hours * 60 * 60 * 1000)
4333
+ : undefined;
4334
+ await this.lockService.lock({
4335
+ refId,
4336
+ refType,
4337
+ type: 'user',
4338
+ date: new Date().toISOString(),
4339
+ expireAt,
4340
+ lockedBy: {
4341
+ id: this.sessionService.user?.id ?? 'system',
4342
+ type: 'oidc.users',
4343
+ },
4344
+ });
4345
+ dialogRef.close();
4346
+ context.setOutput('isCanceled', false);
4347
+ context.setOutput('lockDuration', form?.duration ?? '1h');
4348
+ context.setOutput('lockReason', form?.reason ?? '');
4242
4349
  }
4243
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4244
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction }); }
4350
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4351
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction }); }
4245
4352
  }
4246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction, decorators: [{
4353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction, decorators: [{
4247
4354
  type: Injectable
4248
4355
  }] });
4249
- const AXPGlobalSearchWorkflow = {
4250
- startStepId: 'start',
4356
+ const AXMLockPopupWorkflow = {
4357
+ startStepId: 'lock-popup',
4251
4358
  steps: {
4252
- start: {
4253
- action: 'AXPGlobalSearchStartAction',
4359
+ 'lock-popup': {
4360
+ action: 'AXMLockPopupWorkflowAction',
4361
+ nextSteps: [
4362
+ {
4363
+ conditions: [{ type: 'SINGLE', expression: 'context.getOutput("isCanceled") == false' }],
4364
+ nextStepId: 'successToast',
4365
+ },
4366
+ ],
4367
+ },
4368
+ successToast: {
4369
+ id: 'successToast',
4370
+ action: 'AXPToastAction',
4371
+ input: {
4372
+ color: 'success',
4373
+ title: '@general:workflow.entity-modified-title',
4374
+ content: '@general:workflow.entity-modified-body',
4375
+ },
4376
+ nextSteps: [
4377
+ {
4378
+ conditions: [],
4379
+ nextStepId: 'modifyConfirmed',
4380
+ },
4381
+ ],
4382
+ },
4383
+ modifyConfirmed: {
4384
+ id: 'modifyConfirmed',
4385
+ action: 'AXPEntityModifyConfirmedAction',
4254
4386
  },
4255
4387
  },
4256
4388
  };
4257
4389
 
4258
- const AXPCommonFeatureKeys = {
4259
- GlobalSearch: 'Common:Feature:GlobalSearch',
4260
- AdvancedExport: 'Common:Feature:AdvancedExport',
4261
- ActivityLog: 'Common:Feature:ActivityLog',
4262
- DataImport: 'Common:Feature:DataImport',
4263
- BulkOperations: 'Common:Feature:BulkOperations',
4264
- AdvancedFiltering: 'Common:Feature:AdvancedFiltering',
4265
- DataSynchronization: 'Common:Feature:DataSynchronization',
4266
- };
4267
-
4268
- class AXPGlobalSearchModule {
4269
- constructor(appInitService, injector) {
4390
+ class AXMUnlockConfirmWorkflowAction extends AXPWorkflowAction {
4391
+ constructor() {
4392
+ super(...arguments);
4393
+ this.dialogService = inject(AXDialogService);
4394
+ this.translationService = inject(AXTranslationService);
4395
+ this.lockService = inject(AXPLockService);
4396
+ this.sessionService = inject(AXPSessionService);
4270
4397
  }
4271
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, deps: [{ token: i1$5.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
4272
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, imports: [i1$5.AXPComponentSlotModule, i1.AXPWorkflowModule] }); }
4273
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, providers: [
4274
- {
4275
- provide: AXP_GLOBAL_SEARCH_CONFIG_TOKEN,
4276
- useValue: {
4277
- window: () => import('./acorex-modules-common-search-popup.component-Cdpkw5Vj.mjs').then((c) => c.AXPGlobalSearchPopupComponent),
4398
+ async execute(context) {
4399
+ const refId = context.getVariable('options.refId');
4400
+ const refType = context.getVariable('options.refType');
4401
+ // Show confirmation dialog
4402
+ const dialogResult = await this.dialogService.confirm(await this.translationService.translateAsync('@lock-system:components.unlock-dialog.title'), await this.translationService.translateAsync('@lock-system:components.unlock-dialog.description'), 'warning', 'horizontal', false, 'cancel');
4403
+ if (dialogResult.result) {
4404
+ try {
4405
+ // Perform unlock
4406
+ await this.lockService.unlock({
4407
+ refId: refId,
4408
+ refType: refType,
4409
+ type: 'user',
4410
+ });
4411
+ context.setOutput('isCanceled', false);
4412
+ context.setOutput('unlocked', true);
4413
+ }
4414
+ catch (error) {
4415
+ console.error('Unlock failed:', error);
4416
+ // Show error dialog
4417
+ await this.dialogService.alert(await this.translationService.translateAsync('@lock-system:messages.error.unlock.title'), await this.translationService.translateAsync('@lock-system:messages.error.unlock.description'), 'danger');
4418
+ context.setOutput('isCanceled', true);
4419
+ context.setOutput('unlocked', false);
4420
+ }
4421
+ }
4422
+ else {
4423
+ context.setOutput('isCanceled', true);
4424
+ context.setOutput('unlocked', false);
4425
+ }
4426
+ }
4427
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4428
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction }); }
4429
+ }
4430
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction, decorators: [{
4431
+ type: Injectable
4432
+ }] });
4433
+ const AXMUnlockConfirmWorkflow = {
4434
+ startStepId: 'unlock-confirm',
4435
+ steps: {
4436
+ 'unlock-confirm': {
4437
+ action: 'AXMUnlockConfirmWorkflowAction',
4438
+ nextSteps: [
4439
+ {
4440
+ conditions: [{ type: 'SINGLE', expression: 'context.getOutput("unlocked") == true' }],
4441
+ nextStepId: 'successToast',
4278
4442
  },
4443
+ ],
4444
+ },
4445
+ successToast: {
4446
+ id: 'successToast',
4447
+ action: 'AXPToastAction',
4448
+ input: {
4449
+ color: 'success',
4450
+ title: '@general:workflow.entity-modified-title',
4451
+ content: '@general:workflow.entity-modified-body',
4279
4452
  },
4280
- ], imports: [AXPComponentSlotModule.forChild({
4281
- 'root-header-start': [
4282
- {
4283
- priority: 0,
4284
- name: 'search',
4285
- component: AXPGlobalSearchSlotComponent,
4286
- features: [AXPCommonFeatureKeys.GlobalSearch],
4287
- },
4288
- ],
4289
- }),
4290
- //
4291
- AXPWorkflowModule.forChild({
4453
+ nextSteps: [
4454
+ {
4455
+ conditions: [],
4456
+ nextStepId: 'modifyConfirmed',
4457
+ },
4458
+ ],
4459
+ },
4460
+ modifyConfirmed: {
4461
+ id: 'modifyConfirmed',
4462
+ action: 'AXPEntityModifyConfirmedAction',
4463
+ },
4464
+ },
4465
+ };
4466
+
4467
+ class AXMLockEvaluatorScopeProvider {
4468
+ constructor() {
4469
+ this.lockService = inject(AXPLockService, {
4470
+ optional: true,
4471
+ });
4472
+ }
4473
+ async provide(context) {
4474
+ context.addScope('lock', {
4475
+ check: async (refId, refType) => {
4476
+ if (this.lockService) {
4477
+ const lock = await this.lockService.check({
4478
+ refId, refType
4479
+ });
4480
+ return lock;
4481
+ }
4482
+ return false;
4483
+ }
4484
+ });
4485
+ }
4486
+ }
4487
+
4488
+ class AXMLockSystemModule {
4489
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4490
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, imports: [i1.AXPWorkflowModule] }); }
4491
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, providers: [
4492
+ { provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, multi: true, useClass: AXMLockEvaluatorScopeProvider },
4493
+ // { provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: lockPlugin },
4494
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
4495
+ ], imports: [AXPWorkflowModule.forChild({
4292
4496
  actions: {
4293
- AXPGlobalSearchStartAction
4497
+ AXMLockPopupWorkflowAction,
4498
+ AXMUnlockConfirmWorkflowAction,
4294
4499
  },
4295
4500
  workflows: {
4296
- 'global-search': AXPGlobalSearchWorkflow,
4501
+ 'lock-popup': AXMLockPopupWorkflow,
4502
+ 'unlock-confirm': AXMUnlockConfirmWorkflow,
4297
4503
  },
4298
4504
  })] }); }
4299
4505
  }
4300
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, decorators: [{
4506
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, decorators: [{
4301
4507
  type: NgModule,
4302
4508
  args: [{
4303
4509
  imports: [
4304
- AXPComponentSlotModule.forChild({
4305
- 'root-header-start': [
4306
- {
4307
- priority: 0,
4308
- name: 'search',
4309
- component: AXPGlobalSearchSlotComponent,
4310
- features: [AXPCommonFeatureKeys.GlobalSearch],
4311
- },
4312
- ],
4313
- }),
4314
- //
4315
4510
  AXPWorkflowModule.forChild({
4316
4511
  actions: {
4317
- AXPGlobalSearchStartAction
4512
+ AXMLockPopupWorkflowAction,
4513
+ AXMUnlockConfirmWorkflowAction,
4318
4514
  },
4319
4515
  workflows: {
4320
- 'global-search': AXPGlobalSearchWorkflow,
4516
+ 'lock-popup': AXMLockPopupWorkflow,
4517
+ 'unlock-confirm': AXMUnlockConfirmWorkflow,
4321
4518
  },
4322
- })
4519
+ }),
4323
4520
  ],
4324
- exports: [],
4325
- declarations: [],
4326
4521
  providers: [
4327
- {
4328
- provide: AXP_GLOBAL_SEARCH_CONFIG_TOKEN,
4329
- useValue: {
4330
- window: () => import('./acorex-modules-common-search-popup.component-Cdpkw5Vj.mjs').then((c) => c.AXPGlobalSearchPopupComponent),
4331
- },
4332
- },
4333
- ]
4522
+ { provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, multi: true, useClass: AXMLockEvaluatorScopeProvider },
4523
+ // { provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: lockPlugin },
4524
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
4525
+ ],
4334
4526
  }]
4335
- }], ctorParameters: () => [{ type: i1$5.AXPAppStartUpService }, { type: i0.Injector }] });
4527
+ }] });
4336
4528
 
4337
- class AXPGlobalSearchViewModel {
4338
- constructor() {
4339
- this.settingKeys = {
4340
- recent: "global-search:recents:items",
4341
- pinned: "global-search:pinned:items"
4342
- };
4343
- this.searchService = inject(AXPSearchService);
4344
- this.settingsService = inject(AXPSettingsService);
4345
- this._text = signal(null, ...(ngDevMode ? [{ debugName: "_text" }] : []));
4346
- this.text = this._text.asReadonly();
4347
- this._results = signal([], ...(ngDevMode ? [{ debugName: "_results" }] : []));
4348
- this.results = this._results.asReadonly();
4349
- this._isBusy = signal(false, ...(ngDevMode ? [{ debugName: "_isBusy" }] : []));
4350
- this.isBusy = this._isBusy.asReadonly();
4351
- this.isEmpty = computed(() => this.text() && this.results().length == 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
4352
- this.isValid = computed(() => (this.text()?.length ?? 0) > 2, ...(ngDevMode ? [{ debugName: "isValid" }] : []));
4353
- this.isStart = computed(() => !this.isEmpty() && this.results().length == 0, ...(ngDevMode ? [{ debugName: "isStart" }] : []));
4354
- this.isWelcome = computed(() => this.isStart() && this.pinnedItems().length == 0 && this.recentItems().length == 0, ...(ngDevMode ? [{ debugName: "isWelcome" }] : []));
4355
- this._recentItems = signal([], ...(ngDevMode ? [{ debugName: "_recentItems" }] : []));
4356
- this._pinnedItems = signal([], ...(ngDevMode ? [{ debugName: "_pinnedItems" }] : []));
4357
- this.pinnedItems = this._pinnedItems.asReadonly();
4358
- this.recentItems = computed(() => this.getTopRecentItems(), ...(ngDevMode ? [{ debugName: "recentItems" }] : []));
4359
- this.onItemSelected = new Subject();
4360
- this.loadSettings();
4361
- }
4362
- async search(text) {
4363
- this._isBusy.set(true);
4364
- this._text.set(text);
4365
- if (!this.isValid()) {
4366
- this._results.set([]);
4367
- }
4368
- else {
4369
- await new Promise((resolve) => setTimeout(resolve, 250));
4370
- const results = await this.searchService.search(text);
4371
- this._results.set(results);
4529
+ const namePlugin = {
4530
+ name: 'name',
4531
+ order: 20,
4532
+ apply: (ctx, options) => {
4533
+ const title = options?.title ?? '@general:terms.common.name';
4534
+ const groupId = options?.groupId ?? 'basic-info';
4535
+ const required = options?.required ?? false;
4536
+ const addColumn = options?.column ?? true;
4537
+ //#region ---- Ensure Basic Info Group ----
4538
+ const groups = ctx.groups.list() ?? [];
4539
+ if (!groups.some((g) => g.id === groupId)) {
4540
+ ctx.groups.add({ id: groupId, title: '@general:terms.interface.basic-info' });
4372
4541
  }
4373
- this._isBusy.set(false);
4374
- }
4375
- async execute(item) {
4376
- this.onItemSelected.next(item);
4377
- await this.updateSelectionHistory(item);
4378
- }
4379
- async pin(item) {
4380
- const currentPinned = this._pinnedItems();
4381
- if (!currentPinned.some(i => i.id === item.id)) {
4382
- this._pinnedItems.set([item, ...currentPinned].slice(0, 5));
4383
- await this.saveSettings();
4384
- }
4385
- }
4386
- async unpin(item) {
4387
- const currentPinned = this._pinnedItems();
4388
- this._pinnedItems.set(currentPinned.filter(i => i.id !== item.id));
4389
- await this.saveSettings();
4390
- }
4391
- async togglePin(item) {
4392
- if (this.isPinned(item)) {
4393
- await this.unpin(item);
4394
- }
4395
- else {
4396
- await this.pin(item);
4397
- }
4398
- }
4399
- isPinned(item) {
4400
- const currentPinned = this._pinnedItems();
4401
- return currentPinned.some(i => i.id === item.id);
4402
- }
4403
- async updateSelectionHistory(item) {
4404
- // Update recent selections
4405
- const currentHistory = this._recentItems();
4406
- const updatedHistory = [item, ...currentHistory.filter(i => i.id !== item.id)].slice(0, 5);
4407
- this._recentItems.set(updatedHistory);
4408
- // Save updated settings
4409
- await this.saveSettings();
4410
- }
4411
- getTopRecentItems() {
4412
- const pinnedIds = new Set(this._pinnedItems().map(item => item.id));
4413
- return this._recentItems().filter(item => !pinnedIds.has(item.id)).slice(0, 5);
4414
- }
4415
- async clearRecentItems() {
4416
- this._recentItems.set([]);
4417
- await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.recent, []);
4418
- }
4419
- async loadSettings() {
4420
- // Load recent selections
4421
- const recent = await this.settingsService.get(this.settingKeys.recent);
4422
- if (recent) {
4423
- this._recentItems.set(recent.slice(0, 5));
4542
+ //#endregion
4543
+ //#region ---- Add Name Property ----
4544
+ const props = ctx.properties.list();
4545
+ if (!props.some((p) => p.name === 'name')) {
4546
+ ctx.properties.add({
4547
+ name: 'name',
4548
+ title,
4549
+ groupId,
4550
+ schema: {
4551
+ dataType: 'string',
4552
+ interface: {
4553
+ type: AXPWidgetsList.Editors.TextBox,
4554
+ },
4555
+ },
4556
+ validations: required
4557
+ ? [
4558
+ {
4559
+ rule: 'required',
4560
+ },
4561
+ ]
4562
+ : [],
4563
+ options: {
4564
+ sort: { enabled: true },
4565
+ filter: {
4566
+ advance: { enabled: true },
4567
+ inline: { enabled: true },
4568
+ },
4569
+ },
4570
+ });
4424
4571
  }
4425
- // Load pinned items
4426
- const pinned = await this.settingsService.get(this.settingKeys.pinned);
4427
- if (pinned) {
4428
- this._pinnedItems.set(pinned.slice(0, 5));
4572
+ //#endregion
4573
+ //#region ---- Add Name Column ----
4574
+ if (addColumn) {
4575
+ const columns = ctx.columns.list() ?? [];
4576
+ if (!columns.some((c) => c.name === 'name')) {
4577
+ ctx.columns.add({
4578
+ name: 'name',
4579
+ title,
4580
+ options: {
4581
+ width: '200px',
4582
+ visible: true,
4583
+ },
4584
+ sort: {
4585
+ enabled: true,
4586
+ },
4587
+ });
4588
+ }
4429
4589
  }
4430
- }
4431
- async saveSettings() {
4432
- // Save recent selections
4433
- await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.recent, this._recentItems().slice(0, 5));
4434
- // Save pinned items
4435
- await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.pinned, this._pinnedItems().slice(0, 5));
4436
- }
4590
+ //#endregion
4591
+ //#region ---- Update Interface Layouts ----
4592
+ const ensureLayoutProperty = (layout) => {
4593
+ layout.sections = layout.sections ?? [];
4594
+ if (!layout.sections.some((s) => s.id === groupId)) {
4595
+ layout.sections.push({ id: groupId, order: 10 });
4596
+ }
4597
+ layout.properties = layout.properties ?? [];
4598
+ if (!layout.properties.some((p) => p.name === 'name')) {
4599
+ layout.properties.push({
4600
+ name: 'name',
4601
+ layout: {
4602
+ positions: { lg: { colSpan: 12, order: 10 } },
4603
+ },
4604
+ });
4605
+ }
4606
+ return layout;
4607
+ };
4608
+ ctx.interfaces.master.create.update((create) => ensureLayoutProperty((create ?? { sections: [], properties: [] })));
4609
+ ctx.interfaces.master.modify.update((modify) => ensureLayoutProperty((modify ?? { sections: [], properties: [] })));
4610
+ ctx.interfaces.master.single.update((single) => ensureLayoutProperty((single ?? { title: ctx.entity.title, sections: [], properties: [] })));
4611
+ //#endregion
4612
+ },
4613
+ };
4614
+
4615
+ class AXPNamePluginModule {
4616
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4617
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule }); }
4618
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: namePlugin }] }); }
4437
4619
  }
4620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, decorators: [{
4621
+ type: NgModule,
4622
+ args: [{
4623
+ declarations: [],
4624
+ imports: [],
4625
+ exports: [],
4626
+ providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: namePlugin }],
4627
+ }]
4628
+ }] });
4438
4629
 
4439
- const iconPlugin = {
4440
- name: 'icon',
4441
- order: 75,
4630
+ const notesPlugin = {
4631
+ name: 'notes',
4632
+ order: 22,
4442
4633
  apply: (ctx, options) => {
4443
- ensureListActions(ctx);
4444
- const groupId = 'appearance';
4634
+ const title = options?.title ?? '@general:terms.common.notes';
4635
+ const groupId = options?.groupId ?? 'additional-info';
4636
+ const addColumn = options?.column ?? true;
4637
+ //#region ---- Ensure Additional Info Group ----
4445
4638
  const groups = ctx.groups.list() ?? [];
4446
4639
  if (!groups.some((g) => g.id === groupId)) {
4447
- ctx.groups.add({ id: groupId, title: '@general:terms.interface.appearance' });
4640
+ ctx.groups.add({ id: groupId, title: '@general:terms.interface.additional-info' });
4448
4641
  }
4642
+ //#endregion
4643
+ //#region ---- Add Notes Property ----
4449
4644
  const props = ctx.properties.list();
4450
- if (!props.some((p) => p.name === 'icon')) {
4645
+ if (!props.some((p) => p.name === 'notes')) {
4451
4646
  ctx.properties.add({
4452
- name: 'icon',
4453
- title: '@general:terms.common.icon',
4647
+ name: 'notes',
4648
+ title,
4454
4649
  groupId,
4455
4650
  schema: {
4456
4651
  dataType: 'string',
4457
4652
  interface: {
4458
- type: AXPWidgetsList.Theme.IconChooser,
4459
- options: {},
4653
+ type: AXPWidgetsList.Editors.LargeTextBox,
4654
+ options: {
4655
+ rows: 4,
4656
+ },
4460
4657
  },
4461
4658
  },
4462
4659
  validations: [],
4463
4660
  options: {
4464
4661
  sort: { enabled: false },
4465
4662
  filter: {
4466
- advance: { enabled: false },
4663
+ advance: { enabled: true },
4467
4664
  inline: { enabled: false },
4468
4665
  },
4469
4666
  },
4470
4667
  });
4471
4668
  }
4472
- //#region ---- Add Column to List View ----
4473
- // Add icon column to list view if enabled (default: true)
4474
- const columnEnabled = options?.column?.enabled ?? true;
4475
- if (columnEnabled) {
4669
+ //#endregion
4670
+ //#region ---- Add Notes Column ----
4671
+ if (addColumn) {
4476
4672
  const columns = ctx.columns.list() ?? [];
4477
- if (!columns.some((c) => c.name === 'icon')) {
4673
+ if (!columns.some((c) => c.name === 'notes')) {
4478
4674
  ctx.columns.add({
4479
- name: 'icon',
4480
- title: '@general:terms.common.icon',
4481
- sort: { enabled: false },
4675
+ name: 'notes',
4676
+ title,
4482
4677
  options: {
4483
- visible: options?.column?.visible ?? false,
4484
- width: `${options?.column?.width ?? 120}px`,
4678
+ width: '300px',
4679
+ visible: false,
4485
4680
  },
4486
4681
  });
4487
4682
  }
4488
4683
  }
4489
4684
  //#endregion
4490
4685
  //#region ---- Update Interface Layouts ----
4491
- // Ensure layout includes property in create/modify/single
4492
- const applyLayoutPatch = (layout) => {
4493
- const next = cloneLayoutArrays(layout);
4494
- ensureLayoutSection(next, { id: groupId, order: 150 });
4495
- ensureLayoutPropertyView(next, { name: 'icon', layout: { positions: { lg: { colSpan: 6 } } } });
4496
- return next;
4686
+ const ensureLayoutProperty = (layout) => {
4687
+ layout.sections = layout.sections ?? [];
4688
+ if (!layout.sections.some((s) => s.id === groupId)) {
4689
+ layout.sections.push({ id: groupId, order: 10 });
4690
+ }
4691
+ layout.properties = layout.properties ?? [];
4692
+ if (!layout.properties.some((p) => p.name === 'notes')) {
4693
+ layout.properties.push({
4694
+ name: 'notes',
4695
+ layout: {
4696
+ positions: { lg: { colSpan: 12, order: 40 } },
4697
+ },
4698
+ });
4699
+ }
4700
+ return layout;
4497
4701
  };
4498
- ctx.interfaces.master.create.update((create) => applyLayoutPatch(create ?? { sections: [], properties: [] }));
4499
- ctx.interfaces.master.modify.update((modify) => applyLayoutPatch(modify ?? { sections: [], properties: [] }));
4500
- ctx.interfaces.master.single.update((single) => applyLayoutPatch(single ?? { title: ctx.entity.title, sections: [], properties: [] }));
4702
+ ctx.interfaces.master.create.update((create) => ensureLayoutProperty((create ?? { sections: [], properties: [] })));
4703
+ ctx.interfaces.master.modify.update((modify) => ensureLayoutProperty((modify ?? { sections: [], properties: [] })));
4704
+ ctx.interfaces.master.single.update((single) => ensureLayoutProperty((single ?? { title: ctx.entity.title, sections: [], properties: [] })));
4501
4705
  //#endregion
4502
4706
  },
4503
4707
  };
4504
4708
 
4505
- class AXPIconPluginModule {
4506
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4507
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule }); }
4508
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: iconPlugin }] }); }
4709
+ class AXPNotesPluginModule {
4710
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4711
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule }); }
4712
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: notesPlugin }] }); }
4509
4713
  }
4510
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPIconPluginModule, decorators: [{
4714
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, decorators: [{
4511
4715
  type: NgModule,
4512
4716
  args: [{
4513
4717
  declarations: [],
4514
4718
  imports: [],
4515
4719
  exports: [],
4516
- providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: iconPlugin }],
4720
+ providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: notesPlugin }],
4517
4721
  }]
4518
4722
  }] });
4519
4723
 
4520
- const lockGuardMiddleware = {
4521
- target: { ops: ['update', 'delete'], order: 10 },
4522
- execute: async (ctx, next) => {
4523
- const lockService = inject(AXPLockService);
4524
- const session = inject(AXPSessionService);
4525
- const lock = await lockService.check({ refId: ctx.id, refType: ctx.entityName });
4526
- if (lock) {
4527
- const info = await lockService.getInfo({ refId: ctx.id, refType: ctx.entityName });
4528
- if (info && session.user && info.lockedBy.id !== session.user.id) {
4529
- throw new Error('This record is locked and cannot be edited.');
4530
- }
4531
- }
4532
- await next();
4533
- },
4534
- };
4535
-
4536
- class AXMLockPopupWorkflowAction extends AXPWorkflowAction {
4537
- constructor() {
4538
- super(...arguments);
4539
- this.translationService = inject(AXTranslationService);
4540
- this.layoutBuilder = inject(AXPLayoutBuilderService);
4541
- this.lockService = inject(AXPLockService);
4542
- this.sessionService = inject(AXPSessionService);
4543
- }
4544
- async execute(context) {
4545
- const refId = context.getVariable('options.refId');
4546
- const refType = context.getVariable('options.refType');
4547
- const durationOptions = [
4548
- {
4549
- value: '1h',
4550
- text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.1h'),
4551
- hours: 1,
4552
- },
4553
- {
4554
- value: '1d',
4555
- text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.1d'),
4556
- hours: 24,
4557
- },
4558
- {
4559
- value: 'infinite',
4560
- text: await this.translationService.translateAsync('@lock-system:components.lock-dialog.fields.duration.options.infinite'),
4561
- },
4562
- ];
4563
- const dialogTitle = await this.translationService.translateAsync('@lock-system:components.lock-dialog.title');
4564
- const dialogRef = await this.layoutBuilder
4565
- .create()
4566
- .dialog(dialog => {
4567
- dialog
4568
- .setTitle(dialogTitle)
4569
- .setContext({ duration: '1h', reason: '' })
4570
- .content(flex => {
4571
- flex
4572
- .setDirection('column')
4573
- .formField('@lock-system:components.lock-dialog.fields.duration.title', field => {
4574
- field.path('duration');
4575
- field.selectBox({
4576
- valueField: 'value',
4577
- textField: 'text',
4578
- dataSource: durationOptions,
4579
- validations: [{ rule: 'required' }],
4580
- });
4581
- })
4582
- .formField('@lock-system:components.lock-dialog.fields.reason.title', field => {
4583
- field.path('reason');
4584
- field.largeTextBox({
4585
- rows: 3,
4586
- placeholder: '@lock-system:components.lock-dialog.fields.reason.placeholder',
4587
- });
4588
- });
4589
- })
4590
- .setActions(actions => {
4591
- actions.cancel('@lock-system:components.lock-dialog.actions.cancel');
4592
- const confirmAction = {
4593
- title: '@lock-system:components.lock-dialog.actions.confirm',
4594
- color: 'primary',
4595
- command: { name: 'submit', options: { validate: true } },
4596
- };
4597
- actions.custom(confirmAction);
4598
- });
4599
- })
4600
- .show();
4601
- const action = dialogRef.action();
4602
- if (action === 'cancel') {
4603
- context.setOutput('isCanceled', true);
4604
- dialogRef.close();
4605
- return;
4606
- }
4607
- const form = dialogRef.context();
4608
- const selected = form?.duration ?? '1h';
4609
- const selectedDuration = durationOptions.find((d) => d.value === selected);
4610
- const expireAt = selectedDuration?.hours
4611
- ? new Date(Date.now() + selectedDuration.hours * 60 * 60 * 1000)
4612
- : undefined;
4613
- await this.lockService.lock({
4614
- refId,
4615
- refType,
4616
- type: 'user',
4617
- date: new Date().toISOString(),
4618
- expireAt,
4619
- lockedBy: {
4620
- id: this.sessionService.user?.id ?? 'system',
4621
- type: 'oidc.users',
4622
- },
4623
- });
4624
- dialogRef.close();
4625
- context.setOutput('isCanceled', false);
4626
- context.setOutput('lockDuration', form?.duration ?? '1h');
4627
- context.setOutput('lockReason', form?.reason ?? '');
4628
- }
4629
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4630
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction }); }
4631
- }
4632
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockPopupWorkflowAction, decorators: [{
4633
- type: Injectable
4634
- }] });
4635
- const AXMLockPopupWorkflow = {
4636
- startStepId: 'lock-popup',
4637
- steps: {
4638
- 'lock-popup': {
4639
- action: 'AXMLockPopupWorkflowAction',
4640
- nextSteps: [
4641
- {
4642
- conditions: [{ type: 'SINGLE', expression: 'context.getOutput("isCanceled") == false' }],
4643
- nextStepId: 'successToast',
4644
- },
4645
- ],
4646
- },
4647
- successToast: {
4648
- id: 'successToast',
4649
- action: 'AXPToastAction',
4650
- input: {
4651
- color: 'success',
4652
- title: '@general:workflow.entity-modified-title',
4653
- content: '@general:workflow.entity-modified-body',
4654
- },
4655
- nextSteps: [
4656
- {
4657
- conditions: [],
4658
- nextStepId: 'modifyConfirmed',
4659
- },
4660
- ],
4661
- },
4662
- modifyConfirmed: {
4663
- id: 'modifyConfirmed',
4664
- action: 'AXPEntityModifyConfirmedAction',
4665
- },
4666
- },
4667
- };
4668
-
4669
- class AXMUnlockConfirmWorkflowAction extends AXPWorkflowAction {
4670
- constructor() {
4671
- super(...arguments);
4672
- this.dialogService = inject(AXDialogService);
4673
- this.translationService = inject(AXTranslationService);
4674
- this.lockService = inject(AXPLockService);
4675
- this.sessionService = inject(AXPSessionService);
4676
- }
4677
- async execute(context) {
4678
- const refId = context.getVariable('options.refId');
4679
- const refType = context.getVariable('options.refType');
4680
- // Show confirmation dialog
4681
- const dialogResult = await this.dialogService.confirm(await this.translationService.translateAsync('@lock-system:components.unlock-dialog.title'), await this.translationService.translateAsync('@lock-system:components.unlock-dialog.description'), 'warning', 'horizontal', false, 'cancel');
4682
- if (dialogResult.result) {
4683
- try {
4684
- // Perform unlock
4685
- await this.lockService.unlock({
4686
- refId: refId,
4687
- refType: refType,
4688
- type: 'user',
4689
- });
4690
- context.setOutput('isCanceled', false);
4691
- context.setOutput('unlocked', true);
4692
- }
4693
- catch (error) {
4694
- console.error('Unlock failed:', error);
4695
- // Show error dialog
4696
- await this.dialogService.alert(await this.translationService.translateAsync('@lock-system:messages.error.unlock.title'), await this.translationService.translateAsync('@lock-system:messages.error.unlock.description'), 'danger');
4697
- context.setOutput('isCanceled', true);
4698
- context.setOutput('unlocked', false);
4699
- }
4700
- }
4701
- else {
4702
- context.setOutput('isCanceled', true);
4703
- context.setOutput('unlocked', false);
4704
- }
4705
- }
4706
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4707
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction }); }
4708
- }
4709
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMUnlockConfirmWorkflowAction, decorators: [{
4710
- type: Injectable
4711
- }] });
4712
- const AXMUnlockConfirmWorkflow = {
4713
- startStepId: 'unlock-confirm',
4714
- steps: {
4715
- 'unlock-confirm': {
4716
- action: 'AXMUnlockConfirmWorkflowAction',
4717
- nextSteps: [
4718
- {
4719
- conditions: [{ type: 'SINGLE', expression: 'context.getOutput("unlocked") == true' }],
4720
- nextStepId: 'successToast',
4721
- },
4722
- ],
4723
- },
4724
- successToast: {
4725
- id: 'successToast',
4726
- action: 'AXPToastAction',
4727
- input: {
4728
- color: 'success',
4729
- title: '@general:workflow.entity-modified-title',
4730
- content: '@general:workflow.entity-modified-body',
4731
- },
4732
- nextSteps: [
4733
- {
4734
- conditions: [],
4735
- nextStepId: 'modifyConfirmed',
4736
- },
4737
- ],
4738
- },
4739
- modifyConfirmed: {
4740
- id: 'modifyConfirmed',
4741
- action: 'AXPEntityModifyConfirmedAction',
4742
- },
4743
- },
4744
- };
4745
-
4746
- class AXMLockEvaluatorScopeProvider {
4747
- constructor() {
4748
- this.lockService = inject(AXPLockService, {
4749
- optional: true,
4750
- });
4751
- }
4752
- async provide(context) {
4753
- context.addScope('lock', {
4754
- check: async (refId, refType) => {
4755
- if (this.lockService) {
4756
- const lock = await this.lockService.check({
4757
- refId, refType
4758
- });
4759
- return lock;
4760
- }
4761
- return false;
4762
- }
4763
- });
4764
- }
4765
- }
4766
-
4767
- class AXMLockSystemModule {
4768
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4769
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, imports: [i1.AXPWorkflowModule] }); }
4770
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, providers: [
4771
- { provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, multi: true, useClass: AXMLockEvaluatorScopeProvider },
4772
- // { provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: lockPlugin },
4773
- { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
4774
- ], imports: [AXPWorkflowModule.forChild({
4775
- actions: {
4776
- AXMLockPopupWorkflowAction,
4777
- AXMUnlockConfirmWorkflowAction,
4778
- },
4779
- workflows: {
4780
- 'lock-popup': AXMLockPopupWorkflow,
4781
- 'unlock-confirm': AXMUnlockConfirmWorkflow,
4782
- },
4783
- })] }); }
4784
- }
4785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMLockSystemModule, decorators: [{
4786
- type: NgModule,
4787
- args: [{
4788
- imports: [
4789
- AXPWorkflowModule.forChild({
4790
- actions: {
4791
- AXMLockPopupWorkflowAction,
4792
- AXMUnlockConfirmWorkflowAction,
4793
- },
4794
- workflows: {
4795
- 'lock-popup': AXMLockPopupWorkflow,
4796
- 'unlock-confirm': AXMUnlockConfirmWorkflow,
4797
- },
4798
- }),
4799
- ],
4800
- providers: [
4801
- { provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, multi: true, useClass: AXMLockEvaluatorScopeProvider },
4802
- // { provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: lockPlugin },
4803
- { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
4804
- ],
4805
- }]
4806
- }] });
4807
-
4808
- const namePlugin = {
4809
- name: 'name',
4810
- order: 20,
4811
- apply: (ctx, options) => {
4812
- const title = options?.title ?? '@general:terms.common.name';
4813
- const groupId = options?.groupId ?? 'basic-info';
4814
- const required = options?.required ?? false;
4815
- const addColumn = options?.column ?? true;
4816
- //#region ---- Ensure Basic Info Group ----
4817
- const groups = ctx.groups.list() ?? [];
4818
- if (!groups.some((g) => g.id === groupId)) {
4819
- ctx.groups.add({ id: groupId, title: '@general:terms.interface.basic-info' });
4820
- }
4821
- //#endregion
4822
- //#region ---- Add Name Property ----
4823
- const props = ctx.properties.list();
4824
- if (!props.some((p) => p.name === 'name')) {
4825
- ctx.properties.add({
4826
- name: 'name',
4827
- title,
4828
- groupId,
4829
- schema: {
4830
- dataType: 'string',
4831
- interface: {
4832
- type: AXPWidgetsList.Editors.TextBox,
4833
- },
4834
- },
4835
- validations: required
4836
- ? [
4837
- {
4838
- rule: 'required',
4839
- },
4840
- ]
4841
- : [],
4842
- options: {
4843
- sort: { enabled: true },
4844
- filter: {
4845
- advance: { enabled: true },
4846
- inline: { enabled: true },
4847
- },
4848
- },
4849
- });
4850
- }
4851
- //#endregion
4852
- //#region ---- Add Name Column ----
4853
- if (addColumn) {
4854
- const columns = ctx.columns.list() ?? [];
4855
- if (!columns.some((c) => c.name === 'name')) {
4856
- ctx.columns.add({
4857
- name: 'name',
4858
- title,
4859
- options: {
4860
- width: '200px',
4861
- visible: true,
4862
- },
4863
- sort: {
4864
- enabled: true,
4865
- },
4866
- });
4867
- }
4868
- }
4869
- //#endregion
4870
- //#region ---- Update Interface Layouts ----
4871
- const ensureLayoutProperty = (layout) => {
4872
- layout.sections = layout.sections ?? [];
4873
- if (!layout.sections.some((s) => s.id === groupId)) {
4874
- layout.sections.push({ id: groupId, order: 10 });
4875
- }
4876
- layout.properties = layout.properties ?? [];
4877
- if (!layout.properties.some((p) => p.name === 'name')) {
4878
- layout.properties.push({
4879
- name: 'name',
4880
- layout: {
4881
- positions: { lg: { colSpan: 12, order: 10 } },
4882
- },
4883
- });
4884
- }
4885
- return layout;
4886
- };
4887
- ctx.interfaces.master.create.update((create) => ensureLayoutProperty((create ?? { sections: [], properties: [] })));
4888
- ctx.interfaces.master.modify.update((modify) => ensureLayoutProperty((modify ?? { sections: [], properties: [] })));
4889
- ctx.interfaces.master.single.update((single) => ensureLayoutProperty((single ?? { title: ctx.entity.title, sections: [], properties: [] })));
4890
- //#endregion
4891
- },
4892
- };
4893
-
4894
- class AXPNamePluginModule {
4895
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4896
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule }); }
4897
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: namePlugin }] }); }
4898
- }
4899
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNamePluginModule, decorators: [{
4900
- type: NgModule,
4901
- args: [{
4902
- declarations: [],
4903
- imports: [],
4904
- exports: [],
4905
- providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: namePlugin }],
4906
- }]
4907
- }] });
4908
-
4909
- const notesPlugin = {
4910
- name: 'notes',
4911
- order: 22,
4912
- apply: (ctx, options) => {
4913
- const title = options?.title ?? '@general:terms.common.notes';
4914
- const groupId = options?.groupId ?? 'additional-info';
4915
- const addColumn = options?.column ?? true;
4916
- //#region ---- Ensure Additional Info Group ----
4917
- const groups = ctx.groups.list() ?? [];
4918
- if (!groups.some((g) => g.id === groupId)) {
4919
- ctx.groups.add({ id: groupId, title: '@general:terms.interface.additional-info' });
4920
- }
4921
- //#endregion
4922
- //#region ---- Add Notes Property ----
4923
- const props = ctx.properties.list();
4924
- if (!props.some((p) => p.name === 'notes')) {
4925
- ctx.properties.add({
4926
- name: 'notes',
4927
- title,
4928
- groupId,
4929
- schema: {
4930
- dataType: 'string',
4931
- interface: {
4932
- type: AXPWidgetsList.Editors.LargeTextBox,
4933
- options: {
4934
- rows: 4,
4935
- },
4936
- },
4937
- },
4938
- validations: [],
4939
- options: {
4940
- sort: { enabled: false },
4941
- filter: {
4942
- advance: { enabled: true },
4943
- inline: { enabled: false },
4944
- },
4945
- },
4946
- });
4947
- }
4948
- //#endregion
4949
- //#region ---- Add Notes Column ----
4950
- if (addColumn) {
4951
- const columns = ctx.columns.list() ?? [];
4952
- if (!columns.some((c) => c.name === 'notes')) {
4953
- ctx.columns.add({
4954
- name: 'notes',
4955
- title,
4956
- options: {
4957
- width: '300px',
4958
- visible: false,
4959
- },
4960
- });
4961
- }
4962
- }
4963
- //#endregion
4964
- //#region ---- Update Interface Layouts ----
4965
- const ensureLayoutProperty = (layout) => {
4966
- layout.sections = layout.sections ?? [];
4967
- if (!layout.sections.some((s) => s.id === groupId)) {
4968
- layout.sections.push({ id: groupId, order: 10 });
4969
- }
4970
- layout.properties = layout.properties ?? [];
4971
- if (!layout.properties.some((p) => p.name === 'notes')) {
4972
- layout.properties.push({
4973
- name: 'notes',
4974
- layout: {
4975
- positions: { lg: { colSpan: 12, order: 40 } },
4976
- },
4977
- });
4978
- }
4979
- return layout;
4980
- };
4981
- ctx.interfaces.master.create.update((create) => ensureLayoutProperty((create ?? { sections: [], properties: [] })));
4982
- ctx.interfaces.master.modify.update((modify) => ensureLayoutProperty((modify ?? { sections: [], properties: [] })));
4983
- ctx.interfaces.master.single.update((single) => ensureLayoutProperty((single ?? { title: ctx.entity.title, sections: [], properties: [] })));
4984
- //#endregion
4985
- },
4986
- };
4987
-
4988
- class AXPNotesPluginModule {
4989
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4990
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule }); }
4991
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: notesPlugin }] }); }
4992
- }
4993
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPNotesPluginModule, decorators: [{
4994
- type: NgModule,
4995
- args: [{
4996
- declarations: [],
4997
- imports: [],
4998
- exports: [],
4999
- providers: [{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: notesPlugin }],
5000
- }]
5001
- }] });
5002
-
5003
- const primaryPlugin = {
5004
- name: 'primary',
5005
- order: 66,
5006
- apply: (ctx) => {
5007
- ensureListActions(ctx);
5008
- //#region ---- Add isPrimary Property ----
5009
- // Ensure settings group exists
5010
- const groupId = 'settings';
5011
- const groups = ctx.groups.list() ?? [];
5012
- if (!groups.some((g) => g.id === groupId)) {
5013
- ctx.groups.add({ id: groupId, title: '@general:terms.interface.settings' });
4724
+ const primaryPlugin = {
4725
+ name: 'primary',
4726
+ order: 66,
4727
+ apply: (ctx) => {
4728
+ ensureListActions(ctx);
4729
+ //#region ---- Add isPrimary Property ----
4730
+ // Ensure settings group exists
4731
+ const groupId = 'settings';
4732
+ const groups = ctx.groups.list() ?? [];
4733
+ if (!groups.some((g) => g.id === groupId)) {
4734
+ ctx.groups.add({ id: groupId, title: '@general:terms.interface.settings' });
5014
4735
  }
5015
4736
  // Add isPrimary property if it doesn't exist
5016
4737
  const props = ctx.properties.list();
@@ -5865,7 +5586,7 @@ class AXMVersionHistoryPopupStartAction extends AXPWorkflowAction {
5865
5586
  this.translate = inject(AXTranslationService);
5866
5587
  }
5867
5588
  async execute(context) {
5868
- const comp = (await import('./acorex-modules-common-timeline-version-history-popup.component-J28i59f7.mjs')).AXMTimelineVersionHistoryPopupComponent;
5589
+ const comp = (await import('./acorex-modules-common-timeline-version-history-popup.component-DoTh8TG9.mjs')).AXMTimelineVersionHistoryPopupComponent;
5869
5590
  this.popupService.open(comp, {
5870
5591
  title: await this.translate.translateAsync('@activity-log:actions.view-history.title'),
5871
5592
  data: {
@@ -6064,7 +5785,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
6064
5785
  */
6065
5786
  class AXPValidationRulesModule {
6066
5787
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPValidationRulesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6067
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPValidationRulesModule, imports: [i1$6.AXValidationModule] }); }
5788
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPValidationRulesModule, imports: [i1$4.AXValidationModule] }); }
6068
5789
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPValidationRulesModule, imports: [AXValidationModule.forChild({
6069
5790
  rules: [VariableNameValidationRule],
6070
5791
  })] }); }
@@ -6373,6 +6094,16 @@ class AXMFilterOperatorEvaluatorScopeProvider {
6373
6094
  }
6374
6095
  }
6375
6096
 
6097
+ const AXPCommonFeatureKeys = {
6098
+ GlobalSearch: 'Common:Feature:GlobalSearch',
6099
+ AdvancedExport: 'Common:Feature:AdvancedExport',
6100
+ ActivityLog: 'Common:Feature:ActivityLog',
6101
+ DataImport: 'Common:Feature:DataImport',
6102
+ BulkOperations: 'Common:Feature:BulkOperations',
6103
+ AdvancedFiltering: 'Common:Feature:AdvancedFiltering',
6104
+ DataSynchronization: 'Common:Feature:DataSynchronization',
6105
+ };
6106
+
6376
6107
  //#region ---- Imports ----
6377
6108
  //#endregion
6378
6109
  //#region ---- Feature Definition Provider ----
@@ -6567,7 +6298,7 @@ class AXMCommonModule {
6567
6298
  AXPAvatarPluginModule,
6568
6299
  //#endregion
6569
6300
  //#region ---- Feature Modules ----
6570
- AXPGlobalSearchModule,
6301
+ // AXPGlobalSearchModule,
6571
6302
  AXPCompareModule,
6572
6303
  AXPStatusPluginModule,
6573
6304
  AXPComputedPropertiesModule,
@@ -6673,7 +6404,7 @@ class AXMCommonModule {
6673
6404
  AXPAvatarPluginModule,
6674
6405
  //#endregion
6675
6406
  //#region ---- Feature Modules ----
6676
- AXPGlobalSearchModule,
6407
+ // AXPGlobalSearchModule,
6677
6408
  AXPCompareModule,
6678
6409
  AXPStatusPluginModule,
6679
6410
  AXPComputedPropertiesModule,
@@ -6683,122 +6414,391 @@ class AXMCommonModule {
6683
6414
  AXPWidgetsModule,
6684
6415
  AXMCommonMiddlewaresModule] }); }
6685
6416
  }
6686
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMCommonModule, decorators: [{
6417
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXMCommonModule, decorators: [{
6418
+ type: NgModule,
6419
+ args: [{
6420
+ imports: [
6421
+ //#region ---- Extension & System Plugins ----
6422
+ AXPCategoryModule,
6423
+ AXMLockSystemModule,
6424
+ AXPVersionHistoryModule,
6425
+ AXPAuditInfoPluginModule,
6426
+ //#endregion
6427
+ //#region ---- Operation Plugins ----
6428
+ AXPClonePluginModule,
6429
+ //#endregion
6430
+ //#region ---- Status Management Plugins ----
6431
+ AXPArchivePluginModule,
6432
+ AXPDisablePluginModule,
6433
+ AXPDefaultPluginModule,
6434
+ AXPPrimaryPluginModule,
6435
+ AXPUniqueFieldsPluginModule,
6436
+ //#endregion
6437
+ //#region ---- Property Plugins ----
6438
+ AXPNamePluginModule,
6439
+ AXPTitlePluginModule,
6440
+ AXPNotesPluginModule,
6441
+ AXPDescriptionPluginModule,
6442
+ AXPIconPluginModule,
6443
+ AXPColorPluginModule,
6444
+ AXPAvatarPluginModule,
6445
+ //#endregion
6446
+ //#region ---- Feature Modules ----
6447
+ // AXPGlobalSearchModule,
6448
+ AXPCompareModule,
6449
+ AXPStatusPluginModule,
6450
+ AXPComputedPropertiesModule,
6451
+ AXPValidationRulesModule,
6452
+ //#endregion
6453
+ //#region ---- Platform Modules ----
6454
+ AXPWidgetsModule,
6455
+ AXMCommonMiddlewaresModule,
6456
+ //#endregion
6457
+ ],
6458
+ exports: [],
6459
+ declarations: [],
6460
+ providers: [
6461
+ //#region ---- Menu Provider ----
6462
+ {
6463
+ provide: AXP_MENU_PROVIDER,
6464
+ useClass: AXMMenuProvider,
6465
+ multi: true,
6466
+ },
6467
+ //#endregion
6468
+ //#region ---- Settings Provider ----
6469
+ {
6470
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
6471
+ useClass: AXMSettingProvider,
6472
+ multi: true,
6473
+ },
6474
+ //#endregion
6475
+ //#region ---- Expression Evaluator Scope Providers ----
6476
+ {
6477
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6478
+ useClass: AXPDateTimeEvaluatorScopeProvider,
6479
+ multi: true,
6480
+ },
6481
+ {
6482
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6483
+ useClass: AXPTranslateEvaluatorScopeProvider,
6484
+ multi: true,
6485
+ },
6486
+ {
6487
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6488
+ useClass: AXMFilterOperatorEvaluatorScopeProvider,
6489
+ multi: true,
6490
+ },
6491
+ //#endregion
6492
+ //#region ---- Status Providers ----
6493
+ {
6494
+ provide: AXP_STATUS_PROVIDERS,
6495
+ useClass: TaskStatusProvider,
6496
+ multi: true,
6497
+ },
6498
+ {
6499
+ provide: AXP_STATUS_PROVIDERS,
6500
+ useClass: ApprovalStatusProvider,
6501
+ multi: true,
6502
+ },
6503
+ {
6504
+ provide: AXP_STATUS_PROVIDERS,
6505
+ useClass: StateStatusProvider,
6506
+ multi: true,
6507
+ },
6508
+ //#endregion
6509
+ //#region ---- Module Manifest Provider ----
6510
+ {
6511
+ provide: AXP_MODULE_MANIFEST_PROVIDER,
6512
+ useValue: CommonManifest,
6513
+ multi: true,
6514
+ },
6515
+ //#endregion
6516
+ //#region ---- Feature Definition Provider ----
6517
+ {
6518
+ provide: AXP_FEATURE_DEFINITION_PROVIDER,
6519
+ useClass: AXPCommonFeatureDefinitionProvider,
6520
+ multi: true,
6521
+ },
6522
+ //#endregion
6523
+ //#region ---- Multi-Source Definition Provider ----
6524
+ {
6525
+ provide: AXP_MULTI_SOURCE_DEFINITION_PROVIDER,
6526
+ useClass: AXCAssignmentMultiSourceDefinitionProvider,
6527
+ multi: true,
6528
+ },
6529
+ //#endregion
6530
+ ],
6531
+ }]
6532
+ }] });
6533
+
6534
+ const AXP_GLOBAL_SEARCH_CONFIG_TOKEN = new InjectionToken('AXP_GLOBAL_SEARCH_CONFIG_TOKEN');
6535
+
6536
+ class AXPGlobalSearchSlotComponent {
6537
+ constructor() {
6538
+ this.workflow = inject(AXPWorkflowService);
6539
+ }
6540
+ async startSearch() {
6541
+ await this.workflow.execute('global-search');
6542
+ }
6543
+ async handleKeyboardEvent(event) {
6544
+ if (event.ctrlKey) {
6545
+ switch (event.code) {
6546
+ case 'KeyK':
6547
+ event.preventDefault();
6548
+ event.stopPropagation();
6549
+ await this.startSearch();
6550
+ break;
6551
+ }
6552
+ }
6553
+ }
6554
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6555
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: AXPGlobalSearchSlotComponent, isStandalone: true, selector: "ng-component", host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, ngImport: i0, template: `
6556
+ <ax-button color="primary" class="ax-flex md:ax-hidden" (onClick)="startSearch()">
6557
+ <ax-icon class="fa-regular fa-search">
6558
+ </ax-icon>
6559
+ </ax-button>
6560
+ <div class="ax-bg-primary-200/15 ax-h-10 ax-w-72 ax-rounded-default ax-cursor-pointer ax-justify-between ax-hidden md:ax-flex ax-items-center ax-px-3 hover:ax-bg-primary-200/30 ax-text-primary-text" (click)="startSearch()">
6561
+ <div class="ax-flex ax-items-center ax-gap-2">
6562
+ <i class="fa-light fa-search ax-text-xl"></i>
6563
+ <span>{{ '@global-search:terms.search-placeholder' | translate | async}}</span>
6564
+ </div>
6565
+ <kbd class="ax-text-sm">Ctrl+K</kbd>
6566
+ </div>
6567
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i1$3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }] }); }
6568
+ }
6569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchSlotComponent, decorators: [{
6570
+ type: Component,
6571
+ args: [{
6572
+ template: `
6573
+ <ax-button color="primary" class="ax-flex md:ax-hidden" (onClick)="startSearch()">
6574
+ <ax-icon class="fa-regular fa-search">
6575
+ </ax-icon>
6576
+ </ax-button>
6577
+ <div class="ax-bg-primary-200/15 ax-h-10 ax-w-72 ax-rounded-default ax-cursor-pointer ax-justify-between ax-hidden md:ax-flex ax-items-center ax-px-3 hover:ax-bg-primary-200/30 ax-text-primary-text" (click)="startSearch()">
6578
+ <div class="ax-flex ax-items-center ax-gap-2">
6579
+ <i class="fa-light fa-search ax-text-xl"></i>
6580
+ <span>{{ '@global-search:terms.search-placeholder' | translate | async}}</span>
6581
+ </div>
6582
+ <kbd class="ax-text-sm">Ctrl+K</kbd>
6583
+ </div>
6584
+ `,
6585
+ imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXTranslationModule, AXTextBoxModule]
6586
+ }]
6587
+ }], propDecorators: { handleKeyboardEvent: [{
6588
+ type: HostListener,
6589
+ args: ['document:keydown', ['$event']]
6590
+ }] } });
6591
+
6592
+ class AXPGlobalSearchStartAction extends AXPWorkflowAction {
6593
+ constructor() {
6594
+ super(...arguments);
6595
+ this.popupService = inject(AXPopupService);
6596
+ this.workflow = inject(AXPWorkflowService);
6597
+ this.config = inject(AXP_GLOBAL_SEARCH_CONFIG_TOKEN);
6598
+ }
6599
+ async execute(context) {
6600
+ const component = await this.config.window();
6601
+ const popup = await this.popupService.open(component, {
6602
+ title: 'Search...',
6603
+ size: 'fit',
6604
+ closeOnBackdropClick: true,
6605
+ data: {
6606
+ text: context.getVariable('text'),
6607
+ },
6608
+ header: false,
6609
+ });
6610
+ if (popup.data) {
6611
+ const result = popup.data;
6612
+ if (result && result.command) {
6613
+ this.workflow.execute(result.command?.name, result.command?.options);
6614
+ }
6615
+ }
6616
+ }
6617
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
6618
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction }); }
6619
+ }
6620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchStartAction, decorators: [{
6621
+ type: Injectable
6622
+ }] });
6623
+ const AXPGlobalSearchWorkflow = {
6624
+ startStepId: 'start',
6625
+ steps: {
6626
+ start: {
6627
+ action: 'AXPGlobalSearchStartAction',
6628
+ },
6629
+ },
6630
+ };
6631
+
6632
+ class AXPGlobalSearchModule {
6633
+ constructor(appInitService, injector) {
6634
+ }
6635
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, deps: [{ token: i1$5.AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
6636
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, imports: [i1$5.AXPComponentSlotModule, i1.AXPWorkflowModule] }); }
6637
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, providers: [
6638
+ {
6639
+ provide: AXP_GLOBAL_SEARCH_CONFIG_TOKEN,
6640
+ useValue: {
6641
+ window: () => import('./acorex-modules-common-search-popup.component-WrMDy-u_.mjs').then((c) => c.AXPGlobalSearchPopupComponent),
6642
+ },
6643
+ },
6644
+ ], imports: [AXPComponentSlotModule.forChild({
6645
+ 'root-header-start': [
6646
+ {
6647
+ priority: 0,
6648
+ name: 'search',
6649
+ component: AXPGlobalSearchSlotComponent,
6650
+ features: [AXPCommonFeatureKeys.GlobalSearch],
6651
+ },
6652
+ ],
6653
+ }),
6654
+ //
6655
+ AXPWorkflowModule.forChild({
6656
+ actions: {
6657
+ AXPGlobalSearchStartAction
6658
+ },
6659
+ workflows: {
6660
+ 'global-search': AXPGlobalSearchWorkflow,
6661
+ },
6662
+ })] }); }
6663
+ }
6664
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPGlobalSearchModule, decorators: [{
6687
6665
  type: NgModule,
6688
6666
  args: [{
6689
6667
  imports: [
6690
- //#region ---- Extension & System Plugins ----
6691
- AXPCategoryModule,
6692
- AXMLockSystemModule,
6693
- AXPVersionHistoryModule,
6694
- AXPAuditInfoPluginModule,
6695
- //#endregion
6696
- //#region ---- Operation Plugins ----
6697
- AXPClonePluginModule,
6698
- //#endregion
6699
- //#region ---- Status Management Plugins ----
6700
- AXPArchivePluginModule,
6701
- AXPDisablePluginModule,
6702
- AXPDefaultPluginModule,
6703
- AXPPrimaryPluginModule,
6704
- AXPUniqueFieldsPluginModule,
6705
- //#endregion
6706
- //#region ---- Property Plugins ----
6707
- AXPNamePluginModule,
6708
- AXPTitlePluginModule,
6709
- AXPNotesPluginModule,
6710
- AXPDescriptionPluginModule,
6711
- AXPIconPluginModule,
6712
- AXPColorPluginModule,
6713
- AXPAvatarPluginModule,
6714
- //#endregion
6715
- //#region ---- Feature Modules ----
6716
- AXPGlobalSearchModule,
6717
- AXPCompareModule,
6718
- AXPStatusPluginModule,
6719
- AXPComputedPropertiesModule,
6720
- AXPValidationRulesModule,
6721
- //#endregion
6722
- //#region ---- Platform Modules ----
6723
- AXPWidgetsModule,
6724
- AXMCommonMiddlewaresModule,
6725
- //#endregion
6668
+ AXPComponentSlotModule.forChild({
6669
+ 'root-header-start': [
6670
+ {
6671
+ priority: 0,
6672
+ name: 'search',
6673
+ component: AXPGlobalSearchSlotComponent,
6674
+ features: [AXPCommonFeatureKeys.GlobalSearch],
6675
+ },
6676
+ ],
6677
+ }),
6678
+ //
6679
+ AXPWorkflowModule.forChild({
6680
+ actions: {
6681
+ AXPGlobalSearchStartAction
6682
+ },
6683
+ workflows: {
6684
+ 'global-search': AXPGlobalSearchWorkflow,
6685
+ },
6686
+ })
6726
6687
  ],
6727
6688
  exports: [],
6728
6689
  declarations: [],
6729
6690
  providers: [
6730
- //#region ---- Menu Provider ----
6731
- {
6732
- provide: AXP_MENU_PROVIDER,
6733
- useClass: AXMMenuProvider,
6734
- multi: true,
6735
- },
6736
- //#endregion
6737
- //#region ---- Settings Provider ----
6738
- {
6739
- provide: AXP_SETTING_DEFINITION_PROVIDER,
6740
- useClass: AXMSettingProvider,
6741
- multi: true,
6742
- },
6743
- //#endregion
6744
- //#region ---- Expression Evaluator Scope Providers ----
6745
- {
6746
- provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6747
- useClass: AXPDateTimeEvaluatorScopeProvider,
6748
- multi: true,
6749
- },
6750
- {
6751
- provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6752
- useClass: AXPTranslateEvaluatorScopeProvider,
6753
- multi: true,
6754
- },
6755
- {
6756
- provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
6757
- useClass: AXMFilterOperatorEvaluatorScopeProvider,
6758
- multi: true,
6759
- },
6760
- //#endregion
6761
- //#region ---- Status Providers ----
6762
- {
6763
- provide: AXP_STATUS_PROVIDERS,
6764
- useClass: TaskStatusProvider,
6765
- multi: true,
6766
- },
6767
- {
6768
- provide: AXP_STATUS_PROVIDERS,
6769
- useClass: ApprovalStatusProvider,
6770
- multi: true,
6771
- },
6772
- {
6773
- provide: AXP_STATUS_PROVIDERS,
6774
- useClass: StateStatusProvider,
6775
- multi: true,
6776
- },
6777
- //#endregion
6778
- //#region ---- Module Manifest Provider ----
6779
- {
6780
- provide: AXP_MODULE_MANIFEST_PROVIDER,
6781
- useValue: CommonManifest,
6782
- multi: true,
6783
- },
6784
- //#endregion
6785
- //#region ---- Feature Definition Provider ----
6786
6691
  {
6787
- provide: AXP_FEATURE_DEFINITION_PROVIDER,
6788
- useClass: AXPCommonFeatureDefinitionProvider,
6789
- multi: true,
6790
- },
6791
- //#endregion
6792
- //#region ---- Multi-Source Definition Provider ----
6793
- {
6794
- provide: AXP_MULTI_SOURCE_DEFINITION_PROVIDER,
6795
- useClass: AXCAssignmentMultiSourceDefinitionProvider,
6796
- multi: true,
6692
+ provide: AXP_GLOBAL_SEARCH_CONFIG_TOKEN,
6693
+ useValue: {
6694
+ window: () => import('./acorex-modules-common-search-popup.component-WrMDy-u_.mjs').then((c) => c.AXPGlobalSearchPopupComponent),
6695
+ },
6797
6696
  },
6798
- //#endregion
6799
- ],
6697
+ ]
6800
6698
  }]
6801
- }] });
6699
+ }], ctorParameters: () => [{ type: i1$5.AXPAppStartUpService }, { type: i0.Injector }] });
6700
+
6701
+ class AXPGlobalSearchViewModel {
6702
+ constructor() {
6703
+ this.settingKeys = {
6704
+ recent: "global-search:recents:items",
6705
+ pinned: "global-search:pinned:items"
6706
+ };
6707
+ this.searchService = inject(AXPSearchService);
6708
+ this.settingsService = inject(AXPSettingsService);
6709
+ this._text = signal(null, ...(ngDevMode ? [{ debugName: "_text" }] : []));
6710
+ this.text = this._text.asReadonly();
6711
+ this._results = signal([], ...(ngDevMode ? [{ debugName: "_results" }] : []));
6712
+ this.results = this._results.asReadonly();
6713
+ this._isBusy = signal(false, ...(ngDevMode ? [{ debugName: "_isBusy" }] : []));
6714
+ this.isBusy = this._isBusy.asReadonly();
6715
+ this.isEmpty = computed(() => this.text() && this.results().length == 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
6716
+ this.isValid = computed(() => (this.text()?.length ?? 0) > 2, ...(ngDevMode ? [{ debugName: "isValid" }] : []));
6717
+ this.isStart = computed(() => !this.isEmpty() && this.results().length == 0, ...(ngDevMode ? [{ debugName: "isStart" }] : []));
6718
+ this.isWelcome = computed(() => this.isStart() && this.pinnedItems().length == 0 && this.recentItems().length == 0, ...(ngDevMode ? [{ debugName: "isWelcome" }] : []));
6719
+ this._recentItems = signal([], ...(ngDevMode ? [{ debugName: "_recentItems" }] : []));
6720
+ this._pinnedItems = signal([], ...(ngDevMode ? [{ debugName: "_pinnedItems" }] : []));
6721
+ this.pinnedItems = this._pinnedItems.asReadonly();
6722
+ this.recentItems = computed(() => this.getTopRecentItems(), ...(ngDevMode ? [{ debugName: "recentItems" }] : []));
6723
+ this.onItemSelected = new Subject();
6724
+ this.loadSettings();
6725
+ }
6726
+ async search(text) {
6727
+ this._isBusy.set(true);
6728
+ this._text.set(text);
6729
+ if (!this.isValid()) {
6730
+ this._results.set([]);
6731
+ }
6732
+ else {
6733
+ await new Promise((resolve) => setTimeout(resolve, 250));
6734
+ const results = await this.searchService.search(text);
6735
+ this._results.set(results);
6736
+ }
6737
+ this._isBusy.set(false);
6738
+ }
6739
+ async execute(item) {
6740
+ this.onItemSelected.next(item);
6741
+ await this.updateSelectionHistory(item);
6742
+ }
6743
+ async pin(item) {
6744
+ const currentPinned = this._pinnedItems();
6745
+ if (!currentPinned.some(i => i.id === item.id)) {
6746
+ this._pinnedItems.set([item, ...currentPinned].slice(0, 5));
6747
+ await this.saveSettings();
6748
+ }
6749
+ }
6750
+ async unpin(item) {
6751
+ const currentPinned = this._pinnedItems();
6752
+ this._pinnedItems.set(currentPinned.filter(i => i.id !== item.id));
6753
+ await this.saveSettings();
6754
+ }
6755
+ async togglePin(item) {
6756
+ if (this.isPinned(item)) {
6757
+ await this.unpin(item);
6758
+ }
6759
+ else {
6760
+ await this.pin(item);
6761
+ }
6762
+ }
6763
+ isPinned(item) {
6764
+ const currentPinned = this._pinnedItems();
6765
+ return currentPinned.some(i => i.id === item.id);
6766
+ }
6767
+ async updateSelectionHistory(item) {
6768
+ // Update recent selections
6769
+ const currentHistory = this._recentItems();
6770
+ const updatedHistory = [item, ...currentHistory.filter(i => i.id !== item.id)].slice(0, 5);
6771
+ this._recentItems.set(updatedHistory);
6772
+ // Save updated settings
6773
+ await this.saveSettings();
6774
+ }
6775
+ getTopRecentItems() {
6776
+ const pinnedIds = new Set(this._pinnedItems().map(item => item.id));
6777
+ return this._recentItems().filter(item => !pinnedIds.has(item.id)).slice(0, 5);
6778
+ }
6779
+ async clearRecentItems() {
6780
+ this._recentItems.set([]);
6781
+ await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.recent, []);
6782
+ }
6783
+ async loadSettings() {
6784
+ // Load recent selections
6785
+ const recent = await this.settingsService.get(this.settingKeys.recent);
6786
+ if (recent) {
6787
+ this._recentItems.set(recent.slice(0, 5));
6788
+ }
6789
+ // Load pinned items
6790
+ const pinned = await this.settingsService.get(this.settingKeys.pinned);
6791
+ if (pinned) {
6792
+ this._pinnedItems.set(pinned.slice(0, 5));
6793
+ }
6794
+ }
6795
+ async saveSettings() {
6796
+ // Save recent selections
6797
+ await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.recent, this._recentItems().slice(0, 5));
6798
+ // Save pinned items
6799
+ await this.settingsService.scope(AXPPlatformScope.User).set(this.settingKeys.pinned, this._pinnedItems().slice(0, 5));
6800
+ }
6801
+ }
6802
6802
 
6803
6803
  //#region ---- Imports ----
6804
6804
  //#endregion