@acorex/modules 20.7.12 → 20.7.13
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/data-management/index.d.ts +250 -4
- package/document-management/index.d.ts +4 -2
- package/fesm2022/acorex-modules-data-management.mjs +1 -1
- package/fesm2022/acorex-modules-data-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +338 -90
- package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AXPSessionService, AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
|
|
2
|
-
import { AXPEntityService, AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions, cloneLayoutArrays, ensureLayoutSection, ensureLayoutPropertyView, ensureListActions, actionExists, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
2
|
+
import { AXPEntityService, AXMEntityCrudServiceImpl, entityMasterCrudActions, entityMasterRecordActions, cloneLayoutArrays, ensureLayoutSection, ensureLayoutPropertyView, ensureListActions, actionExists, AXPEntityDefinitionRegistryService, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_STORAGE_MIDDLEWARE, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
3
3
|
import { AXPHookService, AXPPlatformScope, AXPDataGenerator, AXP_MODULE_MANIFEST_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPDeviceService, resolvePlatformScopeKey, resolvePlatformScopeName } from '@acorex/platform/core';
|
|
4
4
|
import { AXPSearchCommandProvider, createAllQueryView, createQueryView, AXPEntityCommandScope, AXPEntityQueryType, AXPFileTypeProviderService, AXP_FILE_TYPE_INFO_PROVIDER, AXPFileStorageService, AXPFilterOperatorMiddlewareService, AXPSettingsService, AXPLockService, UploadFromComputerActionProvider, AXP_FILE_ACTION_PROVIDER, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex/platform/common';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
@@ -1370,7 +1370,7 @@ async function documentTypeFactory(injector) {
|
|
|
1370
1370
|
actions: [...entityMasterRecordActions()],
|
|
1371
1371
|
},
|
|
1372
1372
|
list: {
|
|
1373
|
-
actions: [...entityMasterCrudActions()],
|
|
1373
|
+
actions: [...entityMasterCrudActions({ edit: true })],
|
|
1374
1374
|
views: [createAllQueryView()],
|
|
1375
1375
|
},
|
|
1376
1376
|
},
|
|
@@ -4120,7 +4120,7 @@ class AXMDocumentDialogService {
|
|
|
4120
4120
|
if (showMeta) {
|
|
4121
4121
|
flex.formField('@document-management:terms.common.meta-data', field => {
|
|
4122
4122
|
field.path(`file-${index}.metaDataForm`);
|
|
4123
|
-
field.customWidget('meta-data-form-editor', documentType?.metaDataList);
|
|
4123
|
+
field.customWidget('meta-data-form-editor', documentType?.metaDataList ?? { groups: [] });
|
|
4124
4124
|
});
|
|
4125
4125
|
}
|
|
4126
4126
|
flex.formField('@document-management:terms.common.file', field => {
|
|
@@ -4203,10 +4203,16 @@ class AXMDocumentDialogService {
|
|
|
4203
4203
|
.map((f) => `.${f.name.split('.')[1]}`)
|
|
4204
4204
|
.join(',');
|
|
4205
4205
|
const fileList = Array.isArray(files) ? files : [];
|
|
4206
|
-
|
|
4206
|
+
/** Get metaDataForm from a file item (widget may store under meta or metaDataForm). */
|
|
4207
|
+
const getFileMeta = (item) => item?.metaDataForm ?? (item?.meta && typeof item.meta === 'object' && !Array.isArray(item.meta) ? item.meta : undefined);
|
|
4208
|
+
// Build initial context for all files: each file-${index} gets that file's metaDataForm so form shows existing meta
|
|
4207
4209
|
const initialContext = {};
|
|
4208
4210
|
if (showMeta) {
|
|
4209
|
-
|
|
4211
|
+
fileList.forEach((item, index) => {
|
|
4212
|
+
initialContext[`file-${index}`] = { metaDataForm: getFileMeta(item) ?? metaData };
|
|
4213
|
+
});
|
|
4214
|
+
if (fileList.length === 0)
|
|
4215
|
+
initialContext['file-0'] = { metaDataForm: metaData };
|
|
4210
4216
|
}
|
|
4211
4217
|
// Initialize files array context with default values
|
|
4212
4218
|
initialContext['files'] = fileList.map(item => ({ file: [item] }));
|
|
@@ -4225,7 +4231,7 @@ class AXMDocumentDialogService {
|
|
|
4225
4231
|
if (showMeta) {
|
|
4226
4232
|
flex.formField('@document-management:terms.common.meta-data', field => {
|
|
4227
4233
|
field.path(`file-${index}.metaDataForm`);
|
|
4228
|
-
field.customWidget('meta-data-form-editor', documentType?.metaDataList);
|
|
4234
|
+
field.customWidget('meta-data-form-editor', documentType?.metaDataList ?? { groups: [] });
|
|
4229
4235
|
});
|
|
4230
4236
|
}
|
|
4231
4237
|
flex.formField('File', field => {
|
|
@@ -4252,15 +4258,17 @@ class AXMDocumentDialogService {
|
|
|
4252
4258
|
};
|
|
4253
4259
|
}
|
|
4254
4260
|
const ctx = dialogRef.context();
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4261
|
+
const outFiles = (ctx?.['files']).map((item, index) => ({
|
|
4262
|
+
...item,
|
|
4263
|
+
...(showMeta ? { metaDataForm: ctx?.[`file-${index}`]?.['metaDataForm'] } : {}),
|
|
4264
|
+
}));
|
|
4265
|
+
if (showMeta && outFiles.length) {
|
|
4266
|
+
console.debug('[document-dialog] openAttachmentDialogWithoutSave result', {
|
|
4267
|
+
filesCount: outFiles.length,
|
|
4268
|
+
firstFileMetaDataForm: outFiles[0]?.metaDataForm,
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4271
|
+
return { data: { cancel: false, files: outFiles } };
|
|
4264
4272
|
});
|
|
4265
4273
|
})
|
|
4266
4274
|
.show();
|
|
@@ -7144,55 +7152,321 @@ const attachmentsPlugin = {
|
|
|
7144
7152
|
},
|
|
7145
7153
|
};
|
|
7146
7154
|
|
|
7147
|
-
|
|
7155
|
+
/** Extract metadata for server (metaDataForm) from widget item (meta or metaDataForm). */
|
|
7156
|
+
function getMetaDataFormForServer(item) {
|
|
7157
|
+
if (item?.meta?.metaDataForm != null)
|
|
7158
|
+
return item.meta.metaDataForm;
|
|
7159
|
+
if (item?.metaDataForm != null)
|
|
7160
|
+
return item.metaDataForm;
|
|
7161
|
+
if (item?.meta != null && typeof item.meta === 'object' && !Array.isArray(item.meta))
|
|
7162
|
+
return item.meta;
|
|
7163
|
+
return undefined;
|
|
7164
|
+
}
|
|
7165
|
+
/** Resolve list of attachment field names from entity extensions.attachments. */
|
|
7166
|
+
function getAttachmentFields(attachCfg) {
|
|
7167
|
+
if (!attachCfg || typeof attachCfg !== 'object')
|
|
7168
|
+
return [];
|
|
7169
|
+
if (typeof attachCfg.field === 'string')
|
|
7170
|
+
return [attachCfg.field];
|
|
7171
|
+
return Object.keys(attachCfg).filter((k) => k && typeof k === 'string');
|
|
7172
|
+
}
|
|
7173
|
+
/** Fallback: get attachment field names from properties with file-uploader interface (when extensions.attachments is missing e.g. cached def). */
|
|
7174
|
+
function getAttachmentFieldsFromProperties(def) {
|
|
7175
|
+
const props = def?.properties;
|
|
7176
|
+
if (!Array.isArray(props))
|
|
7177
|
+
return [];
|
|
7178
|
+
return props
|
|
7179
|
+
.filter((p) => p?.schema?.interface?.type === 'file-uploader' && p?.name)
|
|
7180
|
+
.map((p) => p.name);
|
|
7181
|
+
}
|
|
7182
|
+
/**
|
|
7183
|
+
* Handles file list fields configured via entity.extensions.attachments.
|
|
7184
|
+
* Preserves metaDataForm from widget; uploads pending blobs after persistence and writes final references.
|
|
7185
|
+
* Runs before file-cast (order 25) so blobs are uploaded before file-cast sees the data.
|
|
7186
|
+
*/
|
|
7187
|
+
// Run before file-cast (order 25) so blobs are uploaded and refs written before file-cast sees the data
|
|
7188
|
+
const attachmentsUploadMiddleware = {
|
|
7189
|
+
target: { ops: ['create', 'update'], order: 22 },
|
|
7190
|
+
execute: async (ctx, next) => {
|
|
7191
|
+
const registry = inject(AXPEntityDefinitionRegistryService);
|
|
7192
|
+
const storage = inject(AXPFileStorageService);
|
|
7193
|
+
const [moduleName, entityNameOnly] = ctx.entityName.split('.');
|
|
7194
|
+
const def = await registry.resolve(moduleName, entityNameOnly).catch(() => null);
|
|
7195
|
+
const attachCfg = def?.extensions?.attachments;
|
|
7196
|
+
let fields = getAttachmentFields(attachCfg);
|
|
7197
|
+
if (!fields.length && def)
|
|
7198
|
+
fields = getAttachmentFieldsFromProperties(def);
|
|
7199
|
+
if (!fields.length) {
|
|
7200
|
+
await next();
|
|
7201
|
+
return;
|
|
7202
|
+
}
|
|
7203
|
+
const pendingByField = ctx.locals.attach_pending ?? {};
|
|
7204
|
+
ctx.locals.attach_pending = pendingByField;
|
|
7205
|
+
if (ctx.data && typeof ctx.data === 'object') {
|
|
7206
|
+
for (const field of fields) {
|
|
7207
|
+
const list = Array.isArray(ctx.data[field]) ? ctx.data[field] : [];
|
|
7208
|
+
pendingByField[field] = [];
|
|
7209
|
+
const normalized = [];
|
|
7210
|
+
for (const item of list) {
|
|
7211
|
+
const metaDataForm = getMetaDataFormForServer(item);
|
|
7212
|
+
if (item?.source?.kind === 'blob' && item.source.value instanceof Blob) {
|
|
7213
|
+
const blob = item.source.value;
|
|
7214
|
+
const name = item.name || `file-${Date.now()}`;
|
|
7215
|
+
pendingByField[field].push({ fileItem: { ...item, name, metaDataForm }, blob });
|
|
7216
|
+
const entry = {
|
|
7217
|
+
tempId: item.id,
|
|
7218
|
+
name,
|
|
7219
|
+
size: item.size ?? blob.size,
|
|
7220
|
+
status: 'pending_upload',
|
|
7221
|
+
};
|
|
7222
|
+
if (metaDataForm)
|
|
7223
|
+
entry.metaDataForm = metaDataForm;
|
|
7224
|
+
normalized.push(entry);
|
|
7225
|
+
}
|
|
7226
|
+
else if (item?.source?.kind === 'fileId' && item.id && typeof item.source.value === 'string') {
|
|
7227
|
+
const entry = {
|
|
7228
|
+
id: item.id,
|
|
7229
|
+
name: item.name,
|
|
7230
|
+
size: item.size,
|
|
7231
|
+
status: item.status || 'uploaded',
|
|
7232
|
+
source: { kind: 'fileId', value: item.source.value },
|
|
7233
|
+
};
|
|
7234
|
+
if (metaDataForm)
|
|
7235
|
+
entry.metaDataForm = metaDataForm;
|
|
7236
|
+
normalized.push(entry);
|
|
7237
|
+
}
|
|
7238
|
+
else if (item?.id && item?.name) {
|
|
7239
|
+
const entry = {
|
|
7240
|
+
id: item.id,
|
|
7241
|
+
name: item.name,
|
|
7242
|
+
size: item.size,
|
|
7243
|
+
status: item.status || 'uploaded',
|
|
7244
|
+
source: item.source ? { kind: item.source.kind, value: item.source.value } : undefined,
|
|
7245
|
+
};
|
|
7246
|
+
if (metaDataForm)
|
|
7247
|
+
entry.metaDataForm = metaDataForm;
|
|
7248
|
+
normalized.push(entry);
|
|
7249
|
+
}
|
|
7250
|
+
}
|
|
7251
|
+
const dataForBackend = normalized.filter((x) => x.status !== 'pending_upload');
|
|
7252
|
+
ctx.data[field] = dataForBackend;
|
|
7253
|
+
}
|
|
7254
|
+
}
|
|
7255
|
+
await next();
|
|
7256
|
+
const refId = ctx.op === 'create' ? String(ctx.result) : String(ctx.id);
|
|
7257
|
+
const refType = ctx.entityName;
|
|
7258
|
+
for (const field of fields) {
|
|
7259
|
+
const pending = pendingByField[field] ?? [];
|
|
7260
|
+
if (!pending.length)
|
|
7261
|
+
continue;
|
|
7262
|
+
if (!storage)
|
|
7263
|
+
continue;
|
|
7264
|
+
const finalRefs = (ctx.data[field] ?? []).filter((x) => x.status !== 'pending_upload');
|
|
7265
|
+
for (const { fileItem, blob } of pending) {
|
|
7266
|
+
const metaDataForm = fileItem.metaDataForm ?? getMetaDataFormForServer(fileItem);
|
|
7267
|
+
try {
|
|
7268
|
+
const info = await storage.save({
|
|
7269
|
+
file: blob,
|
|
7270
|
+
refId,
|
|
7271
|
+
refType,
|
|
7272
|
+
category: '',
|
|
7273
|
+
name: fileItem.name,
|
|
7274
|
+
});
|
|
7275
|
+
await storage.commit(info.fileId);
|
|
7276
|
+
const entry = {
|
|
7277
|
+
id: info.fileId,
|
|
7278
|
+
name: info.name || fileItem.name,
|
|
7279
|
+
size: info.size || blob.size,
|
|
7280
|
+
type: info.mimeType || blob.type,
|
|
7281
|
+
status: 'uploaded',
|
|
7282
|
+
source: { kind: 'fileId', value: info.fileId },
|
|
7283
|
+
};
|
|
7284
|
+
if (metaDataForm)
|
|
7285
|
+
entry.metaDataForm = metaDataForm;
|
|
7286
|
+
finalRefs.push(entry);
|
|
7287
|
+
}
|
|
7288
|
+
catch (err) {
|
|
7289
|
+
finalRefs.push({
|
|
7290
|
+
tempId: fileItem.id,
|
|
7291
|
+
name: fileItem.name,
|
|
7292
|
+
size: fileItem.size,
|
|
7293
|
+
type: blob.type,
|
|
7294
|
+
status: 'upload_failed',
|
|
7295
|
+
error: err?.message,
|
|
7296
|
+
});
|
|
7297
|
+
}
|
|
7298
|
+
}
|
|
7299
|
+
const entityId = ctx.op === 'create' ? ctx.result : ctx.id;
|
|
7300
|
+
if (entityId != null) {
|
|
7301
|
+
const payload = { [field]: finalRefs };
|
|
7302
|
+
const withMeta = finalRefs.filter((r) => r?.metaDataForm != null).length;
|
|
7303
|
+
console.log('[attachments-upload] ذخیره — الان میخوام ctx.backend.updateOne بزنم (پچ با metaDataForm)', {
|
|
7304
|
+
entityName: ctx.entityName,
|
|
7305
|
+
entityId,
|
|
7306
|
+
field,
|
|
7307
|
+
finalRefsLength: finalRefs.length,
|
|
7308
|
+
withMetaCount: withMeta,
|
|
7309
|
+
payloadSample: payload[field]?.map((r, i) => ({ i, hasMeta: !!r?.metaDataForm })),
|
|
7310
|
+
});
|
|
7311
|
+
try {
|
|
7312
|
+
await ctx.backend.updateOne(ctx.entityName, entityId, payload);
|
|
7313
|
+
console.log('[attachments-upload] ذخیره — ctx.backend.updateOne انجام شد (ok)');
|
|
7314
|
+
}
|
|
7315
|
+
catch (err) {
|
|
7316
|
+
console.warn('[attachments-upload] ذخیره — ctx.backend.updateOne خطا', err);
|
|
7317
|
+
// Result already persisted; optional patch for final refs failed
|
|
7318
|
+
}
|
|
7319
|
+
}
|
|
7320
|
+
if (typeof ctx.result === 'object' && ctx.result !== null) {
|
|
7321
|
+
ctx.result = { ...ctx.result, [field]: finalRefs };
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
},
|
|
7325
|
+
};
|
|
7326
|
+
|
|
7327
|
+
//#region ---- Plugin Guard Utilities ----
|
|
7328
|
+
/**
|
|
7329
|
+
* Check if the 'document' plugin is active (enabled and not excluded) in the payload.
|
|
7330
|
+
*/
|
|
7331
|
+
function isDocumentPluginActive(payload) {
|
|
7332
|
+
const isEnabled = Array.isArray(payload.plugins) && payload.plugins.some((p) => p.name === 'document');
|
|
7333
|
+
const isExcluded = Array.isArray(payload.excludePlugins) && payload.excludePlugins.includes('document');
|
|
7334
|
+
return isEnabled && !isExcluded;
|
|
7335
|
+
}
|
|
7336
|
+
/**
|
|
7337
|
+
* Extract document plugin options from payload.
|
|
7338
|
+
* Returns undefined if plugin is not active or options are missing.
|
|
7339
|
+
*/
|
|
7340
|
+
function getDocumentPluginOptions(payload) {
|
|
7341
|
+
if (!isDocumentPluginActive(payload)) {
|
|
7342
|
+
return undefined;
|
|
7343
|
+
}
|
|
7344
|
+
return (payload.plugins.find((p) => p.name === 'document')?.options ?? {});
|
|
7345
|
+
}
|
|
7346
|
+
/** Resolve list of document type names from plugin options (single or multiple). */
|
|
7347
|
+
function getDocTypeNames(opts) {
|
|
7348
|
+
if (!opts)
|
|
7349
|
+
return [];
|
|
7350
|
+
if (Array.isArray(opts.docTypeNames) && opts.docTypeNames.length > 0)
|
|
7351
|
+
return opts.docTypeNames;
|
|
7352
|
+
if (typeof opts.docTypeName === 'string' && opts.docTypeName.trim())
|
|
7353
|
+
return [opts.docTypeName.trim()];
|
|
7354
|
+
return [];
|
|
7355
|
+
}
|
|
7356
|
+
//#endregion
|
|
7357
|
+
// ---------------- Configure: set accept based on docTypeId / docTypeNames ----------------
|
|
7148
7358
|
const DocumentFileUploaderConfigureProvider = {
|
|
7149
7359
|
key: 'file-uploader.configure',
|
|
7150
7360
|
priority: 0,
|
|
7151
7361
|
async execute(payload) {
|
|
7152
|
-
const
|
|
7153
|
-
const
|
|
7154
|
-
if (!
|
|
7155
|
-
return payload;
|
|
7156
|
-
const opts = (payload.plugins.find((p) => p.name === 'document')?.options ?? {});
|
|
7157
|
-
if (!opts.docTypeName)
|
|
7362
|
+
const opts = getDocumentPluginOptions(payload);
|
|
7363
|
+
const names = getDocTypeNames(opts);
|
|
7364
|
+
if (!names.length)
|
|
7158
7365
|
return payload;
|
|
7159
7366
|
const documentManagementService = inject(AXPDocumentManagementService);
|
|
7160
|
-
const
|
|
7161
|
-
const
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7367
|
+
const allExtensions = [];
|
|
7368
|
+
for (const name of names) {
|
|
7369
|
+
const docType = await documentManagementService.getDocumentTypeByName(name);
|
|
7370
|
+
const selected = docType?.type?.selectedItems ?? [];
|
|
7371
|
+
const extList = selected
|
|
7372
|
+
.map((s) => s?.name)
|
|
7373
|
+
.filter((n) => typeof n === 'string' && n.includes('.'))
|
|
7374
|
+
.map((n) => `.${n.split('.').pop()?.toLowerCase()}`);
|
|
7375
|
+
allExtensions.push(...extList);
|
|
7376
|
+
}
|
|
7377
|
+
const extensions = Array.from(new Set(allExtensions));
|
|
7166
7378
|
payload.overrides = payload.overrides || {};
|
|
7167
7379
|
payload.overrides['accept'] = extensions.join(',');
|
|
7168
7380
|
return payload;
|
|
7169
7381
|
},
|
|
7170
7382
|
};
|
|
7383
|
+
// ---------------- Actions: one "Upload" button per document type (replaces generic Upload from Device) ----------------
|
|
7384
|
+
const DocumentFileUploaderActionsByTypeProvider = {
|
|
7385
|
+
key: 'file-uploader.actions',
|
|
7386
|
+
priority: 5,
|
|
7387
|
+
execute: async (payload) => {
|
|
7388
|
+
const opts = getDocumentPluginOptions({
|
|
7389
|
+
plugins: payload.plugins,
|
|
7390
|
+
excludePlugins: payload.excludePlugins ?? [],
|
|
7391
|
+
capabilities: payload.capabilities,
|
|
7392
|
+
});
|
|
7393
|
+
const docTypeNames = getDocTypeNames(opts);
|
|
7394
|
+
if (docTypeNames.length === 0)
|
|
7395
|
+
return payload;
|
|
7396
|
+
const documentManagementService = inject(AXPDocumentManagementService);
|
|
7397
|
+
const documentDialogService = inject(AXMDocumentDialogService);
|
|
7398
|
+
const fileService = inject(AXFileService);
|
|
7399
|
+
const docTypes = await Promise.all(docTypeNames.map((name) => documentManagementService.getDocumentTypeByName(name)));
|
|
7400
|
+
const byTypeActions = docTypes
|
|
7401
|
+
.filter((dt) => dt != null)
|
|
7402
|
+
.map((docType) => {
|
|
7403
|
+
const selected = docType?.type?.selectedItems ?? [];
|
|
7404
|
+
const accept = Array.from(new Set(selected
|
|
7405
|
+
.map((s) => s?.name)
|
|
7406
|
+
.filter((n) => typeof n === 'string' && n.includes('.'))
|
|
7407
|
+
.map((n) => `.${n.split('.').pop()?.toLowerCase()}`))).join(',');
|
|
7408
|
+
const typeName = docType?.name;
|
|
7409
|
+
const title = docType?.title ?? typeName;
|
|
7410
|
+
const hasMeta = Array.isArray(docType?.metaDataList?.groups) &&
|
|
7411
|
+
docType.metaDataList.groups.length > 0;
|
|
7412
|
+
return {
|
|
7413
|
+
plugin: 'document',
|
|
7414
|
+
global: false,
|
|
7415
|
+
text: title,
|
|
7416
|
+
icon: 'fa-light fa-file-arrow-up',
|
|
7417
|
+
run: async (capabilities) => {
|
|
7418
|
+
const files = await fileService.choose({
|
|
7419
|
+
multiple: payload.options?.multiple ?? true,
|
|
7420
|
+
accept: accept || undefined,
|
|
7421
|
+
});
|
|
7422
|
+
if (files.length === 0)
|
|
7423
|
+
return;
|
|
7424
|
+
const fileItems = files.map((file) => ({
|
|
7425
|
+
id: AXPDataGenerator.uuid(),
|
|
7426
|
+
name: file.name,
|
|
7427
|
+
size: file.size,
|
|
7428
|
+
type: file.type,
|
|
7429
|
+
status: 'attached',
|
|
7430
|
+
source: { kind: 'blob', value: file },
|
|
7431
|
+
__documentTypeName: typeName,
|
|
7432
|
+
}));
|
|
7433
|
+
if (hasMeta) {
|
|
7434
|
+
const result = await documentDialogService.openAttachmentDialogWithoutSave('Document Type Choose File', {
|
|
7435
|
+
documentType: docType,
|
|
7436
|
+
files: fileItems,
|
|
7437
|
+
});
|
|
7438
|
+
if (result.data?.cancel != null && !result.data.cancel && result.data?.files) {
|
|
7439
|
+
result.data.files.forEach((f, i) => {
|
|
7440
|
+
if (fileItems[i])
|
|
7441
|
+
set(fileItems[i], 'metaDataForm', f?.metaDataForm);
|
|
7442
|
+
});
|
|
7443
|
+
}
|
|
7444
|
+
else if (result.data?.cancel) {
|
|
7445
|
+
return;
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
capabilities.addFiles(fileItems);
|
|
7449
|
+
},
|
|
7450
|
+
};
|
|
7451
|
+
});
|
|
7452
|
+
payload.actions = payload.actions.filter((a) => a.plugin !== 'upload-from-computer');
|
|
7453
|
+
payload.actions = [...byTypeActions, ...payload.actions];
|
|
7454
|
+
return payload;
|
|
7455
|
+
},
|
|
7456
|
+
};
|
|
7171
7457
|
// --------------- After Files Added: scaffold for post-add processing ---------------
|
|
7172
7458
|
const DocumentFileUploaderBeforeFilesAddedProvider = {
|
|
7173
7459
|
key: 'file-uploader.beforeFilesAdded',
|
|
7174
7460
|
priority: 0,
|
|
7175
7461
|
async execute(payload) {
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
excludePlugins: payload.excludePlugins,
|
|
7181
|
-
newFiles: payload.newFiles,
|
|
7182
|
-
});
|
|
7183
|
-
const isEnabled = Array.isArray(payload.plugins) && payload.plugins.some((p) => p.name === 'document');
|
|
7184
|
-
const isExcluded = Array.isArray(payload.excludePlugins) && payload.excludePlugins.includes('document');
|
|
7185
|
-
if (!isEnabled || isExcluded)
|
|
7186
|
-
return payload;
|
|
7187
|
-
const opts = (payload.plugins.find((p) => p.name === 'document')?.options ?? {});
|
|
7188
|
-
// Debug: trace resolved options
|
|
7189
|
-
// eslint-disable-next-line no-console
|
|
7190
|
-
console.log('[DocumentFileUploaderBeforeFilesAdded] options', opts);
|
|
7191
|
-
if (!opts.docTypeName)
|
|
7462
|
+
const opts = getDocumentPluginOptions(payload);
|
|
7463
|
+
const docTypeName = payload.newFiles[0]?.__documentTypeName ??
|
|
7464
|
+
opts?.docTypeName;
|
|
7465
|
+
if (!docTypeName)
|
|
7192
7466
|
return payload;
|
|
7193
7467
|
const injector = inject(Injector);
|
|
7194
7468
|
const documentManagementService = injector.get(AXPDocumentManagementService);
|
|
7195
|
-
const docType = await documentManagementService.getDocumentTypeByName(
|
|
7469
|
+
const docType = await documentManagementService.getDocumentTypeByName(docTypeName);
|
|
7196
7470
|
const documentDialogService = injector.get(AXMDocumentDialogService);
|
|
7197
7471
|
const result = await documentDialogService.openAttachmentDialogWithoutSave('Document Type Choose File', {
|
|
7198
7472
|
documentType: docType,
|
|
@@ -7211,41 +7485,18 @@ const DocumentFileUploaderEditDialogAfterFormProvider = {
|
|
|
7211
7485
|
key: 'file-uploader.edit-dialog.groups.after-form',
|
|
7212
7486
|
priority: 0,
|
|
7213
7487
|
async execute(payload) {
|
|
7214
|
-
// Debug: trace edit-dialog hook entry
|
|
7215
|
-
// eslint-disable-next-line no-console
|
|
7216
|
-
console.log('[DocumentFileUploaderEditDialogAfterForm] payload (before)', {
|
|
7217
|
-
plugins: payload.plugins,
|
|
7218
|
-
excludePlugins: payload.excludePlugins,
|
|
7219
|
-
file: payload.file,
|
|
7220
|
-
groups: payload.groups,
|
|
7221
|
-
});
|
|
7222
|
-
const isEnabled = Array.isArray(payload.plugins) && payload.plugins.some((p) => p.name === 'document');
|
|
7223
|
-
const isExcluded = Array.isArray(payload.excludePlugins) && payload.excludePlugins.includes('document');
|
|
7224
|
-
if (!isEnabled || isExcluded)
|
|
7225
|
-
return payload;
|
|
7226
7488
|
const metaObj = payload.file?.metaDataForm;
|
|
7227
|
-
|
|
7228
|
-
const
|
|
7229
|
-
// Debug: trace resolved options and meta object
|
|
7230
|
-
// eslint-disable-next-line no-console
|
|
7231
|
-
console.log('[DocumentFileUploaderEditDialogAfterForm] options & meta', {
|
|
7232
|
-
options: opts,
|
|
7233
|
-
metaObj,
|
|
7234
|
-
});
|
|
7489
|
+
const opts = getDocumentPluginOptions(payload);
|
|
7490
|
+
const docTypeName = payload.file?.__documentTypeName ?? opts?.docTypeName;
|
|
7235
7491
|
const injector = inject(Injector);
|
|
7236
7492
|
const documentManagementService = injector.get(AXPDocumentManagementService);
|
|
7237
|
-
const docType =
|
|
7238
|
-
? await documentManagementService.getDocumentTypeByName(
|
|
7493
|
+
const docType = docTypeName
|
|
7494
|
+
? await documentManagementService.getDocumentTypeByName(docTypeName)
|
|
7239
7495
|
: undefined;
|
|
7240
|
-
// Debug: trace loaded document type and final decision
|
|
7241
|
-
// eslint-disable-next-line no-console
|
|
7242
|
-
console.log('[DocumentFileUploaderEditDialogAfterForm] loaded docType', {
|
|
7243
|
-
docTypeName: opts.docTypeName,
|
|
7244
|
-
hasMetaObj: !!metaObj && Object.keys(metaObj).length > 0,
|
|
7245
|
-
docType,
|
|
7246
|
-
});
|
|
7247
7496
|
if (!docType && (!metaObj || Object.keys(metaObj).length === 0))
|
|
7248
7497
|
return payload;
|
|
7498
|
+
const metaDataList = docType?.metaDataList ?? { groups: [] };
|
|
7499
|
+
const hasDefinitions = Array.isArray(metaDataList.groups) && metaDataList.groups.length > 0;
|
|
7249
7500
|
const fields = [
|
|
7250
7501
|
{
|
|
7251
7502
|
path: 'metaDataForm',
|
|
@@ -7253,11 +7504,7 @@ const DocumentFileUploaderEditDialogAfterFormProvider = {
|
|
|
7253
7504
|
widget: {
|
|
7254
7505
|
name: 'metaDataForm',
|
|
7255
7506
|
type: 'meta-data-form-editor',
|
|
7256
|
-
|
|
7257
|
-
// - documentType.metaDataList structure is used directly in other dialogs:
|
|
7258
|
-
// AXMDocumentDialogService → field.customWidget('meta-data-form-editor', documentType?.metaDataList)
|
|
7259
|
-
// - So we pass the whole metaDataList object here as well for consistency.
|
|
7260
|
-
options: { definitions: docType?.metaDataList },
|
|
7507
|
+
options: metaDataList,
|
|
7261
7508
|
defaultValue: metaObj,
|
|
7262
7509
|
},
|
|
7263
7510
|
},
|
|
@@ -7267,19 +7514,8 @@ const DocumentFileUploaderEditDialogAfterFormProvider = {
|
|
|
7267
7514
|
title: docType?.title ?? '@document-management:terms.common.meta-data',
|
|
7268
7515
|
parameters: fields,
|
|
7269
7516
|
};
|
|
7270
|
-
// metaDataList is an object with a `groups` array; align condition with that structure
|
|
7271
|
-
const hasDefinitions = !!docType &&
|
|
7272
|
-
!!docType.metaDataList &&
|
|
7273
|
-
Array.isArray(docType.metaDataList.groups) &&
|
|
7274
|
-
docType.metaDataList.groups.length > 0;
|
|
7275
7517
|
if (hasDefinitions) {
|
|
7276
7518
|
payload.groups = [...(payload.groups ?? []), group];
|
|
7277
|
-
// Debug: confirm metadata group injection
|
|
7278
|
-
// eslint-disable-next-line no-console
|
|
7279
|
-
console.log('[DocumentFileUploaderEditDialogAfterForm] metadata group injected', {
|
|
7280
|
-
group,
|
|
7281
|
-
groupsAfter: payload.groups,
|
|
7282
|
-
});
|
|
7283
7519
|
}
|
|
7284
7520
|
return payload;
|
|
7285
7521
|
},
|
|
@@ -7374,6 +7610,7 @@ class AXMDocumentManagementModule {
|
|
|
7374
7610
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMDocumentManagementModule, providers: [
|
|
7375
7611
|
// Module-specific providers (not part of manifest system)
|
|
7376
7612
|
{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: attachmentsPlugin },
|
|
7613
|
+
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: attachmentsUploadMiddleware },
|
|
7377
7614
|
{
|
|
7378
7615
|
provide: ROUTES,
|
|
7379
7616
|
multi: true,
|
|
@@ -7384,6 +7621,11 @@ class AXMDocumentManagementModule {
|
|
|
7384
7621
|
useValue: p,
|
|
7385
7622
|
multi: true,
|
|
7386
7623
|
})),
|
|
7624
|
+
{
|
|
7625
|
+
provide: AXP_FILE_ACTION_PROVIDER,
|
|
7626
|
+
useValue: DocumentFileUploaderActionsByTypeProvider,
|
|
7627
|
+
multi: true,
|
|
7628
|
+
},
|
|
7387
7629
|
// Module Manifest Provider
|
|
7388
7630
|
{
|
|
7389
7631
|
provide: AXP_MODULE_MANIFEST_PROVIDER,
|
|
@@ -7472,6 +7714,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7472
7714
|
providers: [
|
|
7473
7715
|
// Module-specific providers (not part of manifest system)
|
|
7474
7716
|
{ provide: AXP_ENTITY_ACTION_PLUGIN, multi: true, useValue: attachmentsPlugin },
|
|
7717
|
+
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: attachmentsUploadMiddleware },
|
|
7475
7718
|
{
|
|
7476
7719
|
provide: ROUTES,
|
|
7477
7720
|
multi: true,
|
|
@@ -7482,6 +7725,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7482
7725
|
useValue: p,
|
|
7483
7726
|
multi: true,
|
|
7484
7727
|
})),
|
|
7728
|
+
{
|
|
7729
|
+
provide: AXP_FILE_ACTION_PROVIDER,
|
|
7730
|
+
useValue: DocumentFileUploaderActionsByTypeProvider,
|
|
7731
|
+
multi: true,
|
|
7732
|
+
},
|
|
7485
7733
|
// Module Manifest Provider
|
|
7486
7734
|
{
|
|
7487
7735
|
provide: AXP_MODULE_MANIFEST_PROVIDER,
|