@acorex-platform/module-asset-management-client 0.0.20
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.
- package/fesm2022/acorex-platform-module-asset-management-client-asset-lifecycle.provider-BDaCpGsv.mjs +78 -0
- package/fesm2022/acorex-platform-module-asset-management-client-asset-lifecycle.provider-BDaCpGsv.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-asset-management-client-asset-rental-history-status.provider-DwhQPb0-.mjs +109 -0
- package/fesm2022/acorex-platform-module-asset-management-client-asset-rental-history-status.provider-DwhQPb0-.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-asset-management-client-contracts.mjs +257 -0
- package/fesm2022/acorex-platform-module-asset-management-client-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-asset-management-client-recalculate-asset-operational-status.activity-ueTauO_k.mjs +62 -0
- package/fesm2022/acorex-platform-module-asset-management-client-recalculate-asset-operational-status.activity-ueTauO_k.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-asset-management-client.mjs +2472 -0
- package/fesm2022/acorex-platform-module-asset-management-client.mjs.map +1 -0
- package/package.json +28 -0
- package/types/acorex-platform-module-asset-management-client-contracts.d.ts +441 -0
- package/types/acorex-platform-module-asset-management-client.d.ts +278 -0
|
@@ -0,0 +1,2472 @@
|
|
|
1
|
+
import { AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
|
|
2
|
+
import { AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_STATUS_PROVIDERS, AXPSearchCommandProvider, createEntityCommandOptions } from '@acorex-platform/framework-client/common';
|
|
3
|
+
import { AXP_MODULE_MANIFEST_PROVIDER, AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, provideLazyProvider, AXP_FEATURE_DEFINITION_PROVIDER, AXPDataGenerator } from '@acorex-platform/framework-client/core';
|
|
4
|
+
import { AXP_PAGE_COMPONENT_PROVIDER, AXPStandardSectionItemsBuilderComponent } from '@acorex-platform/framework-client/layout/components';
|
|
5
|
+
import { AXPMiddlewareAbortError, AXP_ENTITY_STORAGE_MIDDLEWARE, AXPEntityService } from '@acorex-platform/framework-client/layout/entity';
|
|
6
|
+
import { provideCommand, provideCommandSetups, AXPCommandService } from '@acorex-platform/framework-client/runtime';
|
|
7
|
+
import * as i0 from '@angular/core';
|
|
8
|
+
import { Injectable, NgModule, inject, input, output, viewChild, signal, computed, effect, ChangeDetectionStrategy, Component, untracked } from '@angular/core';
|
|
9
|
+
import * as contracts from '@acorex-platform/module-asset-management-client/contracts';
|
|
10
|
+
import { ASSET_CATALOG_SCOPE_BOOKING, RootConfig, AXMAssetManagementCommandKeys, AXMAssetManagementFeatureKeys, AXPAssetsMaintenancePermissionKeys, AXMAssetManagementMenuKeys, AXM_ASSET_STATUS_DEFINITION_KEY, AXMAssetStatus, ASSET_TYPE_COMPONENTS_PAGE_COMPONENT_KEY, AXMAssetLifecycleStatus } from '@acorex-platform/module-asset-management-client/contracts';
|
|
11
|
+
export * from '@acorex-platform/module-asset-management-client/contracts';
|
|
12
|
+
import { AXPCommonMenuKeys, AXPCommonPermissionGroupKeys } from '@acorex-platform/module-common-client/contracts';
|
|
13
|
+
import { AXPStatusProvider, AXPWidgetsCatalog } from '@acorex-platform/framework-shared/core';
|
|
14
|
+
import { merge, get, isEqual, cloneDeep, isString, defaultTo } from 'lodash';
|
|
15
|
+
import * as i1 from '@acorex/components/button';
|
|
16
|
+
import { AXButtonModule } from '@acorex/components/button';
|
|
17
|
+
import * as i2 from '@acorex/components/decorators';
|
|
18
|
+
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
19
|
+
import * as i4 from '@acorex/core/translation';
|
|
20
|
+
import { AXTranslationService, resolveMultiLanguageString, AXTranslationModule } from '@acorex/core/translation';
|
|
21
|
+
import { AXPLayoutBuilderService } from '@acorex-platform/framework-client/layout/builder';
|
|
22
|
+
import * as i3 from '@angular/common';
|
|
23
|
+
import { CommonModule } from '@angular/common';
|
|
24
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutBase } from '@acorex-platform/framework-client/layout/views';
|
|
25
|
+
|
|
26
|
+
function _mergeNamespaces(n, m) {
|
|
27
|
+
m.forEach(function (e) {
|
|
28
|
+
e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
|
|
29
|
+
if (k !== 'default' && !(k in n)) {
|
|
30
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
31
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () { return e[k]; }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
return Object.freeze(n);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region ---- Constants ----
|
|
43
|
+
const QUESTIONNAIRE = 'AssessmentManagement.Questionnaire';
|
|
44
|
+
const QUESTION_BANK_ITEM = 'AssessmentManagement.QuestionBankItem';
|
|
45
|
+
const WORKFLOW_DEFINITION = 'WorkflowManagement.WorkflowDefinition';
|
|
46
|
+
const ASSET_CATALOG_TARGETS = [QUESTIONNAIRE, QUESTION_BANK_ITEM, WORKFLOW_DEFINITION];
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region ---- Provider ----
|
|
49
|
+
class AXMAssetManagementCatalogScopeDefinitionProvider {
|
|
50
|
+
async items() {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
name: ASSET_CATALOG_SCOPE_BOOKING,
|
|
54
|
+
title: '@asset-management:catalog-scopes.booking.title',
|
|
55
|
+
description: '@asset-management:catalog-scopes.booking.description',
|
|
56
|
+
targets: [...ASSET_CATALOG_TARGETS],
|
|
57
|
+
icon: 'fa-light fa-calendar-check',
|
|
58
|
+
cssClass: 'primary-surface',
|
|
59
|
+
order: 25,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementCatalogScopeDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
64
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementCatalogScopeDefinitionProvider }); }
|
|
65
|
+
}
|
|
66
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementCatalogScopeDefinitionProvider, decorators: [{
|
|
67
|
+
type: Injectable
|
|
68
|
+
}] });
|
|
69
|
+
|
|
70
|
+
//#region ---- Imports ----
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region ---- Manifest Definition ----
|
|
73
|
+
/**
|
|
74
|
+
* Asset Management Module Manifest.
|
|
75
|
+
* Defines module metadata, features, and provider references.
|
|
76
|
+
*/
|
|
77
|
+
const AssetManagementManifest = {
|
|
78
|
+
name: RootConfig.module.name,
|
|
79
|
+
version: '1.0.0',
|
|
80
|
+
title: RootConfig.module.title,
|
|
81
|
+
icon: RootConfig.module.icon,
|
|
82
|
+
i18n: RootConfig.config.i18n,
|
|
83
|
+
type: 'domain',
|
|
84
|
+
domain: 'asset-maintenance',
|
|
85
|
+
required: false,
|
|
86
|
+
// Module dependencies (optional)
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
89
|
+
|
|
90
|
+
//#region ---- Imports ----
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region ---- Asset System Type Has Child Middleware ----
|
|
93
|
+
/**
|
|
94
|
+
* Enriches AssetSystemType query results with `hasChild` for hierarchical tree views.
|
|
95
|
+
* Uses `childrenCount` from the storage query pipeline when available.
|
|
96
|
+
*/
|
|
97
|
+
const assetSystemTypeHasChildMiddleware = {
|
|
98
|
+
target: {
|
|
99
|
+
ops: ['query', 'queryAll'],
|
|
100
|
+
entity: `${RootConfig.module.name}.${RootConfig.entities.assetSystemType.name}`,
|
|
101
|
+
order: 10,
|
|
102
|
+
},
|
|
103
|
+
execute: async (ctx, next) => {
|
|
104
|
+
await next();
|
|
105
|
+
if (!ctx.result?.items?.length) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
ctx.result = {
|
|
109
|
+
...ctx.result,
|
|
110
|
+
items: ctx.result.items.map((item) => ({
|
|
111
|
+
...item,
|
|
112
|
+
hasChild: (item.childrenCount ?? 0) > 0,
|
|
113
|
+
})),
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//#endregion
|
|
118
|
+
|
|
119
|
+
//#region ---- Imports ----
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region ---- Persist validation ----
|
|
122
|
+
function hasPartyId(value) {
|
|
123
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
124
|
+
}
|
|
125
|
+
function assertRentalPartyForDirection(data) {
|
|
126
|
+
if (data.rentalDirection === 'rentTo' && !hasPartyId(data.rentedToId)) {
|
|
127
|
+
throw new Error('@asset-management:assetRentalHistories.entities.assetRentalHistory.validations.rented-to-required');
|
|
128
|
+
}
|
|
129
|
+
if (data.rentalDirection === 'rentFrom' && !hasPartyId(data.rentedFromId)) {
|
|
130
|
+
throw new Error('@asset-management:assetRentalHistories.entities.assetRentalHistory.validations.rented-from-required');
|
|
131
|
+
}
|
|
132
|
+
if (!hasPartyId(data.rentedToId) && !hasPartyId(data.rentedFromId)) {
|
|
133
|
+
throw new Error('@asset-management:assetRentalHistories.entities.assetRentalHistory.validations.rental-party-required');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
|
|
138
|
+
//#region ---- Imports ----
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region ---- Asset Rental History Party Middleware ----
|
|
141
|
+
/**
|
|
142
|
+
* Ensures the supplier party matching rentalDirection is set, and clears the opposite party.
|
|
143
|
+
*/
|
|
144
|
+
const assetRentalHistoryPartyMiddleware = {
|
|
145
|
+
target: {
|
|
146
|
+
ops: ['create', 'update'],
|
|
147
|
+
entity: `${RootConfig.module.name}.${RootConfig.entities.assetRentalHistory.name}`,
|
|
148
|
+
order: 8,
|
|
149
|
+
},
|
|
150
|
+
execute: async (ctx, next) => {
|
|
151
|
+
if (!ctx.data || typeof ctx.data !== 'object') {
|
|
152
|
+
await next();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const incoming = ctx.data;
|
|
156
|
+
let previous = (ctx.previous ?? {});
|
|
157
|
+
if (ctx.op === 'update' && ctx.id != null && !ctx.previous) {
|
|
158
|
+
previous = (await ctx.backend.getOne(ctx.entityName, ctx.id).catch(() => ({})));
|
|
159
|
+
}
|
|
160
|
+
const merged = {
|
|
161
|
+
...previous,
|
|
162
|
+
...incoming,
|
|
163
|
+
};
|
|
164
|
+
if (merged.rentalDirection === 'rentTo') {
|
|
165
|
+
incoming.rentedFromId = null;
|
|
166
|
+
incoming.rentedFrom = undefined;
|
|
167
|
+
merged.rentedFromId = null;
|
|
168
|
+
merged.rentedFrom = undefined;
|
|
169
|
+
}
|
|
170
|
+
else if (merged.rentalDirection === 'rentFrom') {
|
|
171
|
+
incoming.rentedToId = null;
|
|
172
|
+
incoming.rentedTo = undefined;
|
|
173
|
+
merged.rentedToId = null;
|
|
174
|
+
merged.rentedTo = undefined;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
assertRentalPartyForDirection(merged);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
throw new AXPMiddlewareAbortError(error instanceof Error ? error.message : String(error), {
|
|
181
|
+
code: 'RENTAL_PARTY_REQUIRED',
|
|
182
|
+
status: 400,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
await next();
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
//#endregion
|
|
189
|
+
|
|
190
|
+
//#region ---- Middleware Exports ----
|
|
191
|
+
//#endregion
|
|
192
|
+
|
|
193
|
+
//#region ---- Imports ----
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region ---- Module ----
|
|
196
|
+
class AXMAssetManagementModule {
|
|
197
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
198
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementModule }); }
|
|
199
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementModule, providers: [
|
|
200
|
+
// Module Manifest Provider
|
|
201
|
+
{
|
|
202
|
+
provide: AXP_MODULE_MANIFEST_PROVIDER,
|
|
203
|
+
useValue: AssetManagementManifest,
|
|
204
|
+
multi: true,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
provide: AXP_CATALOG_SCOPE_DEFINITION_PROVIDER,
|
|
208
|
+
useClass: AXMAssetManagementCatalogScopeDefinitionProvider,
|
|
209
|
+
multi: true,
|
|
210
|
+
},
|
|
211
|
+
// Feature Definition Provider (lazy-loaded)
|
|
212
|
+
provideLazyProvider(AXP_FEATURE_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return featureDefinition_provider; }).then((m) => m.AXMAssetManagementFeatureDefinitionProvider)),
|
|
213
|
+
// Permission Definition Provider (lazy-loaded)
|
|
214
|
+
provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMAssetManagementPermissionDefinitionProvider)),
|
|
215
|
+
// Menu Provider (lazy-loaded)
|
|
216
|
+
provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMAssetManagementMenuProvider)),
|
|
217
|
+
// Entity Provider (lazy-loaded)
|
|
218
|
+
// Search Provider (lazy-loaded)
|
|
219
|
+
provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMAssetManagementSearchCommandProvider)),
|
|
220
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index; }).then((m) => m.AXMAssetTypeComponentsPageComponentProvider)),
|
|
221
|
+
provideCommand('AssetType:Components:Save', () => Promise.resolve().then(function () { return saveAssetTypeComponents_command; }).then((m) => m.AXMSaveAssetTypeComponentsCommand)),
|
|
222
|
+
provideCommand(AXMAssetManagementCommandKeys.AssetRentalHistory.RentFrom, () => Promise.resolve().then(function () { return createAssetRentalHistoryRent_commands; }).then((m) => m.AXMCreateAssetRentalHistoryRentFromCommand)),
|
|
223
|
+
provideCommand(AXMAssetManagementCommandKeys.AssetRentalHistory.RentTo, () => Promise.resolve().then(function () { return createAssetRentalHistoryRent_commands; }).then((m) => m.AXMCreateAssetRentalHistoryRentToCommand)),
|
|
224
|
+
provideCommandSetups([
|
|
225
|
+
{
|
|
226
|
+
key: AXMAssetManagementCommandKeys.WorkflowActivity.RecalculateOperationalStatus,
|
|
227
|
+
command: () => import('./acorex-platform-module-asset-management-client-recalculate-asset-operational-status.activity-ueTauO_k.mjs').then((c) => c.RecalculateAssetOperationalStatusActivity),
|
|
228
|
+
},
|
|
229
|
+
]),
|
|
230
|
+
// provideLazyProvider(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, () =>
|
|
231
|
+
// import('./features/asset-status.rules').then((m) => m.AXMAssetManagementAssetStatusRulesExpressionScopeProvider),
|
|
232
|
+
// ),
|
|
233
|
+
// Status Providers
|
|
234
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => Promise.resolve().then(function () { return assetStatus_provider; }).then((m) => m.AXMAssetManagementAssetStatusProvider)),
|
|
235
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-asset-management-client-asset-rental-history-status.provider-DwhQPb0-.mjs').then((m) => m.AXMAssetManagementAssetRentalHistoryStatusProvider)),
|
|
236
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-asset-management-client-asset-lifecycle.provider-BDaCpGsv.mjs').then((m) => m.AXMAssetManagementAssetLifecycleStatusProvider)),
|
|
237
|
+
{
|
|
238
|
+
provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
|
|
239
|
+
useValue: assetSystemTypeHasChildMiddleware,
|
|
240
|
+
multi: true,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
|
|
244
|
+
useValue: assetRentalHistoryPartyMiddleware,
|
|
245
|
+
multi: true,
|
|
246
|
+
},
|
|
247
|
+
] }); }
|
|
248
|
+
}
|
|
249
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementModule, decorators: [{
|
|
250
|
+
type: NgModule,
|
|
251
|
+
args: [{
|
|
252
|
+
imports: [],
|
|
253
|
+
providers: [
|
|
254
|
+
// Module Manifest Provider
|
|
255
|
+
{
|
|
256
|
+
provide: AXP_MODULE_MANIFEST_PROVIDER,
|
|
257
|
+
useValue: AssetManagementManifest,
|
|
258
|
+
multi: true,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
provide: AXP_CATALOG_SCOPE_DEFINITION_PROVIDER,
|
|
262
|
+
useClass: AXMAssetManagementCatalogScopeDefinitionProvider,
|
|
263
|
+
multi: true,
|
|
264
|
+
},
|
|
265
|
+
// Feature Definition Provider (lazy-loaded)
|
|
266
|
+
provideLazyProvider(AXP_FEATURE_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return featureDefinition_provider; }).then((m) => m.AXMAssetManagementFeatureDefinitionProvider)),
|
|
267
|
+
// Permission Definition Provider (lazy-loaded)
|
|
268
|
+
provideLazyProvider(AXP_PERMISSION_DEFINITION_PROVIDER, () => Promise.resolve().then(function () { return permissionDefinition_provider; }).then((m) => m.AXMAssetManagementPermissionDefinitionProvider)),
|
|
269
|
+
// Menu Provider (lazy-loaded)
|
|
270
|
+
provideLazyProvider(AXP_MENU_PROVIDER, () => Promise.resolve().then(function () { return menu_provider; }).then((m) => m.AXMAssetManagementMenuProvider)),
|
|
271
|
+
// Entity Provider (lazy-loaded)
|
|
272
|
+
// Search Provider (lazy-loaded)
|
|
273
|
+
provideLazyProvider(AXP_SEARCH_PROVIDER, () => Promise.resolve().then(function () { return searchCommand_provider; }).then((m) => m.AXMAssetManagementSearchCommandProvider)),
|
|
274
|
+
provideLazyProvider(AXP_PAGE_COMPONENT_PROVIDER, () => Promise.resolve().then(function () { return index; }).then((m) => m.AXMAssetTypeComponentsPageComponentProvider)),
|
|
275
|
+
provideCommand('AssetType:Components:Save', () => Promise.resolve().then(function () { return saveAssetTypeComponents_command; }).then((m) => m.AXMSaveAssetTypeComponentsCommand)),
|
|
276
|
+
provideCommand(AXMAssetManagementCommandKeys.AssetRentalHistory.RentFrom, () => Promise.resolve().then(function () { return createAssetRentalHistoryRent_commands; }).then((m) => m.AXMCreateAssetRentalHistoryRentFromCommand)),
|
|
277
|
+
provideCommand(AXMAssetManagementCommandKeys.AssetRentalHistory.RentTo, () => Promise.resolve().then(function () { return createAssetRentalHistoryRent_commands; }).then((m) => m.AXMCreateAssetRentalHistoryRentToCommand)),
|
|
278
|
+
provideCommandSetups([
|
|
279
|
+
{
|
|
280
|
+
key: AXMAssetManagementCommandKeys.WorkflowActivity.RecalculateOperationalStatus,
|
|
281
|
+
command: () => import('./acorex-platform-module-asset-management-client-recalculate-asset-operational-status.activity-ueTauO_k.mjs').then((c) => c.RecalculateAssetOperationalStatusActivity),
|
|
282
|
+
},
|
|
283
|
+
]),
|
|
284
|
+
// provideLazyProvider(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, () =>
|
|
285
|
+
// import('./features/asset-status.rules').then((m) => m.AXMAssetManagementAssetStatusRulesExpressionScopeProvider),
|
|
286
|
+
// ),
|
|
287
|
+
// Status Providers
|
|
288
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => Promise.resolve().then(function () { return assetStatus_provider; }).then((m) => m.AXMAssetManagementAssetStatusProvider)),
|
|
289
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-asset-management-client-asset-rental-history-status.provider-DwhQPb0-.mjs').then((m) => m.AXMAssetManagementAssetRentalHistoryStatusProvider)),
|
|
290
|
+
provideLazyProvider(AXP_STATUS_PROVIDERS, () => import('./acorex-platform-module-asset-management-client-asset-lifecycle.provider-BDaCpGsv.mjs').then((m) => m.AXMAssetManagementAssetLifecycleStatusProvider)),
|
|
291
|
+
{
|
|
292
|
+
provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
|
|
293
|
+
useValue: assetSystemTypeHasChildMiddleware,
|
|
294
|
+
multi: true,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
provide: AXP_ENTITY_STORAGE_MIDDLEWARE,
|
|
298
|
+
useValue: assetRentalHistoryPartyMiddleware,
|
|
299
|
+
multi: true,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
}]
|
|
303
|
+
}] });
|
|
304
|
+
|
|
305
|
+
//#region ---- Imports ----
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region ---- Feature Definition Provider ----
|
|
308
|
+
/**
|
|
309
|
+
* Asset Management Feature Definition Provider.
|
|
310
|
+
* Provides feature definitions for the Asset Management module.
|
|
311
|
+
*/
|
|
312
|
+
class AXMAssetManagementFeatureDefinitionProvider {
|
|
313
|
+
async provide(context) {
|
|
314
|
+
// Asset Management feature
|
|
315
|
+
context.addFeature(AXMAssetManagementFeatureKeys.AssetManagement, {
|
|
316
|
+
title: '@asset-management:features.asset-management.title',
|
|
317
|
+
description: '@asset-management:features.asset-management.description',
|
|
318
|
+
defaultValue: true,
|
|
319
|
+
type: 'boolean',
|
|
320
|
+
});
|
|
321
|
+
// // Advanced Maintenance feature
|
|
322
|
+
// context.addFeature(AXMAssetManagementFeatureKeys.AdvancedMaintenance, {
|
|
323
|
+
// title: '@asset-management:features.advanced-maintenance.title',
|
|
324
|
+
// description: '@asset-management:features.advanced-maintenance.description',
|
|
325
|
+
// defaultValue: false,
|
|
326
|
+
// type: 'boolean',
|
|
327
|
+
// });
|
|
328
|
+
// // Maintenance Scheduling feature
|
|
329
|
+
// context.addFeature(AXMAssetManagementFeatureKeys.MaintenanceScheduling, {
|
|
330
|
+
// title: '@asset-management:features.maintenance-scheduling.title',
|
|
331
|
+
// description: '@asset-management:features.maintenance-scheduling.description',
|
|
332
|
+
// defaultValue: true,
|
|
333
|
+
// type: 'boolean',
|
|
334
|
+
// });
|
|
335
|
+
// // Inspection Workflow feature
|
|
336
|
+
// context.addFeature(AXMAssetManagementFeatureKeys.InspectionWorkflow, {
|
|
337
|
+
// title: '@asset-management:features.inspection-workflow.title',
|
|
338
|
+
// description: '@asset-management:features.inspection-workflow.description',
|
|
339
|
+
// defaultValue: true,
|
|
340
|
+
// type: 'boolean',
|
|
341
|
+
// });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
//#endregion
|
|
345
|
+
|
|
346
|
+
var featureDefinition_provider = /*#__PURE__*/Object.freeze({
|
|
347
|
+
__proto__: null,
|
|
348
|
+
AXMAssetManagementFeatureDefinitionProvider: AXMAssetManagementFeatureDefinitionProvider
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
//#region ---- Imports ----
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region ---- Menu Provider ----
|
|
354
|
+
/**
|
|
355
|
+
* Asset Management Menu Provider.
|
|
356
|
+
* Provides menu items for the Asset Management module with permission and feature checks.
|
|
357
|
+
*/
|
|
358
|
+
class AXMAssetManagementMenuProvider {
|
|
359
|
+
constructor() {
|
|
360
|
+
this.entityService = inject(AXPEntityService);
|
|
361
|
+
}
|
|
362
|
+
async provide(context) {
|
|
363
|
+
const module = RootConfig.module;
|
|
364
|
+
const keys = AXPAssetsMaintenancePermissionKeys;
|
|
365
|
+
const PLAN_EQUIPMENT_MENU_KEY = 'Configuration:Menu:PlantEquipment';
|
|
366
|
+
context.find(AXPCommonMenuKeys.PlantEquipment).addItems([
|
|
367
|
+
{
|
|
368
|
+
name: AXMAssetManagementMenuKeys.Assets,
|
|
369
|
+
text: '@asset-management:assets.menus.root.title',
|
|
370
|
+
path: this.entityService.createPath(module.name, RootConfig.entities.asset.name),
|
|
371
|
+
priority: 2,
|
|
372
|
+
icon: RootConfig.entities.asset.icon,
|
|
373
|
+
policy: {
|
|
374
|
+
features: [module.name],
|
|
375
|
+
permissions: [keys.MaintainAssets],
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
name: AXMAssetManagementMenuKeys.AssetSystems,
|
|
380
|
+
text: '@asset-management:assetSystems.menus.root.title',
|
|
381
|
+
path: this.entityService.createPath(module.name, RootConfig.entities.assetSystem.name),
|
|
382
|
+
priority: 3,
|
|
383
|
+
icon: RootConfig.entities.assetSystem.icon,
|
|
384
|
+
policy: {
|
|
385
|
+
features: [module.name],
|
|
386
|
+
permissions: [keys.MaintainAssets],
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
]);
|
|
390
|
+
const mainAssetsMaintenanceDivider = context.find(AXMAssetManagementMenuKeys.MainPlanEquipmentAssetsMaintenanceDivider);
|
|
391
|
+
if (!mainAssetsMaintenanceDivider.exists) {
|
|
392
|
+
context.find(AXPCommonMenuKeys.PlantEquipment).addItems([
|
|
393
|
+
{
|
|
394
|
+
name: AXMAssetManagementMenuKeys.MainPlanEquipmentAssetsMaintenanceDivider,
|
|
395
|
+
text: '',
|
|
396
|
+
type: 'break',
|
|
397
|
+
priority: 10,
|
|
398
|
+
},
|
|
399
|
+
]);
|
|
400
|
+
}
|
|
401
|
+
const planEquipmentMenu = context.find(PLAN_EQUIPMENT_MENU_KEY);
|
|
402
|
+
if (!planEquipmentMenu.exists) {
|
|
403
|
+
context.find(AXPCommonMenuKeys.Configuration).addItems([
|
|
404
|
+
{
|
|
405
|
+
name: PLAN_EQUIPMENT_MENU_KEY,
|
|
406
|
+
priority: 9000,
|
|
407
|
+
text: '@general:menus.plan-equipment.title',
|
|
408
|
+
icon: module.icon,
|
|
409
|
+
},
|
|
410
|
+
]);
|
|
411
|
+
}
|
|
412
|
+
context.find(PLAN_EQUIPMENT_MENU_KEY).addItems([
|
|
413
|
+
{
|
|
414
|
+
name: AXMAssetManagementMenuKeys.AssetTypes,
|
|
415
|
+
text: '@asset-management:assetTypes.menus.root.title',
|
|
416
|
+
path: this.entityService.createPath(module.name, RootConfig.entities.assetType.name),
|
|
417
|
+
priority: 2,
|
|
418
|
+
icon: RootConfig.entities.assetType.icon,
|
|
419
|
+
policy: {
|
|
420
|
+
features: [module.name],
|
|
421
|
+
permissions: [keys.Setup],
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: AXMAssetManagementMenuKeys.AssetSystemTypes,
|
|
426
|
+
text: '@asset-management:assetSystemTypes.menus.root.title',
|
|
427
|
+
path: this.entityService.createPath(module.name, RootConfig.entities.assetSystemType.name),
|
|
428
|
+
priority: 3,
|
|
429
|
+
icon: RootConfig.entities.assetSystemType.icon,
|
|
430
|
+
policy: {
|
|
431
|
+
features: [module.name],
|
|
432
|
+
permissions: [keys.Setup],
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
]);
|
|
436
|
+
const planEquipmentAssetsMaintenanceDivider = context.find(AXMAssetManagementMenuKeys.PlanEquipmentAssetsMaintenanceDivider);
|
|
437
|
+
if (!planEquipmentAssetsMaintenanceDivider.exists) {
|
|
438
|
+
context.find(PLAN_EQUIPMENT_MENU_KEY).addItems([
|
|
439
|
+
{
|
|
440
|
+
name: AXMAssetManagementMenuKeys.PlanEquipmentAssetsMaintenanceDivider,
|
|
441
|
+
text: '',
|
|
442
|
+
type: 'break',
|
|
443
|
+
priority: 10,
|
|
444
|
+
},
|
|
445
|
+
]);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
//#endregion
|
|
450
|
+
|
|
451
|
+
var menu_provider = /*#__PURE__*/Object.freeze({
|
|
452
|
+
__proto__: null,
|
|
453
|
+
AXMAssetManagementMenuProvider: AXMAssetManagementMenuProvider
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region ----- Permission Definition Provider -----
|
|
458
|
+
/**
|
|
459
|
+
* Registers Assets & Maintenance capabilities owned by asset-management.
|
|
460
|
+
*/
|
|
461
|
+
class AXMAssetManagementPermissionDefinitionProvider {
|
|
462
|
+
async define(context) {
|
|
463
|
+
const keys = AXPAssetsMaintenancePermissionKeys;
|
|
464
|
+
const groups = AXPCommonPermissionGroupKeys;
|
|
465
|
+
const P = '@common:assets-maintenance.permissions';
|
|
466
|
+
const G = '@common:permission-groups';
|
|
467
|
+
context.addGroup(groups.AssetsMaintenance.Root, `${G}.assets-maintenance.title`, `${G}.assets-maintenance.description`, { order: 70 });
|
|
468
|
+
context
|
|
469
|
+
.addGroup(groups.AssetsMaintenance.Assets, `${G}.assets-maintenance-assets.title`, `${G}.assets-maintenance-assets.description`, { parent: groups.AssetsMaintenance.Root, order: 10 })
|
|
470
|
+
.addPermission(keys.Access, `${P}.access.title`, `${P}.access.description`)
|
|
471
|
+
.endPermission()
|
|
472
|
+
.addPermission(keys.MaintainAssets, `${P}.maintain-assets.title`, `${P}.maintain-assets.description`)
|
|
473
|
+
.endPermission()
|
|
474
|
+
.addPermission(keys.Setup, `${P}.setup.title`, `${P}.setup.description`)
|
|
475
|
+
.endPermission()
|
|
476
|
+
.endGroup();
|
|
477
|
+
}
|
|
478
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
479
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementPermissionDefinitionProvider }); }
|
|
480
|
+
}
|
|
481
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetManagementPermissionDefinitionProvider, decorators: [{
|
|
482
|
+
type: Injectable
|
|
483
|
+
}] });
|
|
484
|
+
|
|
485
|
+
var permissionDefinition_provider = /*#__PURE__*/Object.freeze({
|
|
486
|
+
__proto__: null,
|
|
487
|
+
AXMAssetManagementPermissionDefinitionProvider: AXMAssetManagementPermissionDefinitionProvider
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
//#region ---- Imports ----
|
|
491
|
+
//#endregion
|
|
492
|
+
//#region ---- Search Command Provider ----
|
|
493
|
+
class AXMAssetManagementSearchCommandProvider extends AXPSearchCommandProvider {
|
|
494
|
+
constructor() {
|
|
495
|
+
super(...arguments);
|
|
496
|
+
this.commands = [
|
|
497
|
+
{
|
|
498
|
+
id: 'create-asset',
|
|
499
|
+
group: 'command',
|
|
500
|
+
title: '@asset-management:assets.search.create-asset.title',
|
|
501
|
+
icon: RootConfig.entities.asset.icon,
|
|
502
|
+
description: '@asset-management:assets.search.create-asset.description',
|
|
503
|
+
command: {
|
|
504
|
+
name: 'Entity:Create',
|
|
505
|
+
options: createEntityCommandOptions(`${RootConfig.module.name}.${RootConfig.entities.asset.name}`, {
|
|
506
|
+
name: RootConfig.entities.asset.name,
|
|
507
|
+
module: RootConfig.module.name,
|
|
508
|
+
title: RootConfig.entities.asset.title,
|
|
509
|
+
}),
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
516
|
+
|
|
517
|
+
var searchCommand_provider = /*#__PURE__*/Object.freeze({
|
|
518
|
+
__proto__: null,
|
|
519
|
+
AXMAssetManagementSearchCommandProvider: AXMAssetManagementSearchCommandProvider
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
class AXMAssetManagementAssetStatusProvider extends AXPStatusProvider {
|
|
523
|
+
constructor() {
|
|
524
|
+
super(...arguments);
|
|
525
|
+
this.key = AXM_ASSET_STATUS_DEFINITION_KEY;
|
|
526
|
+
this.statuses = [
|
|
527
|
+
{
|
|
528
|
+
name: AXMAssetStatus.Available,
|
|
529
|
+
title: '@asset-management:assets.states.available',
|
|
530
|
+
icon: 'fa-light fa-circle-check',
|
|
531
|
+
color: 'success',
|
|
532
|
+
order: 1,
|
|
533
|
+
isInitial: true,
|
|
534
|
+
isFinal: false,
|
|
535
|
+
generateView: true,
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: AXMAssetStatus.Assigned,
|
|
539
|
+
title: '@asset-management:assets.states.assigned',
|
|
540
|
+
icon: 'fa-light fa-user-check',
|
|
541
|
+
color: 'info',
|
|
542
|
+
order: 2,
|
|
543
|
+
isInitial: false,
|
|
544
|
+
isFinal: false,
|
|
545
|
+
generateView: true,
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
name: AXMAssetStatus.UnderMaintenanceInspection,
|
|
549
|
+
title: '@asset-management:assets.states.under-maintenance',
|
|
550
|
+
icon: 'fa-light fa-toolbox',
|
|
551
|
+
color: 'warning',
|
|
552
|
+
order: 3,
|
|
553
|
+
isInitial: false,
|
|
554
|
+
isFinal: false,
|
|
555
|
+
generateView: true,
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
name: AXMAssetStatus.OutOfService,
|
|
559
|
+
title: '@asset-management:assets.states.out-of-service',
|
|
560
|
+
icon: 'fa-light fa-triangle-exclamation',
|
|
561
|
+
color: 'danger',
|
|
562
|
+
order: 4,
|
|
563
|
+
isInitial: false,
|
|
564
|
+
isFinal: false,
|
|
565
|
+
generateView: true,
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
name: AXMAssetStatus.Lost,
|
|
569
|
+
title: '@asset-management:assets.states.lost',
|
|
570
|
+
icon: 'fa-light fa-magnifying-glass-minus',
|
|
571
|
+
color: 'danger',
|
|
572
|
+
order: 5,
|
|
573
|
+
isInitial: false,
|
|
574
|
+
isFinal: false,
|
|
575
|
+
generateView: true,
|
|
576
|
+
},
|
|
577
|
+
];
|
|
578
|
+
this.transitions = [
|
|
579
|
+
{
|
|
580
|
+
from: AXMAssetStatus.Available,
|
|
581
|
+
to: AXMAssetStatus.Assigned,
|
|
582
|
+
title: '@asset-management:assets.transitions.assign',
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
from: AXMAssetStatus.Assigned,
|
|
586
|
+
to: AXMAssetStatus.Available,
|
|
587
|
+
title: '@asset-management:assets.transitions.unassign',
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
from: AXMAssetStatus.Available,
|
|
591
|
+
to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
592
|
+
title: '@asset-management:assets.transitions.start-maintenance',
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
from: AXMAssetStatus.Assigned,
|
|
596
|
+
to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
597
|
+
title: '@asset-management:assets.transitions.start-maintenance',
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
from: AXMAssetStatus.OutOfService,
|
|
601
|
+
to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
602
|
+
title: '@asset-management:assets.transitions.start-maintenance',
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
from: AXMAssetStatus.UnderMaintenanceInspection,
|
|
606
|
+
to: AXMAssetStatus.Available,
|
|
607
|
+
title: '@asset-management:assets.transitions.release-as-available',
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
from: AXMAssetStatus.UnderMaintenanceInspection,
|
|
611
|
+
to: AXMAssetStatus.Assigned,
|
|
612
|
+
title: '@asset-management:assets.transitions.restore-assignment',
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
from: AXMAssetStatus.UnderMaintenanceInspection,
|
|
616
|
+
to: AXMAssetStatus.OutOfService,
|
|
617
|
+
title: '@asset-management:assets.transitions.keep-out-of-service',
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
from: AXMAssetStatus.Available,
|
|
621
|
+
to: AXMAssetStatus.OutOfService,
|
|
622
|
+
title: '@asset-management:assets.transitions.mark-out-of-service',
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
from: AXMAssetStatus.Assigned,
|
|
626
|
+
to: AXMAssetStatus.OutOfService,
|
|
627
|
+
title: '@asset-management:assets.transitions.mark-out-of-service',
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
from: AXMAssetStatus.OutOfService,
|
|
631
|
+
to: AXMAssetStatus.Available,
|
|
632
|
+
title: '@asset-management:assets.transitions.restore-service',
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
from: AXMAssetStatus.OutOfService,
|
|
636
|
+
to: AXMAssetStatus.Assigned,
|
|
637
|
+
title: '@asset-management:assets.transitions.restore-service',
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
from: AXMAssetStatus.Available,
|
|
641
|
+
to: AXMAssetStatus.Lost,
|
|
642
|
+
title: '@asset-management:assets.transitions.mark-lost',
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
from: AXMAssetStatus.Assigned,
|
|
646
|
+
to: AXMAssetStatus.Lost,
|
|
647
|
+
title: '@asset-management:assets.transitions.mark-lost',
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
from: AXMAssetStatus.OutOfService,
|
|
651
|
+
to: AXMAssetStatus.Lost,
|
|
652
|
+
title: '@asset-management:assets.transitions.mark-lost',
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
from: AXMAssetStatus.UnderMaintenanceInspection,
|
|
656
|
+
to: AXMAssetStatus.Lost,
|
|
657
|
+
title: '@asset-management:assets.transitions.mark-lost',
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
from: AXMAssetStatus.Lost,
|
|
661
|
+
to: AXMAssetStatus.Available,
|
|
662
|
+
title: '@asset-management:assets.transitions.found',
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
from: AXMAssetStatus.Lost,
|
|
666
|
+
to: AXMAssetStatus.Assigned,
|
|
667
|
+
title: '@asset-management:assets.transitions.found',
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
from: AXMAssetStatus.Lost,
|
|
671
|
+
to: AXMAssetStatus.OutOfService,
|
|
672
|
+
title: '@asset-management:assets.transitions.found-out-of-service',
|
|
673
|
+
},
|
|
674
|
+
];
|
|
675
|
+
// readonly transitions: AXPStatusTransition[] = [
|
|
676
|
+
// {
|
|
677
|
+
// from: AXMAssetStatus.Available,
|
|
678
|
+
// to: AXMAssetStatus.Assigned,
|
|
679
|
+
// title: '@asset-management:assets.transitions.assign',
|
|
680
|
+
// },
|
|
681
|
+
// {
|
|
682
|
+
// from: AXMAssetStatus.Assigned,
|
|
683
|
+
// to: AXMAssetStatus.Available,
|
|
684
|
+
// title: '@asset-management:assets.transitions.unassign',
|
|
685
|
+
// },
|
|
686
|
+
// {
|
|
687
|
+
// from: AXMAssetStatus.Assigned,
|
|
688
|
+
// to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
689
|
+
// title: '@asset-management:assets.transitions.start-maintenance',
|
|
690
|
+
// },
|
|
691
|
+
// {
|
|
692
|
+
// from: AXMAssetStatus.Assigned,
|
|
693
|
+
// to: AXMAssetStatus.OutOfService,
|
|
694
|
+
// title: '@asset-management:assets.transitions.mark-out-of-service',
|
|
695
|
+
// },
|
|
696
|
+
// {
|
|
697
|
+
// from: AXMAssetStatus.Available,
|
|
698
|
+
// to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
699
|
+
// title: '@asset-management:assets.transitions.start-maintenance',
|
|
700
|
+
// },
|
|
701
|
+
// {
|
|
702
|
+
// from: AXMAssetStatus.OutOfService,
|
|
703
|
+
// to: AXMAssetStatus.UnderMaintenanceInspection,
|
|
704
|
+
// title: '@asset-management:assets.transitions.start-maintenance',
|
|
705
|
+
// },
|
|
706
|
+
// {
|
|
707
|
+
// from: AXMAssetStatus.UnderMaintenanceInspection,
|
|
708
|
+
// to: AXMAssetStatus.Available,
|
|
709
|
+
// title: '@asset-management:assets.transitions.complete-maintenance',
|
|
710
|
+
// },
|
|
711
|
+
// {
|
|
712
|
+
// from: AXMAssetStatus.Available,
|
|
713
|
+
// to: AXMAssetStatus.OutOfService,
|
|
714
|
+
// title: '@asset-management:assets.transitions.mark-out-of-service',
|
|
715
|
+
// },
|
|
716
|
+
// {
|
|
717
|
+
// from: AXMAssetStatus.OutOfService,
|
|
718
|
+
// to: AXMAssetStatus.Available,
|
|
719
|
+
// title: '@asset-management:assets.transitions.restore-service',
|
|
720
|
+
// },
|
|
721
|
+
// {
|
|
722
|
+
// from: AXMAssetStatus.Available,
|
|
723
|
+
// to: AXMAssetStatus.Lost,
|
|
724
|
+
// title: '@asset-management:assets.transitions.mark-lost',
|
|
725
|
+
// },
|
|
726
|
+
// {
|
|
727
|
+
// from: AXMAssetStatus.Assigned,
|
|
728
|
+
// to: AXMAssetStatus.Lost,
|
|
729
|
+
// title: '@asset-management:assets.transitions.mark-lost',
|
|
730
|
+
// },
|
|
731
|
+
// {
|
|
732
|
+
// from: AXMAssetStatus.Lost,
|
|
733
|
+
// to: AXMAssetStatus.Available,
|
|
734
|
+
// title: '@asset-management:assets.transitions.found',
|
|
735
|
+
// },
|
|
736
|
+
// ];
|
|
737
|
+
this.defaultStatus = AXMAssetStatus.Available;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
var assetStatus_provider = /*#__PURE__*/Object.freeze({
|
|
742
|
+
__proto__: null,
|
|
743
|
+
AXMAssetManagementAssetStatusProvider: AXMAssetManagementAssetStatusProvider
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
const rentalHistorySharedCreateFields = [
|
|
747
|
+
'rentalDirection',
|
|
748
|
+
'createdDate',
|
|
749
|
+
'startDate',
|
|
750
|
+
'monthlyRent',
|
|
751
|
+
'expectedReturnDate',
|
|
752
|
+
'actualReturnDate',
|
|
753
|
+
'status',
|
|
754
|
+
'description',
|
|
755
|
+
];
|
|
756
|
+
//#endregion
|
|
757
|
+
//#region ---- Helpers ----
|
|
758
|
+
function buildRentCreateOptions(direction) {
|
|
759
|
+
const isRentFrom = direction === 'rentFrom';
|
|
760
|
+
return {
|
|
761
|
+
includeProperties: [
|
|
762
|
+
...rentalHistorySharedCreateFields,
|
|
763
|
+
isRentFrom ? 'rentedFromId' : 'rentedToId',
|
|
764
|
+
],
|
|
765
|
+
excludeProperties: [isRentFrom ? 'rentedToId' : 'rentedFromId'],
|
|
766
|
+
decoration: {
|
|
767
|
+
header: {
|
|
768
|
+
title: isRentFrom
|
|
769
|
+
? '@asset-management:assetRentalHistories.entities.assetRentalHistory.actions.rent-from.dialog-title'
|
|
770
|
+
: '@asset-management:assetRentalHistories.entities.assetRentalHistory.actions.rent-to.dialog-title',
|
|
771
|
+
},
|
|
772
|
+
},
|
|
773
|
+
process: {
|
|
774
|
+
redirect: false,
|
|
775
|
+
canCreateNewOne: true,
|
|
776
|
+
},
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
//#endregion
|
|
780
|
+
//#region ---- Commands ----
|
|
781
|
+
class AXMCreateAssetRentalHistoryRentCommandBase {
|
|
782
|
+
constructor() {
|
|
783
|
+
this.commandService = inject(AXPCommandService);
|
|
784
|
+
}
|
|
785
|
+
async execute(input) {
|
|
786
|
+
const seedData = this.resolveSeedData(input);
|
|
787
|
+
const createOptions = buildRentCreateOptions(this.rentalDirection);
|
|
788
|
+
const result = await this.commandService.execute('Entity:Create', {
|
|
789
|
+
entity: RootConfig.entities.assetRentalHistory.source,
|
|
790
|
+
entityInfo: {
|
|
791
|
+
name: RootConfig.entities.assetRentalHistory.name,
|
|
792
|
+
module: RootConfig.module.name,
|
|
793
|
+
title: RootConfig.entities.assetRentalHistory.title,
|
|
794
|
+
},
|
|
795
|
+
data: seedData,
|
|
796
|
+
options: createOptions,
|
|
797
|
+
});
|
|
798
|
+
return result ?? { success: false };
|
|
799
|
+
}
|
|
800
|
+
resolveSeedData(input) {
|
|
801
|
+
const ctx = input;
|
|
802
|
+
const options = (input.options ?? ctx.options ?? {});
|
|
803
|
+
const process = (options['process'] ?? {});
|
|
804
|
+
const processData = process['data'];
|
|
805
|
+
const contextData = ctx.data ?? input.data ?? {};
|
|
806
|
+
return merge({}, typeof contextData === 'object' &&
|
|
807
|
+
contextData !== null &&
|
|
808
|
+
!Array.isArray(contextData)
|
|
809
|
+
? contextData
|
|
810
|
+
: {}, typeof processData === 'object' &&
|
|
811
|
+
processData !== null &&
|
|
812
|
+
!Array.isArray(processData)
|
|
813
|
+
? processData
|
|
814
|
+
: {}, { rentalDirection: this.rentalDirection });
|
|
815
|
+
}
|
|
816
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentCommandBase, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
817
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentCommandBase, providedIn: 'root' }); }
|
|
818
|
+
}
|
|
819
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentCommandBase, decorators: [{
|
|
820
|
+
type: Injectable,
|
|
821
|
+
args: [{ providedIn: 'root' }]
|
|
822
|
+
}] });
|
|
823
|
+
class AXMCreateAssetRentalHistoryRentFromCommand extends AXMCreateAssetRentalHistoryRentCommandBase {
|
|
824
|
+
constructor() {
|
|
825
|
+
super(...arguments);
|
|
826
|
+
this.rentalDirection = 'rentFrom';
|
|
827
|
+
}
|
|
828
|
+
static { this.commandKey = AXMAssetManagementCommandKeys.AssetRentalHistory.RentFrom; }
|
|
829
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentFromCommand, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
830
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentFromCommand, providedIn: 'root' }); }
|
|
831
|
+
}
|
|
832
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentFromCommand, decorators: [{
|
|
833
|
+
type: Injectable,
|
|
834
|
+
args: [{ providedIn: 'root' }]
|
|
835
|
+
}] });
|
|
836
|
+
class AXMCreateAssetRentalHistoryRentToCommand extends AXMCreateAssetRentalHistoryRentCommandBase {
|
|
837
|
+
constructor() {
|
|
838
|
+
super(...arguments);
|
|
839
|
+
this.rentalDirection = 'rentTo';
|
|
840
|
+
}
|
|
841
|
+
static { this.commandKey = AXMAssetManagementCommandKeys.AssetRentalHistory.RentTo; }
|
|
842
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentToCommand, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
843
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentToCommand, providedIn: 'root' }); }
|
|
844
|
+
}
|
|
845
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMCreateAssetRentalHistoryRentToCommand, decorators: [{
|
|
846
|
+
type: Injectable,
|
|
847
|
+
args: [{ providedIn: 'root' }]
|
|
848
|
+
}] });
|
|
849
|
+
|
|
850
|
+
var createAssetRentalHistoryRent_commands = /*#__PURE__*/Object.freeze({
|
|
851
|
+
__proto__: null,
|
|
852
|
+
AXMCreateAssetRentalHistoryRentFromCommand: AXMCreateAssetRentalHistoryRentFromCommand,
|
|
853
|
+
AXMCreateAssetRentalHistoryRentToCommand: AXMCreateAssetRentalHistoryRentToCommand
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
function normalizeAssetTypeBuilderLocalizedField(value, fallback) {
|
|
857
|
+
if (value == null || value === '') {
|
|
858
|
+
return fallback;
|
|
859
|
+
}
|
|
860
|
+
if (typeof value === 'string') {
|
|
861
|
+
const trimmed = value.trim();
|
|
862
|
+
return trimmed || fallback;
|
|
863
|
+
}
|
|
864
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
865
|
+
const record = value;
|
|
866
|
+
const anyLocaleText = Object.values(record).some((v) => typeof v === 'string' && String(v).trim() !== '');
|
|
867
|
+
if (anyLocaleText) {
|
|
868
|
+
return value;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return fallback;
|
|
872
|
+
}
|
|
873
|
+
function createAssetTypeSectionBuilderDefaultValue(assetTypeId) {
|
|
874
|
+
return {
|
|
875
|
+
sections: [
|
|
876
|
+
{
|
|
877
|
+
id: AXPDataGenerator.uuid(),
|
|
878
|
+
code: 1,
|
|
879
|
+
title: 'New Section',
|
|
880
|
+
assetTypeId: assetTypeId ?? '',
|
|
881
|
+
description: '',
|
|
882
|
+
items: [],
|
|
883
|
+
},
|
|
884
|
+
],
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
function normalizeAssetTypeSectionBuilderValue(value, assetTypeId) {
|
|
888
|
+
if (!value || typeof value !== 'object') {
|
|
889
|
+
return createAssetTypeSectionBuilderDefaultValue(assetTypeId);
|
|
890
|
+
}
|
|
891
|
+
const raw = value;
|
|
892
|
+
if (!Array.isArray(raw.sections) || raw.sections.length === 0) {
|
|
893
|
+
return createAssetTypeSectionBuilderDefaultValue(assetTypeId);
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
sections: raw.sections.map((section, sectionIndex) => {
|
|
897
|
+
const sectionData = (section ?? {});
|
|
898
|
+
const id = typeof sectionData.id === 'string' && sectionData.id ? sectionData.id : AXPDataGenerator.uuid();
|
|
899
|
+
const sectionItems = Array.isArray(sectionData.items) ? sectionData.items : [];
|
|
900
|
+
return {
|
|
901
|
+
id,
|
|
902
|
+
code: typeof sectionData.code === 'number' ? sectionData.code : sectionIndex + 1,
|
|
903
|
+
title: normalizeAssetTypeBuilderLocalizedField(sectionData.title, `Section ${sectionIndex + 1}`),
|
|
904
|
+
assetTypeId: typeof sectionData.assetTypeId === 'string' && sectionData.assetTypeId
|
|
905
|
+
? sectionData.assetTypeId
|
|
906
|
+
: assetTypeId ?? '',
|
|
907
|
+
description: normalizeAssetTypeBuilderLocalizedField(sectionData.description, ''),
|
|
908
|
+
items: sectionItems.map((item, itemIndex) => {
|
|
909
|
+
const itemData = (item ?? {});
|
|
910
|
+
const rawAt = itemData.assetType;
|
|
911
|
+
const assetTypeIdFromRef = rawAt &&
|
|
912
|
+
typeof rawAt === 'object' &&
|
|
913
|
+
typeof rawAt.id === 'string' &&
|
|
914
|
+
String(rawAt.id).trim()
|
|
915
|
+
? String(rawAt.id).trim()
|
|
916
|
+
: '';
|
|
917
|
+
const normalizedAssetTypeId = typeof itemData.assetTypeId === 'string' && itemData.assetTypeId.trim()
|
|
918
|
+
? itemData.assetTypeId.trim()
|
|
919
|
+
: assetTypeIdFromRef || (assetTypeId ?? '');
|
|
920
|
+
const assetTypeRef = rawAt && typeof rawAt === 'object'
|
|
921
|
+
? {
|
|
922
|
+
id: typeof rawAt.id === 'string' && String(rawAt.id).trim()
|
|
923
|
+
? String(rawAt.id).trim()
|
|
924
|
+
: normalizedAssetTypeId,
|
|
925
|
+
name: normalizeAssetTypeBuilderLocalizedField(rawAt.name, ''),
|
|
926
|
+
}
|
|
927
|
+
: {
|
|
928
|
+
id: normalizedAssetTypeId,
|
|
929
|
+
name: '',
|
|
930
|
+
};
|
|
931
|
+
return {
|
|
932
|
+
id: typeof itemData.id === 'string' && itemData.id ? itemData.id : AXPDataGenerator.uuid(),
|
|
933
|
+
assetTypeSectionId: typeof itemData.assetTypeSectionId === 'string' && itemData.assetTypeSectionId
|
|
934
|
+
? itemData.assetTypeSectionId
|
|
935
|
+
: id,
|
|
936
|
+
assetTypeSectionComponentId: typeof itemData.assetTypeSectionComponentId === 'string' && itemData.assetTypeSectionComponentId
|
|
937
|
+
? itemData.assetTypeSectionComponentId
|
|
938
|
+
: undefined,
|
|
939
|
+
assetTypeId: normalizedAssetTypeId,
|
|
940
|
+
assetType: assetTypeRef,
|
|
941
|
+
assetTypeSection: itemData.assetTypeSection,
|
|
942
|
+
roleName: normalizeAssetTypeBuilderLocalizedField(itemData.roleName, ''),
|
|
943
|
+
count: typeof itemData.count === 'number' ? itemData.count : 1,
|
|
944
|
+
hasMaintenance: itemData.hasMaintenance === true,
|
|
945
|
+
assetId: typeof itemData.assetId === 'string' && itemData.assetId ? itemData.assetId : undefined,
|
|
946
|
+
asset: itemData.asset && typeof itemData.asset === 'object'
|
|
947
|
+
? {
|
|
948
|
+
id: typeof itemData.asset.id === 'string'
|
|
949
|
+
? (itemData.asset.id ?? '')
|
|
950
|
+
: '',
|
|
951
|
+
code: typeof itemData.asset.code === 'string'
|
|
952
|
+
? itemData.asset.code
|
|
953
|
+
: undefined,
|
|
954
|
+
title: normalizeAssetTypeBuilderLocalizedField(itemData.asset.title, ''),
|
|
955
|
+
}
|
|
956
|
+
: undefined,
|
|
957
|
+
};
|
|
958
|
+
}),
|
|
959
|
+
};
|
|
960
|
+
}),
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
class AXMAssetTypeSectionBuilderComponent {
|
|
965
|
+
constructor() {
|
|
966
|
+
this.value = input(null, /* @ts-ignore */
|
|
967
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
968
|
+
this.assetTypeId = input(undefined, /* @ts-ignore */
|
|
969
|
+
...(ngDevMode ? [{ debugName: "assetTypeId" }] : /* istanbul ignore next */ []));
|
|
970
|
+
this.options = input({}, /* @ts-ignore */
|
|
971
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
972
|
+
this.valueChange = output();
|
|
973
|
+
this.standardRef = viewChild(AXPStandardSectionItemsBuilderComponent, /* @ts-ignore */
|
|
974
|
+
...(ngDevMode ? [{ debugName: "standardRef" }] : /* istanbul ignore next */ []));
|
|
975
|
+
this.layoutBuilder = inject(AXPLayoutBuilderService);
|
|
976
|
+
this.translationService = inject(AXTranslationService);
|
|
977
|
+
this.disabledSectionPrompt = false;
|
|
978
|
+
this.disabledAddSectionPrompt = async () => null;
|
|
979
|
+
this.builderValue = signal({ sections: [] }, /* @ts-ignore */
|
|
980
|
+
...(ngDevMode ? [{ debugName: "builderValue" }] : /* istanbul ignore next */ []));
|
|
981
|
+
this.standardConfig = computed(() => ({
|
|
982
|
+
mapItemToView: (item, _section) => this.mapItemToView(item),
|
|
983
|
+
promptAddSection: this.allowAddSection() ? (value) => this.promptAddSection(value) : this.disabledAddSectionPrompt,
|
|
984
|
+
promptEditSection: this.allowEditSection()
|
|
985
|
+
? (section, value) => this.promptEditSection(section, value)
|
|
986
|
+
: this.disabledSectionPrompt,
|
|
987
|
+
promptAddItems: this.allowAddItems() ? (sectionId, value) => this.promptAddItems(sectionId, value) : undefined,
|
|
988
|
+
promptEditItem: (item, sectionId, value) => this.linkAssetMode()
|
|
989
|
+
? this.promptEditLinkedAssetItem(item, sectionId, value)
|
|
990
|
+
: this.promptEditItem(item, sectionId, value),
|
|
991
|
+
confirmRemoveSection: this.linkAssetMode() ? async () => false : undefined,
|
|
992
|
+
confirmRemoveItem: this.linkAssetMode()
|
|
993
|
+
? (item, sectionId) => this.confirmRemoveLinkedAssetItem(item, sectionId)
|
|
994
|
+
: undefined,
|
|
995
|
+
showSectionTechnicalName: false,
|
|
996
|
+
allowReorderSections: this.allowReorderSections(),
|
|
997
|
+
minSectionCount: this.allowAddSection() ? 1 : Number.MAX_SAFE_INTEGER,
|
|
998
|
+
texts: {
|
|
999
|
+
addSection: '@asset-management:assetTypeSections.entities.assetTypeSection.actions.add-section.title',
|
|
1000
|
+
addItem: '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.actions.add-item.title',
|
|
1001
|
+
},
|
|
1002
|
+
}), /* @ts-ignore */
|
|
1003
|
+
...(ngDevMode ? [{ debugName: "standardConfig" }] : /* istanbul ignore next */ []));
|
|
1004
|
+
this.hideHeaderActions = computed(() => this.options()['hideHeaderActions'] === true, /* @ts-ignore */
|
|
1005
|
+
...(ngDevMode ? [{ debugName: "hideHeaderActions" }] : /* istanbul ignore next */ []));
|
|
1006
|
+
this.allowAddSection = computed(() => this.options()['allowAddSection'] !== false, /* @ts-ignore */
|
|
1007
|
+
...(ngDevMode ? [{ debugName: "allowAddSection" }] : /* istanbul ignore next */ []));
|
|
1008
|
+
this.allowEditSection = computed(() => {
|
|
1009
|
+
if (this.linkAssetMode()) {
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
return this.options()['allowEditSection'] !== false;
|
|
1013
|
+
}, /* @ts-ignore */
|
|
1014
|
+
...(ngDevMode ? [{ debugName: "allowEditSection" }] : /* istanbul ignore next */ []));
|
|
1015
|
+
this.allowAddItems = computed(() => this.options()['allowAddItems'] !== false, /* @ts-ignore */
|
|
1016
|
+
...(ngDevMode ? [{ debugName: "allowAddItems" }] : /* istanbul ignore next */ []));
|
|
1017
|
+
this.allowReorderSections = computed(() => {
|
|
1018
|
+
const option = this.options()['allowReorderSections'];
|
|
1019
|
+
return typeof option === 'boolean' ? option : true;
|
|
1020
|
+
}, /* @ts-ignore */
|
|
1021
|
+
...(ngDevMode ? [{ debugName: "allowReorderSections" }] : /* istanbul ignore next */ []));
|
|
1022
|
+
this.readonly = computed(() => this.options()['readonly'] === true, /* @ts-ignore */
|
|
1023
|
+
...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1024
|
+
this.linkAssetMode = computed(() => this.options()['linkAssetMode'] === true, /* @ts-ignore */
|
|
1025
|
+
...(ngDevMode ? [{ debugName: "linkAssetMode" }] : /* istanbul ignore next */ []));
|
|
1026
|
+
this.#syncValueToBuilder = effect(() => {
|
|
1027
|
+
const normalized = normalizeAssetTypeSectionBuilderValue(this.value(), this.assetTypeId());
|
|
1028
|
+
this.builderValue.set(this.toBuilderValue(normalized));
|
|
1029
|
+
}, /* @ts-ignore */
|
|
1030
|
+
...(ngDevMode ? [{ debugName: "#syncValueToBuilder" }] : /* istanbul ignore next */ []));
|
|
1031
|
+
}
|
|
1032
|
+
#syncValueToBuilder;
|
|
1033
|
+
async addSection() {
|
|
1034
|
+
await this.standardRef()?.addSection();
|
|
1035
|
+
}
|
|
1036
|
+
/** Aligns section-items baseline to persisted value after save. */
|
|
1037
|
+
syncAfterSave(value) {
|
|
1038
|
+
const normalized = normalizeAssetTypeSectionBuilderValue(value, this.assetTypeId());
|
|
1039
|
+
this.builderValue.set(this.toBuilderValue(normalized));
|
|
1040
|
+
queueMicrotask(() => this.standardRef()?.markClean());
|
|
1041
|
+
}
|
|
1042
|
+
/** Re-applies the current `[value]` input and clears builder dirty state after discard. */
|
|
1043
|
+
resetAfterDiscard() {
|
|
1044
|
+
const normalized = normalizeAssetTypeSectionBuilderValue(this.value(), this.assetTypeId());
|
|
1045
|
+
this.builderValue.set(this.toBuilderValue(normalized));
|
|
1046
|
+
queueMicrotask(() => this.standardRef()?.markClean());
|
|
1047
|
+
}
|
|
1048
|
+
onBuilderValueChange(next) {
|
|
1049
|
+
this.builderValue.set(next);
|
|
1050
|
+
const value = this.fromBuilderValue(next);
|
|
1051
|
+
this.valueChange.emit(value);
|
|
1052
|
+
}
|
|
1053
|
+
async promptAddSection(value) {
|
|
1054
|
+
const seed = {
|
|
1055
|
+
code: this.getNextSectionCode(value),
|
|
1056
|
+
title: '',
|
|
1057
|
+
description: '',
|
|
1058
|
+
};
|
|
1059
|
+
const dialogValue = await this.promptSectionForm('create', seed, value);
|
|
1060
|
+
if (!dialogValue)
|
|
1061
|
+
return null;
|
|
1062
|
+
const sectionId = AXPDataGenerator.uuid();
|
|
1063
|
+
return {
|
|
1064
|
+
id: sectionId,
|
|
1065
|
+
name: sectionId,
|
|
1066
|
+
code: dialogValue.code,
|
|
1067
|
+
title: dialogValue.title,
|
|
1068
|
+
description: dialogValue.description,
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
async promptEditSection(section, value) {
|
|
1072
|
+
const seed = {
|
|
1073
|
+
code: Number(section['code'] ?? 0) || this.getNextSectionCode(value),
|
|
1074
|
+
title: this.resolveLocalizedTextForDialog(section['title']),
|
|
1075
|
+
description: this.resolveLocalizedTextForDialog(section['description']),
|
|
1076
|
+
};
|
|
1077
|
+
const dialogValue = await this.promptSectionForm('edit', seed, value, section.id);
|
|
1078
|
+
if (!dialogValue)
|
|
1079
|
+
return null;
|
|
1080
|
+
return {
|
|
1081
|
+
...section,
|
|
1082
|
+
code: dialogValue.code,
|
|
1083
|
+
title: dialogValue.title,
|
|
1084
|
+
description: dialogValue.description,
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
async promptSectionForm(mode, seed, value, currentSectionId) {
|
|
1088
|
+
const title = mode === 'create'
|
|
1089
|
+
? (await this.translationService.translateAsync('@asset-management:assetTypeSections.entities.assetTypeSection.actions.add-section.title')) || 'Add Section'
|
|
1090
|
+
: (await this.translationService.translateAsync('@general:actions.edit.title')) || 'Edit';
|
|
1091
|
+
const result = await this.layoutBuilder
|
|
1092
|
+
.create()
|
|
1093
|
+
.dialog((dialog) => {
|
|
1094
|
+
dialog
|
|
1095
|
+
.setTitle(title)
|
|
1096
|
+
.setSize('sm')
|
|
1097
|
+
.setCloseButton(true)
|
|
1098
|
+
.setContext({ ...seed })
|
|
1099
|
+
.content((layout) => {
|
|
1100
|
+
layout.mode('edit');
|
|
1101
|
+
layout.dynamicForm(this.buildSectionFormDefinition());
|
|
1102
|
+
})
|
|
1103
|
+
.setActions((actions) => {
|
|
1104
|
+
actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
|
|
1105
|
+
})
|
|
1106
|
+
.onAction((dialogRef) => {
|
|
1107
|
+
if (dialogRef.action() === 'cancel') {
|
|
1108
|
+
return { success: false };
|
|
1109
|
+
}
|
|
1110
|
+
const context = dialogRef.context();
|
|
1111
|
+
const code = Number(context.code ?? 0);
|
|
1112
|
+
const titleValue = String(context.title ?? '').trim();
|
|
1113
|
+
const description = String(context.description ?? '');
|
|
1114
|
+
if (!Number.isFinite(code) || code <= 0 || !titleValue) {
|
|
1115
|
+
return { success: false };
|
|
1116
|
+
}
|
|
1117
|
+
if (this.isDuplicateSectionCode(value, code, currentSectionId)) {
|
|
1118
|
+
return { success: false };
|
|
1119
|
+
}
|
|
1120
|
+
return { success: true, kind: 'object', value: {
|
|
1121
|
+
code,
|
|
1122
|
+
title: titleValue,
|
|
1123
|
+
description,
|
|
1124
|
+
},
|
|
1125
|
+
};
|
|
1126
|
+
});
|
|
1127
|
+
})
|
|
1128
|
+
.show();
|
|
1129
|
+
return result?.success && result.value ? result.value : null;
|
|
1130
|
+
}
|
|
1131
|
+
isDuplicateSectionCode(value, code, currentSectionId) {
|
|
1132
|
+
return value.sections.some((section) => {
|
|
1133
|
+
if (currentSectionId && section.id === currentSectionId)
|
|
1134
|
+
return false;
|
|
1135
|
+
const sectionCode = Number(section['code'] ?? 0);
|
|
1136
|
+
return Number.isFinite(sectionCode) && sectionCode === code;
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
getNextSectionCode(value) {
|
|
1140
|
+
const maxCode = value.sections.reduce((max, section) => {
|
|
1141
|
+
const sectionCode = Number(section['code'] ?? 0);
|
|
1142
|
+
if (!Number.isFinite(sectionCode))
|
|
1143
|
+
return max;
|
|
1144
|
+
return Math.max(max, sectionCode);
|
|
1145
|
+
}, 0);
|
|
1146
|
+
return maxCode + 1;
|
|
1147
|
+
}
|
|
1148
|
+
mapItemToView(item) {
|
|
1149
|
+
const roleName = this.resolveLocalizedTextForDialog(item['roleName'] ?? '');
|
|
1150
|
+
const assetTypeName = this.resolveLocalizedTextForDialog(item['assetType']?.name ?? '');
|
|
1151
|
+
const count = Number(item['count'] ?? 0);
|
|
1152
|
+
const hasMaintenance = item['hasMaintenance'] === true;
|
|
1153
|
+
const linkedAsset = item['asset'];
|
|
1154
|
+
const linkedAssetCode = typeof linkedAsset?.code === 'string' ? linkedAsset.code : '';
|
|
1155
|
+
const linkedAssetTitle = this.resolveLocalizedTextForDialog(linkedAsset?.title ?? '');
|
|
1156
|
+
if (this.linkAssetMode()) {
|
|
1157
|
+
const hasLinkedAsset = !!item['assetId'];
|
|
1158
|
+
const linkedAssetName = linkedAssetTitle || '@asset-management:assets.entities.asset.components.asset-component.no-link';
|
|
1159
|
+
const linkedAssetDisplay = linkedAssetCode ? `${linkedAssetName} (${linkedAssetCode})` : linkedAssetName;
|
|
1160
|
+
return {
|
|
1161
|
+
icon: hasLinkedAsset ? 'fa-light fa-link' : 'fa-light fa-link-slash',
|
|
1162
|
+
iconTone: hasLinkedAsset ? 'easy' : 'hard',
|
|
1163
|
+
title: roleName,
|
|
1164
|
+
name: linkedAssetDisplay,
|
|
1165
|
+
badges: [
|
|
1166
|
+
{
|
|
1167
|
+
text: hasLinkedAsset
|
|
1168
|
+
? '@asset-management:assets.entities.asset.components.asset-component.assigned'
|
|
1169
|
+
: '@asset-management:assets.entities.asset.components.asset-component.unassigned',
|
|
1170
|
+
variant: hasLinkedAsset ? 'success' : 'warning',
|
|
1171
|
+
},
|
|
1172
|
+
...(hasLinkedAsset && linkedAssetTitle
|
|
1173
|
+
? [
|
|
1174
|
+
{
|
|
1175
|
+
text: linkedAssetTitle,
|
|
1176
|
+
variant: 'neutral',
|
|
1177
|
+
},
|
|
1178
|
+
]
|
|
1179
|
+
: []),
|
|
1180
|
+
{
|
|
1181
|
+
text: assetTypeName,
|
|
1182
|
+
variant: 'neutral',
|
|
1183
|
+
},
|
|
1184
|
+
],
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
return {
|
|
1188
|
+
icon: 'fa-light fa-cube',
|
|
1189
|
+
title: roleName,
|
|
1190
|
+
name: assetTypeName,
|
|
1191
|
+
badges: [
|
|
1192
|
+
{
|
|
1193
|
+
text: `x${count}`,
|
|
1194
|
+
variant: 'neutral',
|
|
1195
|
+
},
|
|
1196
|
+
...(hasMaintenance
|
|
1197
|
+
? [
|
|
1198
|
+
{
|
|
1199
|
+
text: '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.fields.hasMaintenance.title',
|
|
1200
|
+
variant: 'success',
|
|
1201
|
+
},
|
|
1202
|
+
]
|
|
1203
|
+
: []),
|
|
1204
|
+
],
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
async promptAddItems(sectionId, value) {
|
|
1208
|
+
const section = value.sections.find((item) => item.id === sectionId);
|
|
1209
|
+
if (!section)
|
|
1210
|
+
return null;
|
|
1211
|
+
const itemValue = await this.promptItemForm('create');
|
|
1212
|
+
if (!itemValue)
|
|
1213
|
+
return null;
|
|
1214
|
+
const nextOrder = section.items.length;
|
|
1215
|
+
const id = AXPDataGenerator.uuid();
|
|
1216
|
+
return [
|
|
1217
|
+
{
|
|
1218
|
+
id,
|
|
1219
|
+
order: nextOrder,
|
|
1220
|
+
name: itemValue.assetType.name,
|
|
1221
|
+
roleName: itemValue.roleName,
|
|
1222
|
+
count: itemValue.count,
|
|
1223
|
+
hasMaintenance: itemValue.hasMaintenance,
|
|
1224
|
+
assetType: itemValue.assetType,
|
|
1225
|
+
assetTypeSectionId: section.id,
|
|
1226
|
+
assetTypeId: itemValue.assetTypeId || this.assetTypeId() || '',
|
|
1227
|
+
},
|
|
1228
|
+
];
|
|
1229
|
+
}
|
|
1230
|
+
async promptEditItem(item, _sectionId, _value) {
|
|
1231
|
+
const dialogValue = await this.promptItemForm('edit', {
|
|
1232
|
+
assetTypeId: String(item['assetTypeId'] ?? this.assetTypeId() ?? ''),
|
|
1233
|
+
assetType: item['assetType'] ?? {
|
|
1234
|
+
id: String(item['assetTypeId'] ?? this.assetTypeId() ?? ''),
|
|
1235
|
+
name: '',
|
|
1236
|
+
},
|
|
1237
|
+
roleName: this.resolveLocalizedTextForDialog(item['roleName'] ?? item['name'] ?? ''),
|
|
1238
|
+
count: Number(item['count'] ?? 1),
|
|
1239
|
+
hasMaintenance: item['hasMaintenance'] === true,
|
|
1240
|
+
});
|
|
1241
|
+
if (!dialogValue)
|
|
1242
|
+
return null;
|
|
1243
|
+
return {
|
|
1244
|
+
...item,
|
|
1245
|
+
name: dialogValue.assetType.name,
|
|
1246
|
+
roleName: dialogValue.roleName,
|
|
1247
|
+
count: dialogValue.count,
|
|
1248
|
+
hasMaintenance: dialogValue.hasMaintenance,
|
|
1249
|
+
assetTypeId: dialogValue.assetTypeId,
|
|
1250
|
+
assetType: dialogValue.assetType,
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
async promptEditLinkedAssetItem(item, _sectionId, _value) {
|
|
1254
|
+
const seed = {
|
|
1255
|
+
assetId: String(item['assetId'] ?? ''),
|
|
1256
|
+
assetTypeId: String(item['assetTypeId'] ?? '').trim(),
|
|
1257
|
+
asset: item['asset'] ?? {
|
|
1258
|
+
id: '',
|
|
1259
|
+
code: '',
|
|
1260
|
+
title: '',
|
|
1261
|
+
},
|
|
1262
|
+
};
|
|
1263
|
+
const result = await this.promptLinkAssetForm(seed);
|
|
1264
|
+
if (!result) {
|
|
1265
|
+
return null;
|
|
1266
|
+
}
|
|
1267
|
+
return {
|
|
1268
|
+
...item,
|
|
1269
|
+
assetId: result.assetId || undefined,
|
|
1270
|
+
asset: result.assetId ? result.asset : undefined,
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
async promptLinkAssetForm(seed) {
|
|
1274
|
+
const title = (await this.translationService.translateAsync('@asset-management:assets.entities.asset.components.asset-component.actions.edit.title')) || 'Edit Component Asset';
|
|
1275
|
+
const result = await this.layoutBuilder
|
|
1276
|
+
.create()
|
|
1277
|
+
.dialog((dialog) => {
|
|
1278
|
+
dialog
|
|
1279
|
+
.setTitle(title)
|
|
1280
|
+
.setSize('sm')
|
|
1281
|
+
.setCloseButton(true)
|
|
1282
|
+
.setContext({ ...seed })
|
|
1283
|
+
.content((layout) => {
|
|
1284
|
+
layout.mode('edit');
|
|
1285
|
+
layout.dynamicForm(this.buildLinkAssetFormDefinition());
|
|
1286
|
+
})
|
|
1287
|
+
.setActions((actions) => {
|
|
1288
|
+
actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
|
|
1289
|
+
})
|
|
1290
|
+
.onAction((dialogRef) => {
|
|
1291
|
+
if (dialogRef.action() === 'cancel') {
|
|
1292
|
+
return { success: false };
|
|
1293
|
+
}
|
|
1294
|
+
const context = dialogRef.context();
|
|
1295
|
+
const assetId = String(context.assetId ?? '').trim();
|
|
1296
|
+
const asset = context.asset ?? { id: assetId, code: '', title: '' };
|
|
1297
|
+
return { success: true, kind: 'object', value: {
|
|
1298
|
+
assetId,
|
|
1299
|
+
assetTypeId: String(context.assetTypeId ?? ''),
|
|
1300
|
+
asset: {
|
|
1301
|
+
id: String(asset.id ?? assetId),
|
|
1302
|
+
code: String(asset.code ?? ''),
|
|
1303
|
+
title: String(asset.title ?? ''),
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
};
|
|
1307
|
+
});
|
|
1308
|
+
})
|
|
1309
|
+
.show();
|
|
1310
|
+
return result?.success && result.value ? result.value : null;
|
|
1311
|
+
}
|
|
1312
|
+
async confirmRemoveLinkedAssetItem(item, sectionId) {
|
|
1313
|
+
const hasLinkedAsset = typeof item['assetId'] === 'string' && item['assetId'].length > 0;
|
|
1314
|
+
if (!hasLinkedAsset) {
|
|
1315
|
+
return false;
|
|
1316
|
+
}
|
|
1317
|
+
const deleteTitle = (await this.translationService.translateAsync('@asset-management:assets.entities.asset.components.asset-component.actions.delete.title')) || 'Remove Component Asset';
|
|
1318
|
+
const linkedAsset = item['asset'];
|
|
1319
|
+
const linkedAssetTitle = this.resolveLocalizedTextForDialog(linkedAsset?.title ?? '');
|
|
1320
|
+
const linkedAssetCode = typeof linkedAsset?.code === 'string' ? linkedAsset.code : '';
|
|
1321
|
+
const assetDisplay = linkedAssetTitle || linkedAssetCode || String(item['assetId'] ?? '');
|
|
1322
|
+
const assetLabel = `${assetDisplay}${linkedAssetCode && linkedAssetTitle ? ` (${linkedAssetCode})` : ''}`;
|
|
1323
|
+
const deleteResult = await this.layoutBuilder
|
|
1324
|
+
.create()
|
|
1325
|
+
.dialog((dialog) => {
|
|
1326
|
+
dialog
|
|
1327
|
+
.setTitle(deleteTitle)
|
|
1328
|
+
.setMessage('@general:workflow.confirm-delete')
|
|
1329
|
+
.setSize('sm')
|
|
1330
|
+
.setCloseButton(true)
|
|
1331
|
+
.setContext({ assetLabel })
|
|
1332
|
+
.content((layout) => {
|
|
1333
|
+
layout.mode('edit');
|
|
1334
|
+
layout.dynamicForm(this.buildRemoveLinkedAssetFormDefinition());
|
|
1335
|
+
})
|
|
1336
|
+
.setActions((actions) => {
|
|
1337
|
+
actions.cancel('@general:actions.cancel.title').custom({
|
|
1338
|
+
title: '@general:actions.delete.title',
|
|
1339
|
+
color: 'danger',
|
|
1340
|
+
command: {
|
|
1341
|
+
name: 'delete',
|
|
1342
|
+
options: {
|
|
1343
|
+
validate: false,
|
|
1344
|
+
},
|
|
1345
|
+
},
|
|
1346
|
+
});
|
|
1347
|
+
})
|
|
1348
|
+
.onAction((dialogRef) => {
|
|
1349
|
+
if (dialogRef.action() !== 'delete') {
|
|
1350
|
+
return { success: false };
|
|
1351
|
+
}
|
|
1352
|
+
return { success: true, kind: 'object', data: undefined };
|
|
1353
|
+
});
|
|
1354
|
+
})
|
|
1355
|
+
.show();
|
|
1356
|
+
if (deleteResult?.success === true) {
|
|
1357
|
+
this.unlinkLinkedAssetItem(item.id, sectionId);
|
|
1358
|
+
}
|
|
1359
|
+
// Prevent structural row removal; only unlink asset assignment.
|
|
1360
|
+
return false;
|
|
1361
|
+
}
|
|
1362
|
+
buildRemoveLinkedAssetFormDefinition() {
|
|
1363
|
+
const group = {
|
|
1364
|
+
name: 'unlink-asset',
|
|
1365
|
+
title: '@asset-management:assets.entities.asset.components.asset-component.title',
|
|
1366
|
+
parameters: [
|
|
1367
|
+
{
|
|
1368
|
+
path: 'assetLabel',
|
|
1369
|
+
title: '@asset-management:assets.entities.asset.title',
|
|
1370
|
+
widget: {
|
|
1371
|
+
path: 'assetLabel',
|
|
1372
|
+
type: AXPWidgetsCatalog.text,
|
|
1373
|
+
options: {
|
|
1374
|
+
disabled: true,
|
|
1375
|
+
},
|
|
1376
|
+
},
|
|
1377
|
+
},
|
|
1378
|
+
],
|
|
1379
|
+
};
|
|
1380
|
+
return { groups: [group] };
|
|
1381
|
+
}
|
|
1382
|
+
unlinkLinkedAssetItem(itemId, sectionId) {
|
|
1383
|
+
const nextValue = {
|
|
1384
|
+
sections: this.builderValue().sections.map((section) => {
|
|
1385
|
+
if (section.id !== sectionId) {
|
|
1386
|
+
return section;
|
|
1387
|
+
}
|
|
1388
|
+
return {
|
|
1389
|
+
...section,
|
|
1390
|
+
items: section.items.map((item) => {
|
|
1391
|
+
if (item.id !== itemId) {
|
|
1392
|
+
return item;
|
|
1393
|
+
}
|
|
1394
|
+
return {
|
|
1395
|
+
...item,
|
|
1396
|
+
assetId: undefined,
|
|
1397
|
+
asset: undefined,
|
|
1398
|
+
};
|
|
1399
|
+
}),
|
|
1400
|
+
};
|
|
1401
|
+
}),
|
|
1402
|
+
};
|
|
1403
|
+
this.onBuilderValueChange(nextValue);
|
|
1404
|
+
}
|
|
1405
|
+
async promptItemForm(mode, seed) {
|
|
1406
|
+
const defaultSeed = seed ?? {
|
|
1407
|
+
assetTypeId: '',
|
|
1408
|
+
assetType: {
|
|
1409
|
+
id: '',
|
|
1410
|
+
name: '',
|
|
1411
|
+
},
|
|
1412
|
+
roleName: '',
|
|
1413
|
+
count: 1,
|
|
1414
|
+
hasMaintenance: false,
|
|
1415
|
+
};
|
|
1416
|
+
const title = mode === 'create'
|
|
1417
|
+
? (await this.translationService.translateAsync('@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.actions.add-item.title')) || 'Add Component'
|
|
1418
|
+
: (await this.translationService.translateAsync('@general:actions.edit.title')) || 'Edit';
|
|
1419
|
+
const formDefinition = this.buildItemFormDefinition();
|
|
1420
|
+
const result = await this.layoutBuilder
|
|
1421
|
+
.create()
|
|
1422
|
+
.dialog((dialog) => {
|
|
1423
|
+
dialog
|
|
1424
|
+
.setTitle(title)
|
|
1425
|
+
.setSize('sm')
|
|
1426
|
+
.setCloseButton(true)
|
|
1427
|
+
.setContext({ ...defaultSeed })
|
|
1428
|
+
.content((layout) => {
|
|
1429
|
+
layout.mode('edit');
|
|
1430
|
+
layout.dynamicForm(formDefinition);
|
|
1431
|
+
})
|
|
1432
|
+
.setActions((actions) => {
|
|
1433
|
+
actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
|
|
1434
|
+
})
|
|
1435
|
+
.onAction((dialogRef) => {
|
|
1436
|
+
if (dialogRef.action() === 'cancel') {
|
|
1437
|
+
return { success: false };
|
|
1438
|
+
}
|
|
1439
|
+
const context = dialogRef.context();
|
|
1440
|
+
const assetTypeId = String(context.assetTypeId ?? '').trim();
|
|
1441
|
+
const assetType = context.assetType;
|
|
1442
|
+
const roleName = String(context.roleName ?? '').trim();
|
|
1443
|
+
const count = Number(context.count ?? 0);
|
|
1444
|
+
const hasMaintenance = context.hasMaintenance === true;
|
|
1445
|
+
if (!assetTypeId) {
|
|
1446
|
+
return { success: false };
|
|
1447
|
+
}
|
|
1448
|
+
return { success: true, kind: 'object', value: {
|
|
1449
|
+
assetTypeId,
|
|
1450
|
+
assetType: {
|
|
1451
|
+
id: String(assetType?.id ?? assetTypeId),
|
|
1452
|
+
name: String(assetType?.name ?? ''),
|
|
1453
|
+
},
|
|
1454
|
+
roleName,
|
|
1455
|
+
count: Number.isFinite(count) && count > 0 ? count : 1,
|
|
1456
|
+
hasMaintenance,
|
|
1457
|
+
},
|
|
1458
|
+
};
|
|
1459
|
+
});
|
|
1460
|
+
})
|
|
1461
|
+
.show();
|
|
1462
|
+
return result?.success && result.value ? result.value : null;
|
|
1463
|
+
}
|
|
1464
|
+
buildItemFormDefinition() {
|
|
1465
|
+
const excludedAssetTypeId = this.assetTypeId();
|
|
1466
|
+
const group = {
|
|
1467
|
+
name: 'component',
|
|
1468
|
+
title: '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.title',
|
|
1469
|
+
parameters: [
|
|
1470
|
+
{
|
|
1471
|
+
path: 'assetTypeId',
|
|
1472
|
+
title: '@asset-management:assetTypes.entities.assetType.title',
|
|
1473
|
+
widget: {
|
|
1474
|
+
path: 'assetTypeId',
|
|
1475
|
+
type: AXPWidgetsCatalog.lookup,
|
|
1476
|
+
options: {
|
|
1477
|
+
entity: `${RootConfig.module.name}.${RootConfig.entities.assetType.name}`,
|
|
1478
|
+
textField: 'title',
|
|
1479
|
+
valueField: 'id',
|
|
1480
|
+
look: 'select',
|
|
1481
|
+
multiple: false,
|
|
1482
|
+
expose: [
|
|
1483
|
+
{ source: 'id', target: 'assetType.id' },
|
|
1484
|
+
{ source: 'title', target: 'assetType.name' },
|
|
1485
|
+
{ source: 'hasMaintenance', target: 'hasMaintenance' },
|
|
1486
|
+
],
|
|
1487
|
+
...(excludedAssetTypeId
|
|
1488
|
+
? {
|
|
1489
|
+
filter: { field: 'id', operator: { type: 'notEqual' }, value: excludedAssetTypeId },
|
|
1490
|
+
}
|
|
1491
|
+
: {}),
|
|
1492
|
+
validations: [{ rule: 'required' }],
|
|
1493
|
+
},
|
|
1494
|
+
},
|
|
1495
|
+
},
|
|
1496
|
+
this.toFieldDefinition('hasMaintenance', '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.fields.hasMaintenance.title', AXPWidgetsCatalog.toggle),
|
|
1497
|
+
this.toFieldDefinition('count', '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.fields.count.title', AXPWidgetsCatalog.number, [{ rule: 'required' }]),
|
|
1498
|
+
this.toFieldDefinition('roleName', '@asset-management:assetTypeSectionComponents.entities.assetTypeSectionComponent.fields.roleName.title', AXPWidgetsCatalog.largeText),
|
|
1499
|
+
],
|
|
1500
|
+
};
|
|
1501
|
+
return { groups: [group] };
|
|
1502
|
+
}
|
|
1503
|
+
buildSectionFormDefinition() {
|
|
1504
|
+
const group = {
|
|
1505
|
+
name: 'section',
|
|
1506
|
+
title: '@asset-management:assetTypeSections.entities.assetTypeSection.title',
|
|
1507
|
+
parameters: [
|
|
1508
|
+
this.toFieldDefinition('code', '@asset-management:assetTypeSections.entities.assetTypeSection.fields.code.title', AXPWidgetsCatalog.number, [{ rule: 'required' }]),
|
|
1509
|
+
this.toFieldDefinition('title', '@asset-management:assetTypeSections.entities.assetTypeSection.fields.title.title', AXPWidgetsCatalog.text, [{ rule: 'required' }]),
|
|
1510
|
+
this.toFieldDefinition('description', '@asset-management:assetTypeSections.entities.assetTypeSection.fields.description.title', AXPWidgetsCatalog.largeText),
|
|
1511
|
+
],
|
|
1512
|
+
};
|
|
1513
|
+
return { groups: [group] };
|
|
1514
|
+
}
|
|
1515
|
+
buildLinkAssetFormDefinition() {
|
|
1516
|
+
const currentAssetId = this.options()['mainAssetId'];
|
|
1517
|
+
const filters = [
|
|
1518
|
+
...(typeof currentAssetId === 'string' && currentAssetId
|
|
1519
|
+
? [{ field: 'id', operator: { type: 'notEqual' }, value: currentAssetId }]
|
|
1520
|
+
: []),
|
|
1521
|
+
{
|
|
1522
|
+
field: 'assetTypeId',
|
|
1523
|
+
operator: { type: 'equal' },
|
|
1524
|
+
value: "{{ context.eval('assetTypeId') }}",
|
|
1525
|
+
},
|
|
1526
|
+
];
|
|
1527
|
+
const group = {
|
|
1528
|
+
name: 'asset-link',
|
|
1529
|
+
title: '@asset-management:assets.entities.asset.title',
|
|
1530
|
+
parameters: [
|
|
1531
|
+
{
|
|
1532
|
+
path: 'assetId',
|
|
1533
|
+
title: '@asset-management:assets.entities.asset.title',
|
|
1534
|
+
widget: {
|
|
1535
|
+
path: 'assetId',
|
|
1536
|
+
type: AXPWidgetsCatalog.lookup,
|
|
1537
|
+
options: {
|
|
1538
|
+
entity: `${RootConfig.module.name}.${RootConfig.entities.asset.name}`,
|
|
1539
|
+
textField: 'title',
|
|
1540
|
+
valueField: 'id',
|
|
1541
|
+
look: 'lookup',
|
|
1542
|
+
allowSearch: true,
|
|
1543
|
+
hasClearButton: true,
|
|
1544
|
+
columns: ['code', 'title', 'assetTypeId', 'statusId', 'locationId'],
|
|
1545
|
+
expose: [
|
|
1546
|
+
{ source: 'id', target: 'asset.id' },
|
|
1547
|
+
{ source: 'code', target: 'asset.code' },
|
|
1548
|
+
{ source: 'title', target: 'asset.title' },
|
|
1549
|
+
],
|
|
1550
|
+
filter: filters.length === 1 ? filters[0] : { logic: 'and', filters },
|
|
1551
|
+
validations: [{ rule: 'required' }],
|
|
1552
|
+
},
|
|
1553
|
+
},
|
|
1554
|
+
},
|
|
1555
|
+
],
|
|
1556
|
+
};
|
|
1557
|
+
return { groups: [group] };
|
|
1558
|
+
}
|
|
1559
|
+
toFieldDefinition(path, title, widgetType, validations = []) {
|
|
1560
|
+
return {
|
|
1561
|
+
path,
|
|
1562
|
+
title,
|
|
1563
|
+
widget: {
|
|
1564
|
+
path,
|
|
1565
|
+
type: widgetType,
|
|
1566
|
+
...(validations.length > 0 ? { options: { validations } } : {}),
|
|
1567
|
+
},
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
toBuilderValue(value) {
|
|
1571
|
+
return {
|
|
1572
|
+
sections: value.sections.map((section) => ({
|
|
1573
|
+
id: section.id,
|
|
1574
|
+
order: section.code - 1,
|
|
1575
|
+
name: section.id,
|
|
1576
|
+
code: section.code,
|
|
1577
|
+
title: section.title,
|
|
1578
|
+
description: section.description,
|
|
1579
|
+
items: section.items.map((item, itemIndex) => ({
|
|
1580
|
+
id: item.id,
|
|
1581
|
+
order: itemIndex,
|
|
1582
|
+
name: this.resolveLocalizedTextForDialog(item.assetType?.name ?? ''),
|
|
1583
|
+
assetType: item.assetType,
|
|
1584
|
+
roleName: item.roleName,
|
|
1585
|
+
count: item.count,
|
|
1586
|
+
hasMaintenance: item.hasMaintenance,
|
|
1587
|
+
assetTypeId: item.assetTypeId,
|
|
1588
|
+
assetTypeSectionId: item.assetTypeSectionId || section.id,
|
|
1589
|
+
assetTypeSectionComponentId: item.assetTypeSectionComponentId || item.id,
|
|
1590
|
+
assetId: item.assetId,
|
|
1591
|
+
asset: item.asset,
|
|
1592
|
+
})),
|
|
1593
|
+
})),
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
fromBuilderValue(value) {
|
|
1597
|
+
const assetTypeId = this.assetTypeId() ?? '';
|
|
1598
|
+
return {
|
|
1599
|
+
sections: value.sections.map((section, sectionIndex) => {
|
|
1600
|
+
const sectionId = section.id || AXPDataGenerator.uuid();
|
|
1601
|
+
const sectionCodeRaw = Number(section['code'] ?? sectionIndex + 1);
|
|
1602
|
+
const sectionCode = Number.isFinite(sectionCodeRaw) && sectionCodeRaw > 0 ? sectionCodeRaw : sectionIndex + 1;
|
|
1603
|
+
return {
|
|
1604
|
+
id: sectionId,
|
|
1605
|
+
code: sectionCode,
|
|
1606
|
+
title: normalizeAssetTypeBuilderLocalizedField(section['title'], `Section ${sectionCode}`),
|
|
1607
|
+
assetTypeId,
|
|
1608
|
+
description: normalizeAssetTypeBuilderLocalizedField(section['description'], ''),
|
|
1609
|
+
items: section.items.map((item) => this.mapBuilderItemToDomain(item, sectionId, assetTypeId)),
|
|
1610
|
+
};
|
|
1611
|
+
}),
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
mapBuilderItemToDomain(item, sectionId, assetTypeId) {
|
|
1615
|
+
const rawAt = item['assetType'];
|
|
1616
|
+
const normalizedAssetTypeId = (() => {
|
|
1617
|
+
const fromField = typeof item['assetTypeId'] === 'string' ? String(item['assetTypeId']).trim() : '';
|
|
1618
|
+
if (fromField)
|
|
1619
|
+
return fromField;
|
|
1620
|
+
const fromRef = typeof rawAt?.id === 'string' ? String(rawAt.id).trim() : '';
|
|
1621
|
+
if (fromRef)
|
|
1622
|
+
return fromRef;
|
|
1623
|
+
return String(assetTypeId ?? '');
|
|
1624
|
+
})();
|
|
1625
|
+
return {
|
|
1626
|
+
id: item.id || AXPDataGenerator.uuid(),
|
|
1627
|
+
assetTypeSectionId: String(item['assetTypeSectionId'] ?? sectionId),
|
|
1628
|
+
assetTypeId: normalizedAssetTypeId,
|
|
1629
|
+
assetType: {
|
|
1630
|
+
id: String(rawAt?.id ?? normalizedAssetTypeId),
|
|
1631
|
+
name: normalizeAssetTypeBuilderLocalizedField(rawAt?.name, ''),
|
|
1632
|
+
},
|
|
1633
|
+
roleName: normalizeAssetTypeBuilderLocalizedField(item['roleName'], ''),
|
|
1634
|
+
count: Number(item['count'] ?? 1),
|
|
1635
|
+
hasMaintenance: item['hasMaintenance'] === true,
|
|
1636
|
+
assetTypeSectionComponentId: String(item['assetTypeSectionComponentId'] ?? ''),
|
|
1637
|
+
assetId: typeof item['assetId'] === 'string' ? item['assetId'] : undefined,
|
|
1638
|
+
asset: item['asset'] && typeof item['asset'] === 'object'
|
|
1639
|
+
? {
|
|
1640
|
+
id: String(item['asset'].id ?? ''),
|
|
1641
|
+
code: typeof item['asset'].code === 'string'
|
|
1642
|
+
? (item['asset'].code ?? '')
|
|
1643
|
+
: undefined,
|
|
1644
|
+
title: normalizeAssetTypeBuilderLocalizedField(item['asset'].title, ''),
|
|
1645
|
+
}
|
|
1646
|
+
: undefined,
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
resolveLocalizedTextForDialog(value) {
|
|
1650
|
+
if (value == null || value === '') {
|
|
1651
|
+
return '';
|
|
1652
|
+
}
|
|
1653
|
+
if (typeof value === 'string') {
|
|
1654
|
+
return value;
|
|
1655
|
+
}
|
|
1656
|
+
return resolveMultiLanguageString(value, this.translationService.getActiveLang());
|
|
1657
|
+
}
|
|
1658
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeSectionBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1659
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMAssetTypeSectionBuilderComponent, isStandalone: true, selector: "axm-asset-type-section-builder", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, assetTypeId: { classPropertyName: "assetTypeId", publicName: "assetTypeId", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "standardRef", first: true, predicate: AXPStandardSectionItemsBuilderComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"axm-asset-type-section-builder\">\n @if (!readonly() && !hideHeaderActions() && allowAddSection()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n <ax-button\n class=\"ax-sm\"\n [text]=\"'@asset-management:assetTypeSections.entities.assetTypeSection.actions.add-section.title' | translate | async\"\n [color]=\"'primary'\"\n (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder\n class=\"block min-h-[200px]\"\n [value]=\"builderValue()\"\n [config]=\"standardConfig()\"\n [readonly]=\"readonly()\"\n (valueChange)=\"onBuilderValueChange($event)\" />\n</div>\n", styles: [".axm-asset-type-section-builder .__header{margin-bottom:calc(var(--spacing, .25rem) * 3);display:flex;align-items:center;justify-content:space-between}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2.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: AXTranslationModule }, { kind: "component", type: AXPStandardSectionItemsBuilderComponent, selector: "axp-standard-section-items-builder", inputs: ["value", "config", "readonly"], outputs: ["valueChange"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1660
|
+
}
|
|
1661
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeSectionBuilderComponent, decorators: [{
|
|
1662
|
+
type: Component,
|
|
1663
|
+
args: [{ selector: 'axm-asset-type-section-builder', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
1664
|
+
CommonModule,
|
|
1665
|
+
AXButtonModule,
|
|
1666
|
+
AXDecoratorModule,
|
|
1667
|
+
AXTranslationModule,
|
|
1668
|
+
AXPStandardSectionItemsBuilderComponent,
|
|
1669
|
+
], template: "<div class=\"axm-asset-type-section-builder\">\n @if (!readonly() && !hideHeaderActions() && allowAddSection()) {\n <div class=\"__header\">\n <div class=\"__header-left\"></div>\n <div class=\"__header-right\">\n <ax-button\n class=\"ax-sm\"\n [text]=\"'@asset-management:assetTypeSections.entities.assetTypeSection.actions.add-section.title' | translate | async\"\n [color]=\"'primary'\"\n (onClick)=\"addSection()\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-layer-group\"></ax-icon>\n </ax-prefix>\n </ax-button>\n </div>\n </div>\n }\n\n <axp-standard-section-items-builder\n class=\"block min-h-[200px]\"\n [value]=\"builderValue()\"\n [config]=\"standardConfig()\"\n [readonly]=\"readonly()\"\n (valueChange)=\"onBuilderValueChange($event)\" />\n</div>\n", styles: [".axm-asset-type-section-builder .__header{margin-bottom:calc(var(--spacing, .25rem) * 3);display:flex;align-items:center;justify-content:space-between}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
|
|
1670
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], assetTypeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "assetTypeId", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], standardRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPStandardSectionItemsBuilderComponent), { isSignal: true }] }] } });
|
|
1671
|
+
|
|
1672
|
+
const ASSET_TYPE_COMPONENTS_SAVE_COMMAND = 'AssetType:Components:Save';
|
|
1673
|
+
class AXMSaveAssetTypeComponentsCommand {
|
|
1674
|
+
constructor() {
|
|
1675
|
+
this.entityService = inject(AXPEntityService);
|
|
1676
|
+
this.translationService = inject(AXTranslationService);
|
|
1677
|
+
}
|
|
1678
|
+
async execute(input) {
|
|
1679
|
+
const id = input?.id;
|
|
1680
|
+
const entityRef = input?.entity || `${RootConfig.module.name}.${RootConfig.entities.assetType.name}`;
|
|
1681
|
+
const field = input?.field || 'components';
|
|
1682
|
+
const value = input?.value ?? { sections: [] };
|
|
1683
|
+
if (!id) {
|
|
1684
|
+
return {
|
|
1685
|
+
success: false,
|
|
1686
|
+
message: {
|
|
1687
|
+
text: await this.translationService.translateAsync('@general:messages.entity.invalid-data'),
|
|
1688
|
+
},
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
try {
|
|
1692
|
+
const payload = { [field]: value };
|
|
1693
|
+
const isAssetTypeComponentsUpdate = entityRef === `${RootConfig.module.name}.${RootConfig.entities.assetType.name}` && field === 'components';
|
|
1694
|
+
if (isAssetTypeComponentsUpdate) {
|
|
1695
|
+
payload['name'] = this.ensureLatinName(input.name, {
|
|
1696
|
+
fallback: input.title,
|
|
1697
|
+
id,
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
await this.entityService.withEntity(entityRef).data().update(id, payload);
|
|
1701
|
+
return { success: true, kind: 'object',
|
|
1702
|
+
data: { id, field, value },
|
|
1703
|
+
message: {
|
|
1704
|
+
text: await this.translationService.translateAsync('@general:messages.generic.success.description'),
|
|
1705
|
+
},
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
catch (error) {
|
|
1709
|
+
const message = error instanceof Error
|
|
1710
|
+
? error.message
|
|
1711
|
+
: await this.translationService.translateAsync('@general:messages.generic.error.description');
|
|
1712
|
+
return {
|
|
1713
|
+
success: false,
|
|
1714
|
+
message: {
|
|
1715
|
+
text: message,
|
|
1716
|
+
},
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
ensureLatinName(raw, context) {
|
|
1721
|
+
const fromRaw = this.toLatinIdentifier(raw);
|
|
1722
|
+
if (fromRaw) {
|
|
1723
|
+
return fromRaw;
|
|
1724
|
+
}
|
|
1725
|
+
const fromTitle = this.toLatinIdentifier(context?.fallback);
|
|
1726
|
+
if (fromTitle) {
|
|
1727
|
+
return fromTitle;
|
|
1728
|
+
}
|
|
1729
|
+
const fromId = this.toLatinIdentifier(context?.id);
|
|
1730
|
+
if (fromId) {
|
|
1731
|
+
return fromId;
|
|
1732
|
+
}
|
|
1733
|
+
return 'asset_type';
|
|
1734
|
+
}
|
|
1735
|
+
toLatinIdentifier(value) {
|
|
1736
|
+
if (typeof value !== 'string') {
|
|
1737
|
+
return '';
|
|
1738
|
+
}
|
|
1739
|
+
return value
|
|
1740
|
+
.replace(/[^A-Za-z0-9_-]+/g, '_')
|
|
1741
|
+
.replace(/^_+|_+$/g, '')
|
|
1742
|
+
.replace(/_{2,}/g, '_');
|
|
1743
|
+
}
|
|
1744
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMSaveAssetTypeComponentsCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1745
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMSaveAssetTypeComponentsCommand, providedIn: 'root' }); }
|
|
1746
|
+
}
|
|
1747
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMSaveAssetTypeComponentsCommand, decorators: [{
|
|
1748
|
+
type: Injectable,
|
|
1749
|
+
args: [{
|
|
1750
|
+
providedIn: 'root',
|
|
1751
|
+
}]
|
|
1752
|
+
}] });
|
|
1753
|
+
|
|
1754
|
+
var saveAssetTypeComponents_command = /*#__PURE__*/Object.freeze({
|
|
1755
|
+
__proto__: null,
|
|
1756
|
+
ASSET_TYPE_COMPONENTS_SAVE_COMMAND: ASSET_TYPE_COMPONENTS_SAVE_COMMAND,
|
|
1757
|
+
AXMSaveAssetTypeComponentsCommand: AXMSaveAssetTypeComponentsCommand
|
|
1758
|
+
});
|
|
1759
|
+
|
|
1760
|
+
const ASSET_TYPE_SECTIONS_ADD_SECTION_COMMAND = 'AssetType:Sections:AddSection';
|
|
1761
|
+
const ASSET_TYPE_SECTIONS_DISCARD_COMMAND = 'AssetType:Sections:Discard';
|
|
1762
|
+
const ASSET_TYPE_SECTIONS_SAVE_COMMAND = 'AssetType:Sections:Save';
|
|
1763
|
+
class AXMAssetTypeSectionBuilderPageComponent extends AXPPageLayoutBaseComponent {
|
|
1764
|
+
constructor() {
|
|
1765
|
+
super(...arguments);
|
|
1766
|
+
/** Default `{}`: required inputs throw (NG0950) if read before `AXPPageComponentRendererDirective` calls `setInput` after `createComponent`. */
|
|
1767
|
+
this.rootContext = input({}, /* @ts-ignore */
|
|
1768
|
+
...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
|
|
1769
|
+
this.pageConfig = input(/* @ts-ignore */
|
|
1770
|
+
...(ngDevMode ? [undefined, { debugName: "pageConfig" }] : /* istanbul ignore next */ []));
|
|
1771
|
+
this.options = input({}, /* @ts-ignore */
|
|
1772
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
1773
|
+
this.builderRef = viewChild('builderRef', /* @ts-ignore */
|
|
1774
|
+
...(ngDevMode ? [{ debugName: "builderRef" }] : /* istanbul ignore next */ []));
|
|
1775
|
+
this.commandService = inject(AXPCommandService);
|
|
1776
|
+
this.entityService = inject(AXPEntityService);
|
|
1777
|
+
this.hostPageLayout = inject(AXPPageLayoutBase, { optional: true, skipSelf: true });
|
|
1778
|
+
this.baselineValue = signal(null, /* @ts-ignore */
|
|
1779
|
+
...(ngDevMode ? [{ debugName: "baselineValue" }] : /* istanbul ignore next */ []));
|
|
1780
|
+
this.committedValue = signal(null, /* @ts-ignore */
|
|
1781
|
+
...(ngDevMode ? [{ debugName: "committedValue" }] : /* istanbul ignore next */ []));
|
|
1782
|
+
this.config = computed(() => ({
|
|
1783
|
+
...(this.pageConfig() ?? {}),
|
|
1784
|
+
...(this.options() ?? {}),
|
|
1785
|
+
}), /* @ts-ignore */
|
|
1786
|
+
...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
1787
|
+
this.fieldName = computed(() => {
|
|
1788
|
+
const field = this.readStringConfig('field');
|
|
1789
|
+
return field || 'components';
|
|
1790
|
+
}, /* @ts-ignore */
|
|
1791
|
+
...(ngDevMode ? [{ debugName: "fieldName" }] : /* istanbul ignore next */ []));
|
|
1792
|
+
this.sourceFieldName = computed(() => {
|
|
1793
|
+
const field = this.readStringConfig('sourceField');
|
|
1794
|
+
return field || this.fieldName();
|
|
1795
|
+
}, /* @ts-ignore */
|
|
1796
|
+
...(ngDevMode ? [{ debugName: "sourceFieldName" }] : /* istanbul ignore next */ []));
|
|
1797
|
+
this.sourceIdPath = computed(() => {
|
|
1798
|
+
const path = this.readStringConfig('sourceIdPath');
|
|
1799
|
+
return path || 'id';
|
|
1800
|
+
}, /* @ts-ignore */
|
|
1801
|
+
...(ngDevMode ? [{ debugName: "sourceIdPath" }] : /* istanbul ignore next */ []));
|
|
1802
|
+
this.targetIdPath = computed(() => {
|
|
1803
|
+
const path = this.readStringConfig('targetIdPath');
|
|
1804
|
+
return path || this.sourceIdPath();
|
|
1805
|
+
}, /* @ts-ignore */
|
|
1806
|
+
...(ngDevMode ? [{ debugName: "targetIdPath" }] : /* istanbul ignore next */ []));
|
|
1807
|
+
this.sourceEntityRef = computed(() => {
|
|
1808
|
+
const entity = this.readStringConfig('sourceEntity');
|
|
1809
|
+
return entity || `${RootConfig.module.name}.${RootConfig.entities.assetType.name}`;
|
|
1810
|
+
}, /* @ts-ignore */
|
|
1811
|
+
...(ngDevMode ? [{ debugName: "sourceEntityRef" }] : /* istanbul ignore next */ []));
|
|
1812
|
+
this.targetEntityRef = computed(() => {
|
|
1813
|
+
const entity = this.readStringConfig('targetEntity');
|
|
1814
|
+
return entity || this.sourceEntityRef();
|
|
1815
|
+
}, /* @ts-ignore */
|
|
1816
|
+
...(ngDevMode ? [{ debugName: "targetEntityRef" }] : /* istanbul ignore next */ []));
|
|
1817
|
+
this.context = computed(() => this.rootContext(), /* @ts-ignore */
|
|
1818
|
+
...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
1819
|
+
this.sourceRecordId = computed(() => {
|
|
1820
|
+
const id = get(this.context(), this.sourceIdPath());
|
|
1821
|
+
return typeof id === 'string' ? id : undefined;
|
|
1822
|
+
}, /* @ts-ignore */
|
|
1823
|
+
...(ngDevMode ? [{ debugName: "sourceRecordId" }] : /* istanbul ignore next */ []));
|
|
1824
|
+
this.targetRecordId = computed(() => {
|
|
1825
|
+
const id = get(this.context(), this.targetIdPath());
|
|
1826
|
+
return typeof id === 'string' ? id : undefined;
|
|
1827
|
+
}, /* @ts-ignore */
|
|
1828
|
+
...(ngDevMode ? [{ debugName: "targetRecordId" }] : /* istanbul ignore next */ []));
|
|
1829
|
+
this.readonly = computed(() => this.readBooleanConfig('readonly'), /* @ts-ignore */
|
|
1830
|
+
...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1831
|
+
this.linkAssetMode = computed(() => this.readBooleanConfig('linkAssetMode'), /* @ts-ignore */
|
|
1832
|
+
...(ngDevMode ? [{ debugName: "linkAssetMode" }] : /* istanbul ignore next */ []));
|
|
1833
|
+
this.allowAddSection = computed(() => this.readBooleanConfig('allowAddSection', true), /* @ts-ignore */
|
|
1834
|
+
...(ngDevMode ? [{ debugName: "allowAddSection" }] : /* istanbul ignore next */ []));
|
|
1835
|
+
this.allowAddItems = computed(() => this.readBooleanConfig('allowAddItems', true), /* @ts-ignore */
|
|
1836
|
+
...(ngDevMode ? [{ debugName: "allowAddItems" }] : /* istanbul ignore next */ []));
|
|
1837
|
+
this.allowEditSection = computed(() => this.readBooleanConfig('allowEditSection', true), /* @ts-ignore */
|
|
1838
|
+
...(ngDevMode ? [{ debugName: "allowEditSection" }] : /* istanbul ignore next */ []));
|
|
1839
|
+
this.allowReorderSections = computed(() => this.readBooleanConfig('allowReorderSections', true), /* @ts-ignore */
|
|
1840
|
+
...(ngDevMode ? [{ debugName: "allowReorderSections" }] : /* istanbul ignore next */ []));
|
|
1841
|
+
this.builderOptions = computed(() => ({
|
|
1842
|
+
hideHeaderActions: true,
|
|
1843
|
+
readonly: this.readonly(),
|
|
1844
|
+
linkAssetMode: this.linkAssetMode(),
|
|
1845
|
+
mainAssetId: this.targetRecordId(),
|
|
1846
|
+
allowAddSection: this.allowAddSection(),
|
|
1847
|
+
allowEditSection: this.allowEditSection(),
|
|
1848
|
+
allowAddItems: this.allowAddItems(),
|
|
1849
|
+
allowReorderSections: this.allowReorderSections(),
|
|
1850
|
+
}), /* @ts-ignore */
|
|
1851
|
+
...(ngDevMode ? [{ debugName: "builderOptions" }] : /* istanbul ignore next */ []));
|
|
1852
|
+
this.isDirty = computed(() => {
|
|
1853
|
+
const baseline = this.baselineValue();
|
|
1854
|
+
const committed = this.committedValue();
|
|
1855
|
+
return !isEqual(baseline ?? null, committed ?? null);
|
|
1856
|
+
}, /* @ts-ignore */
|
|
1857
|
+
...(ngDevMode ? [{ debugName: "isDirty" }] : /* istanbul ignore next */ []));
|
|
1858
|
+
this.#syncFromContext = effect((onCleanup) => {
|
|
1859
|
+
const ctx = this.context();
|
|
1860
|
+
const id = this.sourceRecordId();
|
|
1861
|
+
const value = get(ctx, this.fieldName());
|
|
1862
|
+
const linkedFromContext = get(ctx, this.fieldName());
|
|
1863
|
+
const sourceValue = get(ctx, this.sourceFieldName());
|
|
1864
|
+
const sourceField = this.sourceFieldName();
|
|
1865
|
+
const immediateValue = this.linkAssetMode()
|
|
1866
|
+
? this.buildLinkedAssetValue(sourceValue ?? null, this.pickPersistedComponentLinks(linkedFromContext, undefined))
|
|
1867
|
+
: (value ?? null);
|
|
1868
|
+
this.baselineValue.set(immediateValue);
|
|
1869
|
+
this.committedValue.set(immediateValue);
|
|
1870
|
+
untracked(() => this.recompute());
|
|
1871
|
+
if (!id) {
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
let cancelled = false;
|
|
1875
|
+
const sourceEntityRef = this.sourceEntityRef();
|
|
1876
|
+
const targetEntityRef = this.targetEntityRef();
|
|
1877
|
+
const targetRecordId = this.targetRecordId();
|
|
1878
|
+
const linkMode = this.linkAssetMode();
|
|
1879
|
+
const fieldName = this.fieldName();
|
|
1880
|
+
const shouldFetchPersistedLinksFromTarget = linkMode &&
|
|
1881
|
+
typeof targetRecordId === 'string' &&
|
|
1882
|
+
targetRecordId.length > 0 &&
|
|
1883
|
+
targetEntityRef !== sourceEntityRef;
|
|
1884
|
+
const load = async () => {
|
|
1885
|
+
try {
|
|
1886
|
+
const [sourceRecord, targetRecord] = await Promise.all([
|
|
1887
|
+
this.entityService.withEntity(sourceEntityRef).data().byKey(id),
|
|
1888
|
+
shouldFetchPersistedLinksFromTarget
|
|
1889
|
+
? this.entityService.withEntity(targetEntityRef).data().byKey(targetRecordId)
|
|
1890
|
+
: Promise.resolve(null),
|
|
1891
|
+
]);
|
|
1892
|
+
if (cancelled)
|
|
1893
|
+
return;
|
|
1894
|
+
const fallbackValue = get(sourceRecord, sourceField);
|
|
1895
|
+
const recordLinksUnknown = linkMode && shouldFetchPersistedLinksFromTarget
|
|
1896
|
+
? get(targetRecord, fieldName)
|
|
1897
|
+
: linkMode
|
|
1898
|
+
? get(sourceRecord, fieldName)
|
|
1899
|
+
: undefined;
|
|
1900
|
+
const resolved = linkMode
|
|
1901
|
+
? this.buildLinkedAssetValue(sourceValue ?? fallbackValue ?? null, this.pickPersistedComponentLinks(linkedFromContext, recordLinksUnknown))
|
|
1902
|
+
: this.hasSections(value)
|
|
1903
|
+
? value
|
|
1904
|
+
: (fallbackValue ?? null);
|
|
1905
|
+
this.baselineValue.set(resolved);
|
|
1906
|
+
this.committedValue.set(resolved);
|
|
1907
|
+
untracked(() => this.recompute());
|
|
1908
|
+
}
|
|
1909
|
+
catch {
|
|
1910
|
+
if (cancelled)
|
|
1911
|
+
return;
|
|
1912
|
+
this.baselineValue.set(immediateValue);
|
|
1913
|
+
this.committedValue.set(immediateValue);
|
|
1914
|
+
untracked(() => this.recompute());
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
void load();
|
|
1918
|
+
onCleanup(() => {
|
|
1919
|
+
cancelled = true;
|
|
1920
|
+
});
|
|
1921
|
+
}, /* @ts-ignore */
|
|
1922
|
+
...(ngDevMode ? [{ debugName: "#syncFromContext" }] : /* istanbul ignore next */ []));
|
|
1923
|
+
}
|
|
1924
|
+
#syncFromContext;
|
|
1925
|
+
onValueChange(value) {
|
|
1926
|
+
this.committedValue.set(value);
|
|
1927
|
+
this.updateRootContextField(this.fieldName(), this.linkAssetMode() ? this.toAssetComponentValue(value) : value);
|
|
1928
|
+
this.recompute();
|
|
1929
|
+
}
|
|
1930
|
+
getWizardStepContext() {
|
|
1931
|
+
const field = this.fieldName();
|
|
1932
|
+
const value = this.committedValue();
|
|
1933
|
+
if (!field || value == null) {
|
|
1934
|
+
return null;
|
|
1935
|
+
}
|
|
1936
|
+
const ctxValue = this.linkAssetMode() ? this.toAssetComponentValue(value) : value;
|
|
1937
|
+
return { [field]: cloneDeep(ctxValue) };
|
|
1938
|
+
}
|
|
1939
|
+
hasUnsavedChanges() {
|
|
1940
|
+
return this.isDirty();
|
|
1941
|
+
}
|
|
1942
|
+
async getPrimaryMenuItems() {
|
|
1943
|
+
if (this.readonly()) {
|
|
1944
|
+
return [];
|
|
1945
|
+
}
|
|
1946
|
+
const addSectionTitle = (await this.translateService.translateAsync('@asset-management:assetTypeSections.entities.assetTypeSection.actions.add-section.title')) || 'Add Section';
|
|
1947
|
+
const discardTitle = (await this.translateService.translateAsync('@general:actions.discard.title')) || 'Discard';
|
|
1948
|
+
const saveTitle = (await this.translateService.translateAsync('@general:actions.save.title')) || 'Save';
|
|
1949
|
+
return [
|
|
1950
|
+
...(this.allowAddSection()
|
|
1951
|
+
? [
|
|
1952
|
+
{
|
|
1953
|
+
title: addSectionTitle,
|
|
1954
|
+
icon: 'fa-light fa-layer-group',
|
|
1955
|
+
zone: 'header',
|
|
1956
|
+
priority: 'primary',
|
|
1957
|
+
color: 'primary',
|
|
1958
|
+
command: { name: ASSET_TYPE_SECTIONS_ADD_SECTION_COMMAND, options: {} },
|
|
1959
|
+
},
|
|
1960
|
+
]
|
|
1961
|
+
: []),
|
|
1962
|
+
{
|
|
1963
|
+
title: discardTitle,
|
|
1964
|
+
icon: 'fa-light fa-rotate-left',
|
|
1965
|
+
zone: 'footer',
|
|
1966
|
+
priority: 'secondary',
|
|
1967
|
+
color: 'default',
|
|
1968
|
+
visible: this.isDirty(),
|
|
1969
|
+
command: { name: ASSET_TYPE_SECTIONS_DISCARD_COMMAND, options: {} },
|
|
1970
|
+
},
|
|
1971
|
+
{
|
|
1972
|
+
title: saveTitle,
|
|
1973
|
+
icon: 'fa-light fa-floppy-disk',
|
|
1974
|
+
zone: 'footer',
|
|
1975
|
+
priority: 'primary',
|
|
1976
|
+
color: 'primary',
|
|
1977
|
+
visible: this.isDirty(),
|
|
1978
|
+
command: { name: ASSET_TYPE_SECTIONS_SAVE_COMMAND, options: {} },
|
|
1979
|
+
},
|
|
1980
|
+
];
|
|
1981
|
+
}
|
|
1982
|
+
async execute(command) {
|
|
1983
|
+
if (command.name === ASSET_TYPE_SECTIONS_ADD_SECTION_COMMAND) {
|
|
1984
|
+
await this.builderRef()?.addSection();
|
|
1985
|
+
return;
|
|
1986
|
+
}
|
|
1987
|
+
if (command.name === ASSET_TYPE_SECTIONS_DISCARD_COMMAND) {
|
|
1988
|
+
this.handleDiscard();
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (command.name !== ASSET_TYPE_SECTIONS_SAVE_COMMAND)
|
|
1992
|
+
return;
|
|
1993
|
+
await this.handleSave({ silent: false });
|
|
1994
|
+
}
|
|
1995
|
+
async handleSave(options) {
|
|
1996
|
+
const silent = options?.silent === true;
|
|
1997
|
+
const id = this.targetRecordId();
|
|
1998
|
+
const entity = this.targetEntityRef();
|
|
1999
|
+
const field = this.fieldName();
|
|
2000
|
+
const value = this.committedValue();
|
|
2001
|
+
if (!id || !entity || !field) {
|
|
2002
|
+
if (!silent) {
|
|
2003
|
+
this.toastService.show({
|
|
2004
|
+
color: 'danger',
|
|
2005
|
+
title: await this.translateService.translateAsync('@general:messages.error.title'),
|
|
2006
|
+
content: await this.translateService.translateAsync('@general:messages.entity.invalid-data'),
|
|
2007
|
+
});
|
|
2008
|
+
}
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
const root = (this.rootContext() ?? {});
|
|
2012
|
+
const result = await this.commandService.execute(ASSET_TYPE_COMPONENTS_SAVE_COMMAND, {
|
|
2013
|
+
id,
|
|
2014
|
+
entity,
|
|
2015
|
+
field,
|
|
2016
|
+
value: this.linkAssetMode() ? this.toAssetComponentValue(value ?? { sections: [] }) : (value ?? { sections: [] }),
|
|
2017
|
+
name: root['name'],
|
|
2018
|
+
title: root['title'],
|
|
2019
|
+
});
|
|
2020
|
+
if (result?.success) {
|
|
2021
|
+
const saved = value ?? { sections: [] };
|
|
2022
|
+
this.baselineValue.set(saved);
|
|
2023
|
+
this.committedValue.set(saved);
|
|
2024
|
+
this.updateRootContextField(field, this.linkAssetMode() ? this.toAssetComponentValue(saved) : saved);
|
|
2025
|
+
this.builderRef()?.syncAfterSave(saved);
|
|
2026
|
+
this.recompute();
|
|
2027
|
+
if (!silent) {
|
|
2028
|
+
this.toastService.show({
|
|
2029
|
+
color: 'success',
|
|
2030
|
+
title: await this.translateService.translateAsync('@general:messages.generic.success.title'),
|
|
2031
|
+
content: await this.translateService.translateAsync('@general:messages.generic.success.description'),
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
this.toastService.show({
|
|
2037
|
+
color: 'danger',
|
|
2038
|
+
title: await this.translateService.translateAsync('@general:messages.error.title'),
|
|
2039
|
+
content: await this.translateService.translateAsync('@general:messages.entity.update-failed'),
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
2042
|
+
recompute() {
|
|
2043
|
+
super.recompute();
|
|
2044
|
+
const layout = this.hostPageLayout;
|
|
2045
|
+
layout?.recompute?.();
|
|
2046
|
+
}
|
|
2047
|
+
handleDiscard() {
|
|
2048
|
+
const baseline = this.baselineValue() ?? { sections: [] };
|
|
2049
|
+
const field = this.fieldName();
|
|
2050
|
+
this.committedValue.set(baseline);
|
|
2051
|
+
this.updateRootContextField(field, this.linkAssetMode() ? this.toAssetComponentValue(baseline) : baseline);
|
|
2052
|
+
this.builderRef()?.resetAfterDiscard();
|
|
2053
|
+
this.recompute();
|
|
2054
|
+
}
|
|
2055
|
+
/** Keeps details-view `rootContext` in sync so sidebar navigation remounts with latest data. */
|
|
2056
|
+
updateRootContextField(field, value) {
|
|
2057
|
+
const ctx = this.rootContext();
|
|
2058
|
+
if (!ctx || typeof ctx !== 'object') {
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
ctx[field] = cloneDeep(value);
|
|
2062
|
+
}
|
|
2063
|
+
buildLinkedAssetValue(source, links) {
|
|
2064
|
+
if (!source || !Array.isArray(source.sections)) {
|
|
2065
|
+
return { sections: [] };
|
|
2066
|
+
}
|
|
2067
|
+
const groupedLinks = new Map();
|
|
2068
|
+
for (const link of links ?? []) {
|
|
2069
|
+
const key = String(link.assetTypeSectionComponentId ?? '');
|
|
2070
|
+
if (!key)
|
|
2071
|
+
continue;
|
|
2072
|
+
if (!groupedLinks.has(key))
|
|
2073
|
+
groupedLinks.set(key, []);
|
|
2074
|
+
groupedLinks.get(key).push(link);
|
|
2075
|
+
}
|
|
2076
|
+
return {
|
|
2077
|
+
sections: source.sections.map((section) => ({
|
|
2078
|
+
...section,
|
|
2079
|
+
items: (section.items ?? []).flatMap((item) => {
|
|
2080
|
+
const componentId = String(item.id ?? '');
|
|
2081
|
+
const count = Math.max(1, Number(item.count ?? 1));
|
|
2082
|
+
const existing = groupedLinks.get(componentId) ?? [];
|
|
2083
|
+
return Array.from({ length: count }).map((_, index) => {
|
|
2084
|
+
const linked = existing[index];
|
|
2085
|
+
return {
|
|
2086
|
+
...item,
|
|
2087
|
+
id: `${componentId}__slot_${index + 1}`,
|
|
2088
|
+
count: 1,
|
|
2089
|
+
assetTypeSectionComponentId: componentId,
|
|
2090
|
+
roleName: this.withSlotSuffix(item.roleName, index + 1),
|
|
2091
|
+
assetId: linked?.assetId,
|
|
2092
|
+
asset: linked?.asset
|
|
2093
|
+
? {
|
|
2094
|
+
id: linked.asset.id,
|
|
2095
|
+
code: linked.asset.code,
|
|
2096
|
+
title: linked.asset.title,
|
|
2097
|
+
}
|
|
2098
|
+
: undefined,
|
|
2099
|
+
};
|
|
2100
|
+
});
|
|
2101
|
+
}),
|
|
2102
|
+
})),
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
withSlotSuffix(value, slotIndex) {
|
|
2106
|
+
const normalized = normalizeAssetTypeBuilderLocalizedField(value, '');
|
|
2107
|
+
const suffix = `#${slotIndex}`;
|
|
2108
|
+
if (typeof normalized === 'string') {
|
|
2109
|
+
const base = normalized.trim();
|
|
2110
|
+
return base ? `${base} ${suffix}` : suffix;
|
|
2111
|
+
}
|
|
2112
|
+
return Object.fromEntries(Object.entries(normalized).map(([locale, text]) => {
|
|
2113
|
+
const trimmed = typeof text === 'string' ? text.trim() : '';
|
|
2114
|
+
return [locale, trimmed ? `${trimmed} ${suffix}` : suffix];
|
|
2115
|
+
}));
|
|
2116
|
+
}
|
|
2117
|
+
toAssetComponentValue(value) {
|
|
2118
|
+
const mainAssetId = this.targetRecordId() ?? '';
|
|
2119
|
+
return value.sections.flatMap((section) => (section.items ?? [])
|
|
2120
|
+
.filter((item) => typeof item.assetId === 'string' && item.assetId)
|
|
2121
|
+
.map((item) => ({
|
|
2122
|
+
id: item.id,
|
|
2123
|
+
assetId: String(item.assetId),
|
|
2124
|
+
asset: {
|
|
2125
|
+
id: String(item.asset?.id ?? item.assetId),
|
|
2126
|
+
code: String(item.asset?.code ?? ''),
|
|
2127
|
+
title: String(item.asset?.title ?? ''),
|
|
2128
|
+
},
|
|
2129
|
+
mainAssetId,
|
|
2130
|
+
mainAsset: {
|
|
2131
|
+
id: mainAssetId,
|
|
2132
|
+
code: '',
|
|
2133
|
+
title: '',
|
|
2134
|
+
},
|
|
2135
|
+
assetTypeSectionComponentId: String(item.assetTypeSectionComponentId ?? ''),
|
|
2136
|
+
assetTypeSectionComponent: {
|
|
2137
|
+
id: String(item.assetTypeSectionComponentId ?? ''),
|
|
2138
|
+
code: String(item.assetTypeSectionId ?? ''),
|
|
2139
|
+
title: String(item.roleName ?? ''),
|
|
2140
|
+
assetTypeId: String(item.assetTypeId ?? ''),
|
|
2141
|
+
assetType: {
|
|
2142
|
+
id: String(item.assetType?.id ?? String(item.assetTypeId ?? '')),
|
|
2143
|
+
name: item.assetType?.name ?? '',
|
|
2144
|
+
},
|
|
2145
|
+
},
|
|
2146
|
+
})));
|
|
2147
|
+
}
|
|
2148
|
+
readStringConfig(key) {
|
|
2149
|
+
const rootValue = this.config()[key];
|
|
2150
|
+
if (typeof rootValue === 'string') {
|
|
2151
|
+
return rootValue;
|
|
2152
|
+
}
|
|
2153
|
+
return '';
|
|
2154
|
+
}
|
|
2155
|
+
readBooleanConfig(key, defaultValue = false) {
|
|
2156
|
+
const rootValue = this.config()[key];
|
|
2157
|
+
if (typeof rootValue === 'boolean') {
|
|
2158
|
+
return rootValue;
|
|
2159
|
+
}
|
|
2160
|
+
return defaultValue;
|
|
2161
|
+
}
|
|
2162
|
+
hasSections(value) {
|
|
2163
|
+
return !!value && Array.isArray(value.sections) && value.sections.length > 0;
|
|
2164
|
+
}
|
|
2165
|
+
/**
|
|
2166
|
+
* Prefer links loaded with the record (`byKey`). Context often holds `assetComponents: []` from a
|
|
2167
|
+
* partial row merge; `[] ?? serverLinks` would keep the empty array and hide persisted assignments.
|
|
2168
|
+
*/
|
|
2169
|
+
pickPersistedComponentLinks(contextLinks, recordLinks) {
|
|
2170
|
+
if (recordLinks !== undefined) {
|
|
2171
|
+
return Array.isArray(recordLinks) ? recordLinks : [];
|
|
2172
|
+
}
|
|
2173
|
+
return Array.isArray(contextLinks) ? contextLinks : null;
|
|
2174
|
+
}
|
|
2175
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeSectionBuilderPageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2176
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.8", type: AXMAssetTypeSectionBuilderPageComponent, isStandalone: true, selector: "axm-asset-type-section-builder-page", inputs: { rootContext: { classPropertyName: "rootContext", publicName: "rootContext", isSignal: true, isRequired: false, transformFunction: null }, pageConfig: { classPropertyName: "pageConfig", publicName: "pageConfig", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.axp-page-layout-base": "true" } }, providers: [
|
|
2177
|
+
{
|
|
2178
|
+
provide: AXPPageLayoutBase,
|
|
2179
|
+
useExisting: AXMAssetTypeSectionBuilderPageComponent,
|
|
2180
|
+
},
|
|
2181
|
+
], viewQueries: [{ propertyName: "builderRef", first: true, predicate: ["builderRef"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
2182
|
+
<axm-asset-type-section-builder
|
|
2183
|
+
#builderRef
|
|
2184
|
+
[value]="committedValue()"
|
|
2185
|
+
[assetTypeId]="sourceRecordId()"
|
|
2186
|
+
[options]="builderOptions()"
|
|
2187
|
+
(valueChange)="onValueChange($event)"
|
|
2188
|
+
/>
|
|
2189
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AXMAssetTypeSectionBuilderComponent, selector: "axm-asset-type-section-builder", inputs: ["value", "assetTypeId", "options"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2190
|
+
}
|
|
2191
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeSectionBuilderPageComponent, decorators: [{
|
|
2192
|
+
type: Component,
|
|
2193
|
+
args: [{
|
|
2194
|
+
selector: 'axm-asset-type-section-builder-page',
|
|
2195
|
+
standalone: true,
|
|
2196
|
+
imports: [AXMAssetTypeSectionBuilderComponent],
|
|
2197
|
+
providers: [
|
|
2198
|
+
{
|
|
2199
|
+
provide: AXPPageLayoutBase,
|
|
2200
|
+
useExisting: AXMAssetTypeSectionBuilderPageComponent,
|
|
2201
|
+
},
|
|
2202
|
+
],
|
|
2203
|
+
template: `
|
|
2204
|
+
<axm-asset-type-section-builder
|
|
2205
|
+
#builderRef
|
|
2206
|
+
[value]="committedValue()"
|
|
2207
|
+
[assetTypeId]="sourceRecordId()"
|
|
2208
|
+
[options]="builderOptions()"
|
|
2209
|
+
(valueChange)="onValueChange($event)"
|
|
2210
|
+
/>
|
|
2211
|
+
`,
|
|
2212
|
+
host: {
|
|
2213
|
+
'[class.axp-page-layout-base]': 'true',
|
|
2214
|
+
},
|
|
2215
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2216
|
+
}]
|
|
2217
|
+
}], propDecorators: { rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], builderRef: [{ type: i0.ViewChild, args: ['builderRef', { isSignal: true }] }] } });
|
|
2218
|
+
|
|
2219
|
+
var assetTypeSectionBuilderPage_component = /*#__PURE__*/Object.freeze({
|
|
2220
|
+
__proto__: null,
|
|
2221
|
+
AXMAssetTypeSectionBuilderPageComponent: AXMAssetTypeSectionBuilderPageComponent
|
|
2222
|
+
});
|
|
2223
|
+
|
|
2224
|
+
class AXMAssetTypeComponentsPageComponentProvider {
|
|
2225
|
+
async components() {
|
|
2226
|
+
return [
|
|
2227
|
+
{
|
|
2228
|
+
key: ASSET_TYPE_COMPONENTS_PAGE_COMPONENT_KEY,
|
|
2229
|
+
loader: () => Promise.resolve().then(function () { return assetTypeSectionBuilderPage_component; }).then((m) => m.AXMAssetTypeSectionBuilderPageComponent),
|
|
2230
|
+
},
|
|
2231
|
+
];
|
|
2232
|
+
}
|
|
2233
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeComponentsPageComponentProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2234
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeComponentsPageComponentProvider }); }
|
|
2235
|
+
}
|
|
2236
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetTypeComponentsPageComponentProvider, decorators: [{
|
|
2237
|
+
type: Injectable
|
|
2238
|
+
}] });
|
|
2239
|
+
|
|
2240
|
+
var index = /*#__PURE__*/_mergeNamespaces({
|
|
2241
|
+
__proto__: null,
|
|
2242
|
+
ASSET_TYPE_COMPONENTS_SAVE_COMMAND: ASSET_TYPE_COMPONENTS_SAVE_COMMAND,
|
|
2243
|
+
AXMAssetTypeComponentsPageComponentProvider: AXMAssetTypeComponentsPageComponentProvider,
|
|
2244
|
+
AXMAssetTypeSectionBuilderComponent: AXMAssetTypeSectionBuilderComponent,
|
|
2245
|
+
AXMAssetTypeSectionBuilderPageComponent: AXMAssetTypeSectionBuilderPageComponent,
|
|
2246
|
+
AXMSaveAssetTypeComponentsCommand: AXMSaveAssetTypeComponentsCommand,
|
|
2247
|
+
createAssetTypeSectionBuilderDefaultValue: createAssetTypeSectionBuilderDefaultValue,
|
|
2248
|
+
normalizeAssetTypeBuilderLocalizedField: normalizeAssetTypeBuilderLocalizedField,
|
|
2249
|
+
normalizeAssetTypeSectionBuilderValue: normalizeAssetTypeSectionBuilderValue
|
|
2250
|
+
}, [contracts]);
|
|
2251
|
+
|
|
2252
|
+
//#region ---- Imports ----
|
|
2253
|
+
//#endregion
|
|
2254
|
+
//#region ---- Constants ----
|
|
2255
|
+
const BLOCKING_WORK_ORDER_STATUSES = new Set(['in-progress', 'completed']);
|
|
2256
|
+
const PROTECTED_LIFECYCLE_STATUSES = new Set([AXMAssetLifecycleStatus.Retired, AXMAssetLifecycleStatus.Disposed]);
|
|
2257
|
+
const PROTECTED_OPERATIONAL_STATUSES = new Set([AXMAssetStatus.Lost]);
|
|
2258
|
+
//#endregion
|
|
2259
|
+
/**
|
|
2260
|
+
* Central policy for asset operational status changes driven by maintenance work orders.
|
|
2261
|
+
* Callers must not set `Asset.statusId` directly from workflows — use {@link recalculate} only.
|
|
2262
|
+
*/
|
|
2263
|
+
class AXMAssetOperationalStatusService {
|
|
2264
|
+
constructor() {
|
|
2265
|
+
//#region ---- Services & Dependencies ----
|
|
2266
|
+
this.entityService = inject(AXPEntityService);
|
|
2267
|
+
}
|
|
2268
|
+
//#endregion
|
|
2269
|
+
//#region ---- Public API ----
|
|
2270
|
+
async recalculate(assetIdRaw, trigger, context = {}) {
|
|
2271
|
+
const assetId = assetIdRaw?.trim();
|
|
2272
|
+
if (!assetId) {
|
|
2273
|
+
return {
|
|
2274
|
+
assetId: '',
|
|
2275
|
+
previousStatusId: null,
|
|
2276
|
+
statusId: null,
|
|
2277
|
+
changed: false,
|
|
2278
|
+
reason: 'assetId is required',
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
const asset = (await this.entityService.withEntity('AssetManagement', 'Asset').data().byKey(assetId));
|
|
2282
|
+
if (!asset?.id) {
|
|
2283
|
+
return {
|
|
2284
|
+
assetId,
|
|
2285
|
+
previousStatusId: null,
|
|
2286
|
+
statusId: null,
|
|
2287
|
+
changed: false,
|
|
2288
|
+
reason: 'Asset not found',
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
const previousStatusId = isString(asset.statusId) ? asset.statusId.trim() : null;
|
|
2292
|
+
const lifecycleStatusId = isString(asset.lifecycleStatusId) ? asset.lifecycleStatusId.trim() : null;
|
|
2293
|
+
if (lifecycleStatusId && PROTECTED_LIFECYCLE_STATUSES.has(lifecycleStatusId)) {
|
|
2294
|
+
return {
|
|
2295
|
+
assetId,
|
|
2296
|
+
previousStatusId,
|
|
2297
|
+
statusId: previousStatusId,
|
|
2298
|
+
changed: false,
|
|
2299
|
+
reason: `${trigger}: asset lifecycle is protected`,
|
|
2300
|
+
};
|
|
2301
|
+
}
|
|
2302
|
+
if (previousStatusId && PROTECTED_OPERATIONAL_STATUSES.has(previousStatusId)) {
|
|
2303
|
+
return {
|
|
2304
|
+
assetId,
|
|
2305
|
+
previousStatusId,
|
|
2306
|
+
statusId: previousStatusId,
|
|
2307
|
+
changed: false,
|
|
2308
|
+
reason: `${trigger}: asset status is protected`,
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
const maintenanceTypeId = await this.resolveMaintenanceTypeId(assetId, context);
|
|
2312
|
+
const shouldBlock = await this.shouldBlockAssetForMaintenance(assetId, maintenanceTypeId);
|
|
2313
|
+
let nextStatusId = previousStatusId;
|
|
2314
|
+
const update = {};
|
|
2315
|
+
if (trigger === 'work-started') {
|
|
2316
|
+
if (shouldBlock) {
|
|
2317
|
+
nextStatusId = AXMAssetStatus.UnderMaintenanceInspection;
|
|
2318
|
+
if (previousStatusId === AXMAssetStatus.Available || previousStatusId === AXMAssetStatus.Assigned) {
|
|
2319
|
+
update.statusBeforeInterruptionId = previousStatusId;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
if (trigger === 'work-completed') {
|
|
2324
|
+
const hasBlockingWork = await this.hasBlockingWorkOrders(assetId);
|
|
2325
|
+
if (hasBlockingWork) {
|
|
2326
|
+
nextStatusId = AXMAssetStatus.UnderMaintenanceInspection;
|
|
2327
|
+
}
|
|
2328
|
+
// Do not release the asset here — completed work still awaits sign-off.
|
|
2329
|
+
}
|
|
2330
|
+
if (trigger === 'work-signed-off') {
|
|
2331
|
+
const hasBlockingWork = await this.hasBlockingWorkOrders(assetId);
|
|
2332
|
+
if (hasBlockingWork) {
|
|
2333
|
+
nextStatusId = AXMAssetStatus.UnderMaintenanceInspection;
|
|
2334
|
+
}
|
|
2335
|
+
else {
|
|
2336
|
+
nextStatusId = this.resolveRestoredStatus(asset);
|
|
2337
|
+
update.statusBeforeInterruptionId = null;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
const changed = !!nextStatusId && nextStatusId !== previousStatusId;
|
|
2341
|
+
const hasFieldUpdates = update.statusBeforeInterruptionId !== undefined;
|
|
2342
|
+
if ((changed && nextStatusId) || hasFieldUpdates) {
|
|
2343
|
+
await this.entityService
|
|
2344
|
+
.withEntity('AssetManagement', 'Asset')
|
|
2345
|
+
.data()
|
|
2346
|
+
.update(assetId, {
|
|
2347
|
+
...update,
|
|
2348
|
+
...(changed && nextStatusId ? { statusId: nextStatusId } : {}),
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
return {
|
|
2352
|
+
assetId,
|
|
2353
|
+
previousStatusId,
|
|
2354
|
+
statusId: nextStatusId,
|
|
2355
|
+
changed,
|
|
2356
|
+
reason: changed ? `${trigger}: status recalculated` : `${trigger}: status unchanged`,
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2359
|
+
//#endregion
|
|
2360
|
+
//#region ---- Policy helpers ----
|
|
2361
|
+
async resolveMaintenanceTypeId(assetId, context) {
|
|
2362
|
+
const fromContext = context.maintenanceTypeId?.trim();
|
|
2363
|
+
if (fromContext) {
|
|
2364
|
+
return fromContext;
|
|
2365
|
+
}
|
|
2366
|
+
const workOrderId = context.workOrderId?.trim();
|
|
2367
|
+
if (workOrderId) {
|
|
2368
|
+
const workOrder = (await this.entityService
|
|
2369
|
+
.withEntity('MaintenanceManagement', 'WorkOrder')
|
|
2370
|
+
.data()
|
|
2371
|
+
.byKey(workOrderId));
|
|
2372
|
+
const fromWorkOrder = workOrder?.maintenanceTypeId?.trim();
|
|
2373
|
+
if (fromWorkOrder) {
|
|
2374
|
+
return fromWorkOrder;
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
const page = await this.entityService
|
|
2378
|
+
.withEntity('MaintenanceManagement', 'WorkOrder')
|
|
2379
|
+
.data()
|
|
2380
|
+
.query({
|
|
2381
|
+
skip: 0,
|
|
2382
|
+
take: 1,
|
|
2383
|
+
filter: {
|
|
2384
|
+
logic: 'and',
|
|
2385
|
+
filters: [
|
|
2386
|
+
{ field: 'assetId', operator: { type: 'equal' }, value: assetId },
|
|
2387
|
+
{ field: 'statusId', operator: { type: 'equal' }, value: 'in-progress' },
|
|
2388
|
+
],
|
|
2389
|
+
},
|
|
2390
|
+
});
|
|
2391
|
+
const row = defaultTo(get(page, 'items[0]'), null);
|
|
2392
|
+
return row?.maintenanceTypeId?.trim() ?? '';
|
|
2393
|
+
}
|
|
2394
|
+
/**
|
|
2395
|
+
* Inspection-like maintenance types keep the asset blocked under the combined operational status.
|
|
2396
|
+
* TODO: replace title/code heuristic with an explicit MaintenanceType classification field when available.
|
|
2397
|
+
*/
|
|
2398
|
+
async shouldBlockAssetForMaintenance(_assetId, maintenanceTypeId) {
|
|
2399
|
+
if (!maintenanceTypeId) {
|
|
2400
|
+
return true;
|
|
2401
|
+
}
|
|
2402
|
+
const maintenanceType = (await this.entityService
|
|
2403
|
+
.withEntity('MaintenanceManagement', 'MaintenanceType')
|
|
2404
|
+
.data()
|
|
2405
|
+
.byKey(maintenanceTypeId));
|
|
2406
|
+
if (!maintenanceType) {
|
|
2407
|
+
return true;
|
|
2408
|
+
}
|
|
2409
|
+
const code = maintenanceType.code?.toLowerCase() ?? '';
|
|
2410
|
+
const titleText = this.resolveDisplayText(maintenanceType.title).toLowerCase();
|
|
2411
|
+
const isInspection = code.includes('inspect') || titleText.includes('inspect');
|
|
2412
|
+
if (isInspection) {
|
|
2413
|
+
return true;
|
|
2414
|
+
}
|
|
2415
|
+
// Non-inspection maintenance that does not block the asset is not modeled yet.
|
|
2416
|
+
// TODO: honor MaintenanceType.blocksAsset (or equivalent) when introduced.
|
|
2417
|
+
return true;
|
|
2418
|
+
}
|
|
2419
|
+
async hasBlockingWorkOrders(assetId) {
|
|
2420
|
+
const page = await this.entityService
|
|
2421
|
+
.withEntity('MaintenanceManagement', 'WorkOrder')
|
|
2422
|
+
.data()
|
|
2423
|
+
.query({
|
|
2424
|
+
skip: 0,
|
|
2425
|
+
take: 100,
|
|
2426
|
+
filter: {
|
|
2427
|
+
logic: 'and',
|
|
2428
|
+
filters: [{ field: 'assetId', operator: { type: 'equal' }, value: assetId }],
|
|
2429
|
+
},
|
|
2430
|
+
});
|
|
2431
|
+
const items = defaultTo(get(page, 'items'), []);
|
|
2432
|
+
return items.some((row) => {
|
|
2433
|
+
const statusId = row.statusId?.trim();
|
|
2434
|
+
return !!statusId && BLOCKING_WORK_ORDER_STATUSES.has(statusId);
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
resolveRestoredStatus(asset) {
|
|
2438
|
+
const saved = isString(asset.statusBeforeInterruptionId) ? asset.statusBeforeInterruptionId.trim() : null;
|
|
2439
|
+
if (saved) {
|
|
2440
|
+
return saved;
|
|
2441
|
+
}
|
|
2442
|
+
return AXMAssetStatus.Available;
|
|
2443
|
+
}
|
|
2444
|
+
resolveDisplayText(value) {
|
|
2445
|
+
if (isString(value)) {
|
|
2446
|
+
return value;
|
|
2447
|
+
}
|
|
2448
|
+
if (value && typeof value === 'object') {
|
|
2449
|
+
const record = value;
|
|
2450
|
+
return record['en-US'] ?? record['fa-IR'] ?? Object.values(record)[0] ?? '';
|
|
2451
|
+
}
|
|
2452
|
+
return '';
|
|
2453
|
+
}
|
|
2454
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetOperationalStatusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2455
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetOperationalStatusService, providedIn: 'root' }); }
|
|
2456
|
+
}
|
|
2457
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMAssetOperationalStatusService, decorators: [{
|
|
2458
|
+
type: Injectable,
|
|
2459
|
+
args: [{ providedIn: 'root' }]
|
|
2460
|
+
}] });
|
|
2461
|
+
|
|
2462
|
+
//#region ---- Types ----
|
|
2463
|
+
//#endregion
|
|
2464
|
+
|
|
2465
|
+
// export * from './asset-status.provider';
|
|
2466
|
+
|
|
2467
|
+
/**
|
|
2468
|
+
* Generated bundle index. Do not edit.
|
|
2469
|
+
*/
|
|
2470
|
+
|
|
2471
|
+
export { ASSET_TYPE_COMPONENTS_SAVE_COMMAND, AXMAssetManagementAssetStatusProvider, AXMAssetManagementFeatureDefinitionProvider, AXMAssetManagementMenuProvider, AXMAssetManagementModule, AXMAssetManagementPermissionDefinitionProvider, AXMAssetManagementSearchCommandProvider, AXMAssetOperationalStatusService, AXMAssetTypeComponentsPageComponentProvider, AXMAssetTypeSectionBuilderComponent, AXMAssetTypeSectionBuilderPageComponent, AXMCreateAssetRentalHistoryRentFromCommand, AXMCreateAssetRentalHistoryRentToCommand, AXMSaveAssetTypeComponentsCommand, assertRentalPartyForDirection, createAssetTypeSectionBuilderDefaultValue, normalizeAssetTypeBuilderLocalizedField, normalizeAssetTypeSectionBuilderValue };
|
|
2472
|
+
//# sourceMappingURL=acorex-platform-module-asset-management-client.mjs.map
|