@masterteam/workspace-builder 0.0.11 → 0.0.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/assets/i18n/ar.json +1 -0
- package/assets/i18n/en.json +1 -0
- package/assets/workspace-builder.css +2 -2
- package/fesm2022/masterteam-workspace-builder.mjs +154 -190
- package/fesm2022/masterteam-workspace-builder.mjs.map +1 -1
- package/package.json +2 -2
- package/types/masterteam-workspace-builder.d.ts +19 -24
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as i1$1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, Injectable, computed,
|
|
5
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { inject, Injectable, computed, signal, linkedSignal, Component, input, booleanAttribute, effect, ChangeDetectionStrategy } from '@angular/core';
|
|
6
5
|
import { TranslocoService, TranslocoDirective } from '@jsverse/transloco';
|
|
7
6
|
import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
8
7
|
import { DynamicDialogConfig, ModalRef, DialogService } from '@masterteam/components/dialog';
|
|
@@ -10,11 +9,9 @@ import { ModalService } from '@masterteam/components/modal';
|
|
|
10
9
|
import { Page } from '@masterteam/components/page';
|
|
11
10
|
import { Card } from '@masterteam/components/card';
|
|
12
11
|
import { ToastService } from '@masterteam/components/toast';
|
|
13
|
-
import * as i3 from 'primeng/contextmenu';
|
|
14
|
-
import { ContextMenuModule } from 'primeng/contextmenu';
|
|
15
12
|
import * as i2 from 'primeng/dragdrop';
|
|
16
13
|
import { DragDropModule } from 'primeng/dragdrop';
|
|
17
|
-
import * as
|
|
14
|
+
import * as i3 from 'primeng/skeleton';
|
|
18
15
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
19
16
|
import { finalize } from 'rxjs';
|
|
20
17
|
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
@@ -48,12 +45,10 @@ class SaveWorkspaceBuilderLayout {
|
|
|
48
45
|
}
|
|
49
46
|
class CreateWorkspaceBuilderGroup {
|
|
50
47
|
title;
|
|
51
|
-
area;
|
|
52
48
|
order;
|
|
53
49
|
static type = '[WorkspaceBuilder] Create Group';
|
|
54
|
-
constructor(title,
|
|
50
|
+
constructor(title, order) {
|
|
55
51
|
this.title = title;
|
|
56
|
-
this.area = area;
|
|
57
52
|
this.order = order;
|
|
58
53
|
}
|
|
59
54
|
}
|
|
@@ -92,7 +87,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
92
87
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
93
88
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
94
89
|
};
|
|
95
|
-
|
|
90
|
+
// AREA is kept as a reference constant (single-area layout)
|
|
96
91
|
function normalizeName(value) {
|
|
97
92
|
if (typeof value === 'string') {
|
|
98
93
|
return value;
|
|
@@ -128,15 +123,13 @@ function extractLocalizedTitle(value) {
|
|
|
128
123
|
function createEmptyLayout(levelId = 0) {
|
|
129
124
|
return {
|
|
130
125
|
levelId,
|
|
131
|
-
|
|
132
|
-
more: [],
|
|
126
|
+
tabs: [],
|
|
133
127
|
};
|
|
134
128
|
}
|
|
135
129
|
function cloneLayout(layout) {
|
|
136
130
|
return {
|
|
137
131
|
levelId: layout.levelId,
|
|
138
|
-
|
|
139
|
-
more: layout.more.map(cloneItem),
|
|
132
|
+
tabs: layout.tabs.map(cloneItem),
|
|
140
133
|
};
|
|
141
134
|
}
|
|
142
135
|
function cloneItem(item) {
|
|
@@ -199,32 +192,13 @@ function normalizeAreaItems(items) {
|
|
|
199
192
|
function normalizeLayout(layout) {
|
|
200
193
|
const normalized = {
|
|
201
194
|
levelId: layout?.levelId ?? 0,
|
|
202
|
-
|
|
203
|
-
more: normalizeAreaItems(layout?.more ?? []),
|
|
195
|
+
tabs: normalizeAreaItems(layout?.tabs ?? []),
|
|
204
196
|
};
|
|
205
197
|
return normalized;
|
|
206
198
|
}
|
|
207
199
|
function toSaveLayoutDto(layout) {
|
|
208
200
|
return {
|
|
209
|
-
|
|
210
|
-
if (item.type === 'group') {
|
|
211
|
-
return {
|
|
212
|
-
type: 'group',
|
|
213
|
-
id: item.id,
|
|
214
|
-
order: index + 1,
|
|
215
|
-
modules: item.modules.map((module, moduleIndex) => ({
|
|
216
|
-
id: module.id,
|
|
217
|
-
order: moduleIndex + 1,
|
|
218
|
-
})),
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
type: 'module',
|
|
223
|
-
id: item.id,
|
|
224
|
-
order: index + 1,
|
|
225
|
-
};
|
|
226
|
-
}),
|
|
227
|
-
more: layout.more.map((item, index) => {
|
|
201
|
+
tabs: layout.tabs.map((item, index) => {
|
|
228
202
|
if (item.type === 'group') {
|
|
229
203
|
return {
|
|
230
204
|
type: 'group',
|
|
@@ -251,38 +225,36 @@ function validateLayout(layout) {
|
|
|
251
225
|
const errors = [];
|
|
252
226
|
const moduleIds = [];
|
|
253
227
|
const groupIds = [];
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
errors.push(`Duplicate order detected in ${area} list.`);
|
|
259
|
-
}
|
|
260
|
-
items.forEach((item) => {
|
|
261
|
-
if (item.type === 'group') {
|
|
262
|
-
groupIds.push(item.id);
|
|
263
|
-
const groupOrders = item.modules.map((module) => module.order);
|
|
264
|
-
if (hasDuplicate(groupOrders.map(String))) {
|
|
265
|
-
errors.push(`Duplicate order detected in group ${item.id}.`);
|
|
266
|
-
}
|
|
267
|
-
item.modules.forEach((module) => {
|
|
268
|
-
const typedModule = module;
|
|
269
|
-
if (typedModule?.type === 'group' ||
|
|
270
|
-
Array.isArray(typedModule?.modules)) {
|
|
271
|
-
errors.push(`Nested groups are not supported (group ${item.id}).`);
|
|
272
|
-
}
|
|
273
|
-
moduleIds.push(module.id);
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
moduleIds.push(item.id);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
228
|
+
const items = layout.tabs;
|
|
229
|
+
const orders = items.map((item) => item.order);
|
|
230
|
+
if (hasDuplicate(orders.map(String))) {
|
|
231
|
+
errors.push('Duplicate order detected in tabs list.');
|
|
280
232
|
}
|
|
233
|
+
items.forEach((item) => {
|
|
234
|
+
if (item.type === 'group') {
|
|
235
|
+
groupIds.push(item.id);
|
|
236
|
+
const groupOrders = item.modules.map((module) => module.order);
|
|
237
|
+
if (hasDuplicate(groupOrders.map(String))) {
|
|
238
|
+
errors.push(`Duplicate order detected in group ${item.id}.`);
|
|
239
|
+
}
|
|
240
|
+
item.modules.forEach((module) => {
|
|
241
|
+
const typedModule = module;
|
|
242
|
+
if (typedModule?.type === 'group' ||
|
|
243
|
+
Array.isArray(typedModule?.modules)) {
|
|
244
|
+
errors.push(`Nested groups are not supported (group ${item.id}).`);
|
|
245
|
+
}
|
|
246
|
+
moduleIds.push(module.id);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
moduleIds.push(item.id);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
281
253
|
if (hasDuplicate(moduleIds)) {
|
|
282
|
-
errors.push('Duplicate module IDs detected
|
|
254
|
+
errors.push('Duplicate module IDs detected in tabs and groups.');
|
|
283
255
|
}
|
|
284
256
|
if (hasDuplicate(groupIds)) {
|
|
285
|
-
errors.push('Duplicate group IDs detected in
|
|
257
|
+
errors.push('Duplicate group IDs detected in tabs.');
|
|
286
258
|
}
|
|
287
259
|
return Array.from(new Set(errors));
|
|
288
260
|
}
|
|
@@ -292,9 +264,9 @@ function computeIsDirty(layout, originalLayout) {
|
|
|
292
264
|
}
|
|
293
265
|
return (JSON.stringify(toSaveLayoutDto(layout)) !== JSON.stringify(originalLayout));
|
|
294
266
|
}
|
|
295
|
-
function insertGroupIntoLayout(layout, groupId, title,
|
|
267
|
+
function insertGroupIntoLayout(layout, groupId, title, order) {
|
|
296
268
|
const next = cloneLayout(layout);
|
|
297
|
-
const list = next
|
|
269
|
+
const list = next.tabs;
|
|
298
270
|
const insertIndex = Math.max(0, Math.min((order ?? list.length + 1) - 1, list.length));
|
|
299
271
|
const group = {
|
|
300
272
|
type: 'group',
|
|
@@ -309,32 +281,25 @@ function insertGroupIntoLayout(layout, groupId, title, area, order) {
|
|
|
309
281
|
}
|
|
310
282
|
function renameGroupInLayout(layout, groupId, title) {
|
|
311
283
|
const next = cloneLayout(layout);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
group.localizedName = { ...title };
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
284
|
+
const group = next.tabs.find((item) => item.type === 'group' && item.id === groupId);
|
|
285
|
+
if (group) {
|
|
286
|
+
group.name = title.en || title.ar;
|
|
287
|
+
group.localizedName = { ...title };
|
|
319
288
|
}
|
|
320
289
|
return normalizeLayout(next);
|
|
321
290
|
}
|
|
322
291
|
function removeGroupAndPromoteModules(layout, groupId) {
|
|
323
292
|
const next = cloneLayout(layout);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
const group = next[area][index];
|
|
293
|
+
const index = next.tabs.findIndex((item) => item.type === 'group' && item.id === groupId);
|
|
294
|
+
if (index !== -1) {
|
|
295
|
+
const group = next.tabs[index];
|
|
330
296
|
const promotedModules = group.modules.map((module) => ({
|
|
331
297
|
type: 'module',
|
|
332
298
|
id: module.id,
|
|
333
299
|
name: module.name,
|
|
334
300
|
order: 0,
|
|
335
301
|
}));
|
|
336
|
-
next
|
|
337
|
-
break;
|
|
302
|
+
next.tabs.splice(index, 1, ...promotedModules);
|
|
338
303
|
}
|
|
339
304
|
return normalizeLayout(next);
|
|
340
305
|
}
|
|
@@ -356,11 +321,8 @@ let WorkspaceBuilderState = class WorkspaceBuilderState extends CrudStateBase {
|
|
|
356
321
|
static getLayout(state) {
|
|
357
322
|
return state.layout;
|
|
358
323
|
}
|
|
359
|
-
static
|
|
360
|
-
return state.layout.
|
|
361
|
-
}
|
|
362
|
-
static getMoreItems(state) {
|
|
363
|
-
return state.layout.more;
|
|
324
|
+
static getTabItems(state) {
|
|
325
|
+
return state.layout.tabs;
|
|
364
326
|
}
|
|
365
327
|
static getValidationErrors(state) {
|
|
366
328
|
return state.validationErrors;
|
|
@@ -402,8 +364,9 @@ let WorkspaceBuilderState = class WorkspaceBuilderState extends CrudStateBase {
|
|
|
402
364
|
key: WorkspaceBuilderActionKey.GetLayout,
|
|
403
365
|
request$: req$,
|
|
404
366
|
onSuccess: (response) => {
|
|
405
|
-
const
|
|
406
|
-
|
|
367
|
+
const data = response.data;
|
|
368
|
+
const incoming = data
|
|
369
|
+
? { levelId, tabs: data.tabs ?? [] }
|
|
407
370
|
: createEmptyLayout(levelId);
|
|
408
371
|
const normalized = normalizeLayout(incoming);
|
|
409
372
|
const validationErrors = validateLayout(normalized);
|
|
@@ -464,14 +427,13 @@ let WorkspaceBuilderState = class WorkspaceBuilderState extends CrudStateBase {
|
|
|
464
427
|
}),
|
|
465
428
|
});
|
|
466
429
|
}
|
|
467
|
-
createGroup(ctx, { title,
|
|
430
|
+
createGroup(ctx, { title, order }) {
|
|
468
431
|
const { levelId } = ctx.getState();
|
|
469
432
|
if (!levelId) {
|
|
470
433
|
return;
|
|
471
434
|
}
|
|
472
435
|
const req$ = this.http.post(`levels/${levelId}/workspaceBuilder/groups`, {
|
|
473
436
|
title,
|
|
474
|
-
area,
|
|
475
437
|
order: order ?? 1,
|
|
476
438
|
});
|
|
477
439
|
return handleApiRequest({
|
|
@@ -483,7 +445,7 @@ let WorkspaceBuilderState = class WorkspaceBuilderState extends CrudStateBase {
|
|
|
483
445
|
if (!groupId) {
|
|
484
446
|
return {};
|
|
485
447
|
}
|
|
486
|
-
const nextLayout = insertGroupIntoLayout(state.layout, groupId, title,
|
|
448
|
+
const nextLayout = insertGroupIntoLayout(state.layout, groupId, title, order);
|
|
487
449
|
const validationErrors = validateLayout(nextLayout);
|
|
488
450
|
return {
|
|
489
451
|
layout: nextLayout,
|
|
@@ -587,10 +549,7 @@ __decorate([
|
|
|
587
549
|
], WorkspaceBuilderState, "getLayout", null);
|
|
588
550
|
__decorate([
|
|
589
551
|
Selector()
|
|
590
|
-
], WorkspaceBuilderState, "
|
|
591
|
-
__decorate([
|
|
592
|
-
Selector()
|
|
593
|
-
], WorkspaceBuilderState, "getMoreItems", null);
|
|
552
|
+
], WorkspaceBuilderState, "getTabItems", null);
|
|
594
553
|
__decorate([
|
|
595
554
|
Selector()
|
|
596
555
|
], WorkspaceBuilderState, "getValidationErrors", null);
|
|
@@ -620,8 +579,7 @@ class WorkspaceBuilderFacade {
|
|
|
620
579
|
store = inject(Store);
|
|
621
580
|
levelId = select(WorkspaceBuilderState.getLevelId);
|
|
622
581
|
layout = select(WorkspaceBuilderState.getLayout);
|
|
623
|
-
|
|
624
|
-
moreItems = select(WorkspaceBuilderState.getMoreItems);
|
|
582
|
+
tabItems = select(WorkspaceBuilderState.getTabItems);
|
|
625
583
|
validationErrors = select(WorkspaceBuilderState.getValidationErrors);
|
|
626
584
|
isDirty = select(WorkspaceBuilderState.getIsDirty);
|
|
627
585
|
successMessages = select(WorkspaceBuilderState.getSuccessMessages);
|
|
@@ -652,8 +610,8 @@ class WorkspaceBuilderFacade {
|
|
|
652
610
|
saveLayout() {
|
|
653
611
|
return this.store.dispatch(new SaveWorkspaceBuilderLayout());
|
|
654
612
|
}
|
|
655
|
-
createGroup(title,
|
|
656
|
-
return this.store.dispatch(new CreateWorkspaceBuilderGroup(title,
|
|
613
|
+
createGroup(title, order) {
|
|
614
|
+
return this.store.dispatch(new CreateWorkspaceBuilderGroup(title, order));
|
|
657
615
|
}
|
|
658
616
|
renameGroup(groupId, title) {
|
|
659
617
|
return this.store.dispatch(new RenameWorkspaceBuilderGroup(groupId, title));
|
|
@@ -673,7 +631,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
673
631
|
}] });
|
|
674
632
|
|
|
675
633
|
class WorkspaceBuilderCreateGroupDialog {
|
|
676
|
-
area = input(null, ...(ngDevMode ? [{ debugName: "area" }] : /* istanbul ignore next */ []));
|
|
677
634
|
modal = inject(ModalService);
|
|
678
635
|
config = inject(DynamicDialogConfig, { optional: true });
|
|
679
636
|
ref = inject(ModalRef);
|
|
@@ -725,9 +682,6 @@ class WorkspaceBuilderCreateGroupDialog {
|
|
|
725
682
|
});
|
|
726
683
|
}
|
|
727
684
|
}
|
|
728
|
-
resolvedArea() {
|
|
729
|
-
return this.area() ?? this.dialogData.area ?? 'main';
|
|
730
|
-
}
|
|
731
685
|
submit() {
|
|
732
686
|
const value = this.formControl.value;
|
|
733
687
|
const en = (value?.title?.en ?? '').trim();
|
|
@@ -751,9 +705,8 @@ class WorkspaceBuilderCreateGroupDialog {
|
|
|
751
705
|
});
|
|
752
706
|
}
|
|
753
707
|
else {
|
|
754
|
-
const area = this.resolvedArea();
|
|
755
708
|
const order = this.dialogData.order;
|
|
756
|
-
this.facade.createGroup(title,
|
|
709
|
+
this.facade.createGroup(title, order).subscribe({
|
|
757
710
|
next: () => {
|
|
758
711
|
this.ts.success(this.translocoService.translate('workspace-builder.group-create-success'));
|
|
759
712
|
this.facade.getLayout();
|
|
@@ -770,7 +723,7 @@ class WorkspaceBuilderCreateGroupDialog {
|
|
|
770
723
|
this.ref.close(null);
|
|
771
724
|
}
|
|
772
725
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkspaceBuilderCreateGroupDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
773
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
726
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.8", type: WorkspaceBuilderCreateGroupDialog, isStandalone: true, selector: "mt-workspace-builder-create-group-dialog", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n <form class=\"col-span-1\">\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfig()\"\r\n [formControl]=\"formControl\"\r\n />\r\n </form>\r\n </div>\r\n\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n variant=\"outlined\"\r\n [label]=\"t('cancel')\"\r\n (onClick)=\"cancel()\"\r\n ></mt-button>\r\n\r\n <mt-button\r\n [label]=\"isEditMode ? t('save') : t('add-group')\"\r\n [disabled]=\"!formControl.valid\"\r\n [loading]=\"isSaving()\"\r\n (onClick)=\"submit()\"\r\n ></mt-button>\r\n </div>\r\n</ng-container>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }] });
|
|
774
727
|
}
|
|
775
728
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkspaceBuilderCreateGroupDialog, decorators: [{
|
|
776
729
|
type: Component,
|
|
@@ -781,22 +734,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
781
734
|
DynamicForm,
|
|
782
735
|
TranslocoDirective,
|
|
783
736
|
], template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n <form class=\"col-span-1\">\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfig()\"\r\n [formControl]=\"formControl\"\r\n />\r\n </form>\r\n </div>\r\n\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button\r\n variant=\"outlined\"\r\n [label]=\"t('cancel')\"\r\n (onClick)=\"cancel()\"\r\n ></mt-button>\r\n\r\n <mt-button\r\n [label]=\"isEditMode ? t('save') : t('add-group')\"\r\n [disabled]=\"!formControl.valid\"\r\n [loading]=\"isSaving()\"\r\n (onClick)=\"submit()\"\r\n ></mt-button>\r\n </div>\r\n</ng-container>\r\n" }]
|
|
784
|
-
}], ctorParameters: () => []
|
|
737
|
+
}], ctorParameters: () => [] });
|
|
785
738
|
|
|
786
739
|
const DRAG_PAYLOAD_MIME = 'application/x-workspace-builder';
|
|
787
740
|
class WorkspaceBuilder {
|
|
788
741
|
levelId = input(null, ...(ngDevMode ? [{ debugName: "levelId" }] : /* istanbul ignore next */ []));
|
|
789
742
|
showHeader = input(true, { ...(ngDevMode ? { debugName: "showHeader" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
790
743
|
autoSave = input(true, { ...(ngDevMode ? { debugName: "autoSave" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
791
|
-
areas = ['
|
|
744
|
+
areas = ['tabs'];
|
|
792
745
|
dropScope = 'workspace-builder-item';
|
|
793
746
|
loadingSkeletonRows = [0, 1, 2, 3];
|
|
794
|
-
createGroupArea = signal('main', ...(ngDevMode ? [{ debugName: "createGroupArea" }] : /* istanbul ignore next */ []));
|
|
795
747
|
isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
|
|
796
748
|
activeDropSlotKey = signal(null, ...(ngDevMode ? [{ debugName: "activeDropSlotKey" }] : /* istanbul ignore next */ []));
|
|
797
749
|
expandedGroups = signal({}, ...(ngDevMode ? [{ debugName: "expandedGroups" }] : /* istanbul ignore next */ []));
|
|
798
750
|
dragPayload = signal(null, ...(ngDevMode ? [{ debugName: "dragPayload" }] : /* istanbul ignore next */ []));
|
|
799
751
|
dragCleanupTimer = null;
|
|
752
|
+
scrollAnimFrame = null;
|
|
753
|
+
scrollContainer = null;
|
|
754
|
+
scrollDirection = 0;
|
|
800
755
|
autoSaveInFlight = false;
|
|
801
756
|
autoSaveQueued = false;
|
|
802
757
|
autoSaveQueuedNotifySuccess = false;
|
|
@@ -805,21 +760,11 @@ class WorkspaceBuilder {
|
|
|
805
760
|
modal = inject(ModalService);
|
|
806
761
|
transloco = inject(TranslocoService);
|
|
807
762
|
ts = inject(ToastService);
|
|
808
|
-
addGroupLabel = toSignal(this.transloco.selectTranslate('workspace-builder.add-group'), {
|
|
809
|
-
initialValue: this.transloco.translate('workspace-builder.add-group'),
|
|
810
|
-
});
|
|
811
763
|
layout = this.facade.layout;
|
|
812
764
|
validationErrors = this.facade.validationErrors;
|
|
813
765
|
isLoadingLayout = this.facade.isLoadingLayout;
|
|
814
766
|
layoutError = this.facade.layoutError;
|
|
815
767
|
isSavingLayout = this.facade.isSavingLayout;
|
|
816
|
-
areaContextItems = computed(() => [
|
|
817
|
-
{
|
|
818
|
-
label: this.addGroupLabel(),
|
|
819
|
-
icon: 'pi pi-plus',
|
|
820
|
-
command: () => this.openCreateGroupDialog(this.createGroupArea()),
|
|
821
|
-
},
|
|
822
|
-
], ...(ngDevMode ? [{ debugName: "areaContextItems" }] : /* istanbul ignore next */ []));
|
|
823
768
|
constructor() {
|
|
824
769
|
effect(() => {
|
|
825
770
|
const levelId = this.levelId();
|
|
@@ -856,8 +801,8 @@ class WorkspaceBuilder {
|
|
|
856
801
|
this.clearDragCleanupTimer();
|
|
857
802
|
this.facade.resetState();
|
|
858
803
|
}
|
|
859
|
-
areaItems(
|
|
860
|
-
return this.layout()
|
|
804
|
+
areaItems(_area) {
|
|
805
|
+
return this.layout().tabs;
|
|
861
806
|
}
|
|
862
807
|
trackItem(item) {
|
|
863
808
|
return `${item.type}:${item.id}`;
|
|
@@ -963,9 +908,7 @@ class WorkspaceBuilder {
|
|
|
963
908
|
if (!payload)
|
|
964
909
|
return false;
|
|
965
910
|
if (payload.kind === 'group') {
|
|
966
|
-
|
|
967
|
-
return false;
|
|
968
|
-
const list = this.layout()[area];
|
|
911
|
+
const list = this.layout().tabs;
|
|
969
912
|
const movingIds = new Set(payload.groups.map((group) => group.id));
|
|
970
913
|
const movingIndexes = list
|
|
971
914
|
.map((item, i) => item.type === 'group' && movingIds.has(item.id) ? i : -1)
|
|
@@ -975,10 +918,10 @@ class WorkspaceBuilder {
|
|
|
975
918
|
const sourceIndex = movingIndexes[0];
|
|
976
919
|
return index === sourceIndex || index === sourceIndex + 1;
|
|
977
920
|
}
|
|
978
|
-
if (payload.source.type !== 'area'
|
|
921
|
+
if (payload.source.type !== 'area') {
|
|
979
922
|
return false;
|
|
980
923
|
}
|
|
981
|
-
const list = this.layout()
|
|
924
|
+
const list = this.layout().tabs;
|
|
982
925
|
const movingIds = new Set(payload.modules.map((module) => module.id));
|
|
983
926
|
const movingIndexes = list
|
|
984
927
|
.map((item, i) => item.type === 'module' && movingIds.has(item.id) ? i : -1)
|
|
@@ -1025,14 +968,9 @@ class WorkspaceBuilder {
|
|
|
1025
968
|
const index = this.resolveSiblingDropIndex(event, moduleIndex);
|
|
1026
969
|
this.handleDrop({ type: 'group', area, groupId }, index, event);
|
|
1027
970
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
contextMenu.show(event);
|
|
1032
|
-
}
|
|
1033
|
-
openCreateGroupDialog(area) {
|
|
1034
|
-
const order = this.layout()[area].length + 1;
|
|
1035
|
-
const data = { area, order };
|
|
971
|
+
openCreateGroupDialog(_area = 'tabs') {
|
|
972
|
+
const order = this.layout().tabs.length + 1;
|
|
973
|
+
const data = { order };
|
|
1036
974
|
this.modal.openModal(WorkspaceBuilderCreateGroupDialog, 'dialog', {
|
|
1037
975
|
header: this.transloco.translate('workspace-builder.create-group'),
|
|
1038
976
|
styleClass: '!w-[28rem]',
|
|
@@ -1040,7 +978,6 @@ class WorkspaceBuilder {
|
|
|
1040
978
|
appendTo: 'body',
|
|
1041
979
|
dismissableMask: true,
|
|
1042
980
|
data,
|
|
1043
|
-
inputValues: { area },
|
|
1044
981
|
});
|
|
1045
982
|
}
|
|
1046
983
|
startRenameGroup(group) {
|
|
@@ -1055,7 +992,6 @@ class WorkspaceBuilder {
|
|
|
1055
992
|
appendTo: 'body',
|
|
1056
993
|
dismissableMask: true,
|
|
1057
994
|
data,
|
|
1058
|
-
inputValues: { area: null },
|
|
1059
995
|
});
|
|
1060
996
|
}
|
|
1061
997
|
onSaveClick() {
|
|
@@ -1096,12 +1032,12 @@ class WorkspaceBuilder {
|
|
|
1096
1032
|
return;
|
|
1097
1033
|
}
|
|
1098
1034
|
const [module] = group.modules.splice(moduleIndex, 1);
|
|
1099
|
-
const
|
|
1100
|
-
const groupIndex =
|
|
1035
|
+
const tabsItems = nextLayout.tabs;
|
|
1036
|
+
const groupIndex = tabsItems.findIndex((item) => item.type === 'group' && item.id === groupId);
|
|
1101
1037
|
if (groupIndex === -1) {
|
|
1102
1038
|
return;
|
|
1103
1039
|
}
|
|
1104
|
-
|
|
1040
|
+
tabsItems.splice(groupIndex + 1, 0, {
|
|
1105
1041
|
type: 'module',
|
|
1106
1042
|
id: module.id,
|
|
1107
1043
|
name: module.name,
|
|
@@ -1162,14 +1098,8 @@ class WorkspaceBuilder {
|
|
|
1162
1098
|
}
|
|
1163
1099
|
}))
|
|
1164
1100
|
.subscribe({
|
|
1165
|
-
next: () => {
|
|
1166
|
-
|
|
1167
|
-
this.ts.success(this.getSuccessMessage(WorkspaceBuilderActionKey.SaveLayout, 'workspace-builder.layout-update-success'));
|
|
1168
|
-
}
|
|
1169
|
-
},
|
|
1170
|
-
error: () => {
|
|
1171
|
-
this.ts.error(this.getErrorMessage(WorkspaceBuilderActionKey.SaveLayout, 'workspace-builder.layout-update-error'));
|
|
1172
|
-
},
|
|
1101
|
+
next: () => { },
|
|
1102
|
+
error: () => { },
|
|
1173
1103
|
});
|
|
1174
1104
|
}
|
|
1175
1105
|
resolveDropPayload(event) {
|
|
@@ -1210,15 +1140,70 @@ class WorkspaceBuilder {
|
|
|
1210
1140
|
this.activeDropSlotKey.set(null);
|
|
1211
1141
|
this.clearDragCleanupTimer();
|
|
1212
1142
|
}
|
|
1143
|
+
onAreaBodyDragOver(event) {
|
|
1144
|
+
this.allowNativeDrop(event);
|
|
1145
|
+
this.updateEdgeScroll(event);
|
|
1146
|
+
}
|
|
1147
|
+
onAreaBodyDragLeave(event) {
|
|
1148
|
+
const container = event.currentTarget;
|
|
1149
|
+
const related = event.relatedTarget;
|
|
1150
|
+
if (!related || !container?.contains(related)) {
|
|
1151
|
+
this.stopEdgeScroll();
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
updateEdgeScroll(event) {
|
|
1155
|
+
const container = event.currentTarget;
|
|
1156
|
+
if (!container)
|
|
1157
|
+
return;
|
|
1158
|
+
const rect = container.getBoundingClientRect();
|
|
1159
|
+
const y = event.clientY;
|
|
1160
|
+
const zone = 80;
|
|
1161
|
+
let direction = 0;
|
|
1162
|
+
if (y - rect.top < zone && container.scrollTop > 0) {
|
|
1163
|
+
direction = -1;
|
|
1164
|
+
}
|
|
1165
|
+
else if (rect.bottom - y < zone &&
|
|
1166
|
+
container.scrollTop < container.scrollHeight - container.clientHeight) {
|
|
1167
|
+
direction = 1;
|
|
1168
|
+
}
|
|
1169
|
+
if (this.scrollContainer !== container ||
|
|
1170
|
+
this.scrollDirection !== direction) {
|
|
1171
|
+
this.scrollContainer = container;
|
|
1172
|
+
this.scrollDirection = direction;
|
|
1173
|
+
this.stopEdgeScroll();
|
|
1174
|
+
if (direction !== 0) {
|
|
1175
|
+
this.runEdgeScroll();
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
runEdgeScroll() {
|
|
1180
|
+
const tick = () => {
|
|
1181
|
+
if (!this.scrollContainer || this.scrollDirection === 0)
|
|
1182
|
+
return;
|
|
1183
|
+
this.scrollContainer.scrollTop += this.scrollDirection * 14;
|
|
1184
|
+
this.scrollAnimFrame = requestAnimationFrame(tick);
|
|
1185
|
+
};
|
|
1186
|
+
this.scrollAnimFrame = requestAnimationFrame(tick);
|
|
1187
|
+
}
|
|
1188
|
+
stopEdgeScroll() {
|
|
1189
|
+
if (this.scrollAnimFrame !== null) {
|
|
1190
|
+
cancelAnimationFrame(this.scrollAnimFrame);
|
|
1191
|
+
this.scrollAnimFrame = null;
|
|
1192
|
+
}
|
|
1193
|
+
this.scrollDirection = 0;
|
|
1194
|
+
this.scrollContainer = null;
|
|
1195
|
+
}
|
|
1213
1196
|
endDragSession() {
|
|
1214
1197
|
this.isDragging.set(false);
|
|
1215
1198
|
this.activeDropSlotKey.set(null);
|
|
1216
1199
|
this.dragPayload.set(null);
|
|
1200
|
+
this.stopEdgeScroll();
|
|
1217
1201
|
this.clearDragCleanupTimer();
|
|
1218
1202
|
}
|
|
1219
1203
|
scheduleDragSessionCleanup() {
|
|
1220
1204
|
this.isDragging.set(false);
|
|
1221
1205
|
this.activeDropSlotKey.set(null);
|
|
1206
|
+
this.stopEdgeScroll();
|
|
1222
1207
|
this.clearDragCleanupTimer();
|
|
1223
1208
|
this.dragCleanupTimer = setTimeout(() => {
|
|
1224
1209
|
this.dragPayload.set(null);
|
|
@@ -1286,53 +1271,34 @@ class WorkspaceBuilder {
|
|
|
1286
1271
|
if (!root) {
|
|
1287
1272
|
return null;
|
|
1288
1273
|
}
|
|
1289
|
-
const selector = area
|
|
1290
|
-
? `[data-area="main"][data-item-index="${itemIndex}"]`
|
|
1291
|
-
: `[data-area="more"][data-item-index="${itemIndex}"]`;
|
|
1274
|
+
const selector = `[data-area="tabs"][data-item-index="${itemIndex}"]`;
|
|
1292
1275
|
return root.querySelector(selector);
|
|
1293
1276
|
}
|
|
1294
1277
|
moveGroups(layout, payload, target, targetIndex) {
|
|
1295
1278
|
if (target.type !== 'area') {
|
|
1296
1279
|
return;
|
|
1297
1280
|
}
|
|
1298
|
-
const sourceArea = payload.source.area;
|
|
1299
|
-
const targetArea = target.area;
|
|
1300
1281
|
const groupIds = new Set(payload.groups.map((group) => group.id));
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
const moving = original.filter((item) => item.type === 'group' && groupIds.has(item.id));
|
|
1304
|
-
if (moving.length === 0) {
|
|
1305
|
-
return;
|
|
1306
|
-
}
|
|
1307
|
-
const removedBefore = original
|
|
1308
|
-
.slice(0, targetIndex)
|
|
1309
|
-
.filter((item) => item.type === 'group' && groupIds.has(item.id)).length;
|
|
1310
|
-
const remaining = original.filter((item) => !(item.type === 'group' && groupIds.has(item.id)));
|
|
1311
|
-
const insertIndex = this.clampIndex(targetIndex - removedBefore, remaining.length);
|
|
1312
|
-
layout[sourceArea] = [
|
|
1313
|
-
...remaining.slice(0, insertIndex),
|
|
1314
|
-
...moving,
|
|
1315
|
-
...remaining.slice(insertIndex),
|
|
1316
|
-
];
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
const sourceList = layout[sourceArea];
|
|
1320
|
-
const moving = sourceList.filter((item) => item.type === 'group' && groupIds.has(item.id));
|
|
1282
|
+
const original = layout.tabs;
|
|
1283
|
+
const moving = original.filter((item) => item.type === 'group' && groupIds.has(item.id));
|
|
1321
1284
|
if (moving.length === 0) {
|
|
1322
1285
|
return;
|
|
1323
1286
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1287
|
+
const removedBefore = original
|
|
1288
|
+
.slice(0, targetIndex)
|
|
1289
|
+
.filter((item) => item.type === 'group' && groupIds.has(item.id)).length;
|
|
1290
|
+
const remaining = original.filter((item) => !(item.type === 'group' && groupIds.has(item.id)));
|
|
1291
|
+
const insertIndex = this.clampIndex(targetIndex - removedBefore, remaining.length);
|
|
1292
|
+
layout.tabs = [
|
|
1293
|
+
...remaining.slice(0, insertIndex),
|
|
1294
|
+
...moving,
|
|
1295
|
+
...remaining.slice(insertIndex),
|
|
1296
|
+
];
|
|
1328
1297
|
}
|
|
1329
1298
|
moveModules(layout, payload, target, targetIndex) {
|
|
1330
1299
|
const moduleIds = new Set(payload.modules.map((module) => module.id));
|
|
1331
|
-
if (payload.source.type === 'area' &&
|
|
1332
|
-
|
|
1333
|
-
payload.source.area === target.area) {
|
|
1334
|
-
const area = payload.source.area;
|
|
1335
|
-
const original = layout[area];
|
|
1300
|
+
if (payload.source.type === 'area' && target.type === 'area') {
|
|
1301
|
+
const original = layout.tabs;
|
|
1336
1302
|
const moving = original.filter((item) => item.type === 'module' && moduleIds.has(item.id));
|
|
1337
1303
|
if (moving.length === 0) {
|
|
1338
1304
|
return;
|
|
@@ -1342,7 +1308,7 @@ class WorkspaceBuilder {
|
|
|
1342
1308
|
.filter((item) => item.type === 'module' && moduleIds.has(item.id)).length;
|
|
1343
1309
|
const remaining = original.filter((item) => !(item.type === 'module' && moduleIds.has(item.id)));
|
|
1344
1310
|
const insertIndex = this.clampIndex(targetIndex - removedBefore, remaining.length);
|
|
1345
|
-
layout
|
|
1311
|
+
layout.tabs = [
|
|
1346
1312
|
...remaining.slice(0, insertIndex),
|
|
1347
1313
|
...moving,
|
|
1348
1314
|
...remaining.slice(insertIndex),
|
|
@@ -1379,7 +1345,7 @@ class WorkspaceBuilder {
|
|
|
1379
1345
|
return;
|
|
1380
1346
|
}
|
|
1381
1347
|
if (target.type === 'area') {
|
|
1382
|
-
const areaList = layout
|
|
1348
|
+
const areaList = layout.tabs;
|
|
1383
1349
|
const insertIndex = this.clampIndex(targetIndex, areaList.length);
|
|
1384
1350
|
const topLevelModules = extracted.map((module) => ({
|
|
1385
1351
|
type: 'module',
|
|
@@ -1399,7 +1365,7 @@ class WorkspaceBuilder {
|
|
|
1399
1365
|
}
|
|
1400
1366
|
extractModulesFromSource(layout, source, moduleIds) {
|
|
1401
1367
|
if (source.type === 'area') {
|
|
1402
|
-
const areaList = layout
|
|
1368
|
+
const areaList = layout.tabs;
|
|
1403
1369
|
const moving = areaList
|
|
1404
1370
|
.filter((item) => item.type === 'module' && moduleIds.has(item.id))
|
|
1405
1371
|
.map((module) => ({
|
|
@@ -1407,7 +1373,7 @@ class WorkspaceBuilder {
|
|
|
1407
1373
|
name: module.name,
|
|
1408
1374
|
order: module.order,
|
|
1409
1375
|
}));
|
|
1410
|
-
layout
|
|
1376
|
+
layout.tabs = areaList.filter((item) => !(item.type === 'module' && moduleIds.has(item.id)));
|
|
1411
1377
|
return moving;
|
|
1412
1378
|
}
|
|
1413
1379
|
const group = this.findGroup(layout, source.area, source.groupId);
|
|
@@ -1419,20 +1385,19 @@ class WorkspaceBuilder {
|
|
|
1419
1385
|
return moving;
|
|
1420
1386
|
}
|
|
1421
1387
|
findGroup(layout, area, groupId) {
|
|
1422
|
-
const found = layout
|
|
1388
|
+
const found = layout.tabs.find((item) => item.type === 'group' && item.id === groupId);
|
|
1423
1389
|
return found ?? null;
|
|
1424
1390
|
}
|
|
1425
1391
|
clampIndex(index, length) {
|
|
1426
1392
|
return Math.max(0, Math.min(index, length));
|
|
1427
1393
|
}
|
|
1428
1394
|
getAllGroups(layout) {
|
|
1429
|
-
return [...layout.
|
|
1395
|
+
return [...layout.tabs].filter((item) => item.type === 'group');
|
|
1430
1396
|
}
|
|
1431
1397
|
cloneLayout(layout) {
|
|
1432
1398
|
return {
|
|
1433
1399
|
levelId: layout.levelId,
|
|
1434
|
-
|
|
1435
|
-
more: layout.more.map((item) => this.cloneItem(item)),
|
|
1400
|
+
tabs: layout.tabs.map((item) => this.cloneItem(item)),
|
|
1436
1401
|
};
|
|
1437
1402
|
}
|
|
1438
1403
|
cloneItem(item) {
|
|
@@ -1472,7 +1437,7 @@ class WorkspaceBuilder {
|
|
|
1472
1437
|
return this.transloco.translate(fallbackTranslationKey);
|
|
1473
1438
|
}
|
|
1474
1439
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkspaceBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1475
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkspaceBuilder, isStandalone: true, selector: "mt-workspace-builder", inputs: { levelId: { classPropertyName: "levelId", publicName: "levelId", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, autoSave: { classPropertyName: "autoSave", publicName: "autoSave", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DialogService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <p-contextMenu\r\n #areaContextMenu\r\n [model]=\"areaContextItems()\"\r\n appendTo=\"body\"\r\n />\r\n\r\n <ng-template #builderContent>\r\n @if (isLoadingLayout()) {\r\n <div class=\"grid gap-5\">\r\n <div class=\"grid grid-cols-1 gap-5 xl:grid-cols-2\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"min-h-[26rem] overflow-hidden bg-surface-0\"\r\n >\r\n <div\r\n class=\"grid min-h-full content-start gap-4 bg-surface-50/60 p-5 pt-4\"\r\n >\r\n @for (row of loadingSkeletonRows; track row) {\r\n <div\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 px-3 py-3 shadow-sm\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton size=\"2rem\" borderRadius=\"0.75rem\" />\r\n <div class=\"grid flex-1 gap-2\">\r\n <p-skeleton width=\"75%\" height=\"1rem\" />\r\n <p-skeleton width=\"45%\" height=\"0.8rem\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n } @else if (layoutError(); as error) {\r\n <div\r\n class=\"grid gap-4 rounded-xl border border-red-200 bg-red-50 px-5 py-6 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"grid gap-1\">\r\n <div class=\"text-sm font-semibold\">\r\n {{ t(\"load-error-title\") }}\r\n </div>\r\n <p class=\"m-0 text-sm text-red-600\">\r\n {{ error || t(\"load-error-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <mt-button\r\n [label]=\"t('retry')\"\r\n icon=\"arrow.refresh-cw-01\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"reloadLayout()\"\r\n />\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"grid gap-5\">\r\n @if (validationErrors().length > 0) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3.5 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"mb-2 text-sm font-semibold\">\r\n {{ t(\"validation-title\") }}\r\n </div>\r\n <ul class=\"m-0 list-disc ps-4\">\r\n @for (error of validationErrors(); track error) {\r\n <li>{{ error }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n\r\n <div class=\"grid grid-cols-1 gap-5 xl:grid-cols-2\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"min-h-[26rem] overflow-hidden bg-surface-0\"\r\n (contextmenu)=\"onAreaContextMenu($event, area, areaContextMenu)\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n >\r\n <ng-template #cardEnd>\r\n <mt-button\r\n [label]=\"t('add-group')\"\r\n icon=\"general.plus\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"openCreateGroupDialog(area)\"\r\n />\r\n </ng-template>\r\n\r\n <div\r\n class=\"workspace-area-body grid min-h-full content-start gap-2 bg-surface-50/60 p-5 pt-2\"\r\n [class.drag-active]=\"isDragging()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, areaItems(area).length)\"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"isAreaDropSlotDisabled(area, 0)\"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, 0),\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, 0))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n 0,\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n item of areaItems(area);\r\n track trackItem(item);\r\n let i = $index\r\n ) {\r\n @if (item.type === \"module\") {\r\n <div\r\n class=\"workspace-draggable-item flex min-h-11 cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, item, {\r\n type: 'area',\r\n area: area,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n item.name\r\n }}</span>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"workspace-group-card grid cursor-grab gap-3 rounded-md border border-surface-200 bg-surface-0 p-3 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"onGroupDragStart($event, item, area)\"\r\n (onDragEnd)=\"onDragEnd()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeGroupDrop($event, area, item.id)\"\r\n >\r\n <div\r\n class=\"group-header flex flex-wrap items-center gap-2 rounded-lg border-2 border-surface-200 bg-surface-50/80 px-2 py-2\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <mt-button\r\n class=\"expand-btn\"\r\n [icon]=\"\r\n isGroupExpanded(item.id)\r\n ? 'arrow.chevron-up'\r\n : 'arrow.chevron-down'\r\n \"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n (onClick)=\"toggleGroup(item.id)\"\r\n />\r\n <span\r\n class=\"group-drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n\r\n <span\r\n class=\"min-w-0 flex-1 truncate text-lg mx-1 font-semibold text-surface-600\"\r\n >{{ item.name }}</span\r\n >\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('rename-group')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"startRenameGroup(item)\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete-group')\"\r\n severity=\"danger\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"deleteGroup(item.id, $event)\"\r\n />\r\n </div>\r\n\r\n @if (isGroupExpanded(item.id)) {\r\n <div\r\n class=\"group-modules grid gap-2 border-t-2 border-dashed border-surface-300 pt-3\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0),\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n 0,\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n module of item.modules;\r\n track module.id;\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"workspace-draggable-item workspace-group-module-item ms-3 flex min-h-11 cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [pDraggable]=\"dropScope\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"\r\n onNativeGroupModuleDrop(\r\n $event,\r\n area,\r\n item.id,\r\n j\r\n )\r\n \"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, module, {\r\n type: 'group',\r\n area: area,\r\n groupId: item.id,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n module.name\r\n }}</span>\r\n <mt-button\r\n icon=\"general.minus\"\r\n [tooltip]=\"t('remove')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeModuleFromGroup(\r\n area,\r\n item.id,\r\n module.id\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, j + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1),\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n j + 1,\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, i + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isAreaDropSlotDisabled(area, i + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, i + 1),\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, i + 1))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n i + 1,\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n\r\n @if (areaItems(area).length === 0) {\r\n <div\r\n class=\"empty-area grid min-h-32 place-items-center rounded-lg border border-dashed border-surface-300 bg-surface-0/80 px-4 py-6 text-center text-sm text-surface-500\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, 0)\"\r\n >\r\n {{ t(\"empty-area\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (showHeader()) {\r\n <mt-page [title]=\"t('title')\" avatarIcon=\"layout.layout-grid-01\">\r\n <ng-template #headerEnd>\r\n @if (!autoSave()) {\r\n <div class=\"flex items-center\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <div class=\"w-full overflow-y-auto p-5\">\r\n @if (!autoSave()) {\r\n <div class=\"mb-4 flex justify-end\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".workspace-area-body{transition:background-color .18s ease,box-shadow .18s ease}.workspace-area-body.drag-active{cursor:grabbing}.workspace-draggable-item.p-draggable-dragging,.workspace-group-card.p-draggable-dragging{transform:scale(.985);box-shadow:0 12px 30px color-mix(in srgb,var(--p-text-color) 14%,transparent)}.drag-handle,.group-drag-handle{user-select:none;-webkit-user-select:none;touch-action:none;transition:transform .15s ease,border-color .15s ease,background-color .15s ease,color .15s ease}.drag-handle:active,.group-drag-handle:active{transform:scale(.96)}.workspace-area-body.drag-active .drag-handle,.workspace-area-body.drag-active .group-drag-handle{cursor:grabbing}.drop-slot{width:100%;height:.4rem;border:1px solid transparent;border-radius:9999px;background:transparent;opacity:0;transition:height .15s ease,border-color .15s ease,background-color .15s ease,box-shadow .15s ease,transform .15s ease,opacity .15s ease}.workspace-area-body.drag-active .drop-slot{height:.65rem;border-color:var(--p-surface-300);background:color-mix(in srgb,var(--p-surface-100) 55%,transparent);opacity:.28;transform:scaleX(.98)}.workspace-area-body.drag-active .drop-slot.drop-slot-disabled{opacity:0;height:.4rem;pointer-events:none}.empty-area.p-droppable-enter{border-color:var(--p-primary-400);background:var(--p-primary-50)}.drop-slot.p-droppable-enter,.workspace-area-body.drag-active .drop-slot:hover,.workspace-area-body.drag-active .drop-slot.drop-slot-active{height:2.5rem;border-width:1px;border-color:color-mix(in srgb,var(--p-primary-500) 55%,var(--p-surface-300));background:color-mix(in srgb,var(--p-primary-50) 45%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-300) 22%,transparent);opacity:1;transform:scaleX(1.01)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i2.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i3.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1440
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkspaceBuilder, isStandalone: true, selector: "mt-workspace-builder", inputs: { levelId: { classPropertyName: "levelId", publicName: "levelId", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, autoSave: { classPropertyName: "autoSave", publicName: "autoSave", isSignal: true, isRequired: false, transformFunction: null } }, providers: [DialogService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <ng-template #builderContent>\r\n @if (isLoadingLayout()) {\r\n <div class=\"flex flex-col gap-5 w-1/2 mx-auto h-full min-h-0\">\r\n <div class=\"flex flex-col gap-5 flex-1 min-h-0\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"flex-1 min-h-0 overflow-hidden bg-surface-0\"\r\n >\r\n <div\r\n class=\"grid min-h-full content-start gap-4 bg-surface-50/60 p-5 pt-4\"\r\n >\r\n @for (row of loadingSkeletonRows; track row) {\r\n <div\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 px-3 py-3 shadow-sm\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton size=\"2rem\" borderRadius=\"0.75rem\" />\r\n <div class=\"grid flex-1 gap-2\">\r\n <p-skeleton width=\"75%\" height=\"1rem\" />\r\n <p-skeleton width=\"45%\" height=\"0.8rem\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n } @else if (layoutError(); as error) {\r\n <div\r\n class=\"grid gap-4 rounded-xl border border-red-200 bg-red-50 px-5 py-6 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"grid gap-1\">\r\n <div class=\"text-sm font-semibold\">\r\n {{ t(\"load-error-title\") }}\r\n </div>\r\n <p class=\"m-0 text-sm text-red-600\">\r\n {{ error || t(\"load-error-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <mt-button\r\n [label]=\"t('retry')\"\r\n icon=\"arrow.refresh-cw-01\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"reloadLayout()\"\r\n />\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-5 h-full min-h-0\">\r\n @if (validationErrors().length > 0) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3.5 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"mb-2 text-sm font-semibold\">\r\n {{ t(\"validation-title\") }}\r\n </div>\r\n <ul class=\"m-0 list-disc ps-4\">\r\n @for (error of validationErrors(); track error) {\r\n <li>{{ error }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n\r\n <div class=\"flex flex-col gap-5 w-1/2 mx-auto flex-1 min-h-0\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"flex-1 min-h-0 overflow-hidden bg-surface-0\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n >\r\n <ng-template #cardEnd>\r\n <mt-button\r\n [label]=\"t('add-group')\"\r\n icon=\"general.plus\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"openCreateGroupDialog(area)\"\r\n />\r\n </ng-template>\r\n\r\n <div\r\n class=\"workspace-area-body grid h-full overflow-y-auto content-start gap-1 bg-surface-50/60 p-5 pt-2\"\r\n [class.drag-active]=\"isDragging()\"\r\n (dragover)=\"onAreaBodyDragOver($event)\"\r\n (dragleave)=\"onAreaBodyDragLeave($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, areaItems(area).length)\"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"isAreaDropSlotDisabled(area, 0)\"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, 0),\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, 0))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n 0,\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n item of areaItems(area);\r\n track trackItem(item);\r\n let i = $index\r\n ) {\r\n @if (item.type === \"module\") {\r\n <div\r\n class=\"workspace-draggable-item flex cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, item, {\r\n type: 'area',\r\n area: area,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n item.name\r\n }}</span>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"workspace-group-card grid cursor-grab gap-3 rounded-md border border-surface-200 bg-surface-0 p-3 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"onGroupDragStart($event, item, area)\"\r\n (onDragEnd)=\"onDragEnd()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeGroupDrop($event, area, item.id)\"\r\n >\r\n <div\r\n class=\"group-header flex flex-wrap items-center gap-2 rounded-lg border-2 border-surface-200 bg-surface-50/80 px-2 py-2\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <mt-button\r\n class=\"expand-btn\"\r\n [icon]=\"\r\n isGroupExpanded(item.id)\r\n ? 'arrow.chevron-up'\r\n : 'arrow.chevron-down'\r\n \"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n (onClick)=\"toggleGroup(item.id)\"\r\n />\r\n <span\r\n class=\"group-drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n\r\n <span\r\n class=\"min-w-0 flex-1 truncate text-lg mx-1 font-semibold text-surface-600\"\r\n >{{ item.name }}</span\r\n >\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('rename-group')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"startRenameGroup(item)\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete-group')\"\r\n severity=\"danger\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"deleteGroup(item.id, $event)\"\r\n />\r\n </div>\r\n\r\n @if (isGroupExpanded(item.id)) {\r\n <div\r\n class=\"group-modules grid gap-2 border-t-2 border-dashed border-surface-300 pt-3\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0),\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n 0,\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n module of item.modules;\r\n track module.id;\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"workspace-draggable-item workspace-group-module-item ms-3 flex cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [pDraggable]=\"dropScope\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"\r\n onNativeGroupModuleDrop(\r\n $event,\r\n area,\r\n item.id,\r\n j\r\n )\r\n \"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, module, {\r\n type: 'group',\r\n area: area,\r\n groupId: item.id,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n module.name\r\n }}</span>\r\n <mt-button\r\n icon=\"general.minus\"\r\n [tooltip]=\"t('remove')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeModuleFromGroup(\r\n area,\r\n item.id,\r\n module.id\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, j + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1),\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n j + 1,\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, i + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isAreaDropSlotDisabled(area, i + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, i + 1),\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, i + 1))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n i + 1,\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n\r\n @if (areaItems(area).length === 0) {\r\n <div\r\n class=\"empty-area grid min-h-32 place-items-center rounded-lg border border-dashed border-surface-300 bg-surface-0/80 px-4 py-6 text-center text-sm text-surface-500\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, 0)\"\r\n >\r\n {{ t(\"empty-area\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (showHeader()) {\r\n <mt-page [title]=\"t('title')\" avatarIcon=\"layout.layout-grid-01\">\r\n <ng-template #headerEnd>\r\n @if (!autoSave()) {\r\n <div class=\"flex items-center\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <div class=\"w-full h-full flex flex-col overflow-hidden p-5\">\r\n @if (!autoSave()) {\r\n <div class=\"mb-4 flex justify-end\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".workspace-area-body{transition:background-color .18s ease,box-shadow .18s ease}.workspace-area-body.drag-active{cursor:grabbing}.workspace-draggable-item.p-draggable-dragging,.workspace-group-card.p-draggable-dragging{transform:scale(.985);box-shadow:0 12px 30px color-mix(in srgb,var(--p-text-color) 14%,transparent)}.drag-handle,.group-drag-handle{user-select:none;-webkit-user-select:none;touch-action:none;transition:transform .15s ease,border-color .15s ease,background-color .15s ease,color .15s ease}.drag-handle:active,.group-drag-handle:active{transform:scale(.96)}.workspace-area-body.drag-active .drag-handle,.workspace-area-body.drag-active .group-drag-handle{cursor:grabbing}.drop-slot{width:100%;height:.4rem;border:1px solid transparent;border-radius:9999px;background:transparent;opacity:0;transition:height .15s ease,border-color .15s ease,background-color .15s ease,box-shadow .15s ease,transform .15s ease,opacity .15s ease}.workspace-area-body.drag-active .drop-slot{height:.65rem;border-color:var(--p-surface-300);background:color-mix(in srgb,var(--p-surface-100) 55%,transparent);opacity:.28;transform:scaleX(.98)}.workspace-area-body.drag-active .drop-slot.drop-slot-disabled{opacity:0;height:.4rem;pointer-events:none}.empty-area.p-droppable-enter{border-color:var(--p-primary-400);background:var(--p-primary-50)}.drop-slot.p-droppable-enter,.workspace-area-body.drag-active .drop-slot:hover,.workspace-area-body.drag-active .drop-slot.drop-slot-active{height:2.5rem;border-width:1px;border-color:color-mix(in srgb,var(--p-primary-500) 55%,var(--p-surface-300));background:color-mix(in srgb,var(--p-primary-50) 45%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-300) 22%,transparent);opacity:1;transform:scaleX(1.01)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i2.Droppable, selector: "[pDroppable]", inputs: ["pDroppable", "pDroppableDisabled", "dropEffect"], outputs: ["onDragEnter", "onDragLeave", "onDrop"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i3.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1476
1441
|
}
|
|
1477
1442
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkspaceBuilder, decorators: [{
|
|
1478
1443
|
type: Component,
|
|
@@ -1484,9 +1449,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1484
1449
|
Icon,
|
|
1485
1450
|
Page,
|
|
1486
1451
|
Card,
|
|
1487
|
-
ContextMenuModule,
|
|
1488
1452
|
SkeletonModule,
|
|
1489
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DialogService], template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <p-contextMenu\r\n #areaContextMenu\r\n [model]=\"areaContextItems()\"\r\n appendTo=\"body\"\r\n />\r\n\r\n <ng-template #builderContent>\r\n @if (isLoadingLayout()) {\r\n <div class=\"grid gap-5\">\r\n <div class=\"grid grid-cols-1 gap-5 xl:grid-cols-2\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"min-h-[26rem] overflow-hidden bg-surface-0\"\r\n >\r\n <div\r\n class=\"grid min-h-full content-start gap-4 bg-surface-50/60 p-5 pt-4\"\r\n >\r\n @for (row of loadingSkeletonRows; track row) {\r\n <div\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 px-3 py-3 shadow-sm\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton size=\"2rem\" borderRadius=\"0.75rem\" />\r\n <div class=\"grid flex-1 gap-2\">\r\n <p-skeleton width=\"75%\" height=\"1rem\" />\r\n <p-skeleton width=\"45%\" height=\"0.8rem\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n } @else if (layoutError(); as error) {\r\n <div\r\n class=\"grid gap-4 rounded-xl border border-red-200 bg-red-50 px-5 py-6 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"grid gap-1\">\r\n <div class=\"text-sm font-semibold\">\r\n {{ t(\"load-error-title\") }}\r\n </div>\r\n <p class=\"m-0 text-sm text-red-600\">\r\n {{ error || t(\"load-error-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <mt-button\r\n [label]=\"t('retry')\"\r\n icon=\"arrow.refresh-cw-01\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"reloadLayout()\"\r\n />\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"grid gap-5\">\r\n @if (validationErrors().length > 0) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3.5 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"mb-2 text-sm font-semibold\">\r\n {{ t(\"validation-title\") }}\r\n </div>\r\n <ul class=\"m-0 list-disc ps-4\">\r\n @for (error of validationErrors(); track error) {\r\n <li>{{ error }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n\r\n <div class=\"grid grid-cols-1 gap-5 xl:grid-cols-2\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"min-h-[26rem] overflow-hidden bg-surface-0\"\r\n (contextmenu)=\"onAreaContextMenu($event, area, areaContextMenu)\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n >\r\n <ng-template #cardEnd>\r\n <mt-button\r\n [label]=\"t('add-group')\"\r\n icon=\"general.plus\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"openCreateGroupDialog(area)\"\r\n />\r\n </ng-template>\r\n\r\n <div\r\n class=\"workspace-area-body grid min-h-full content-start gap-2 bg-surface-50/60 p-5 pt-2\"\r\n [class.drag-active]=\"isDragging()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, areaItems(area).length)\"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"isAreaDropSlotDisabled(area, 0)\"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, 0),\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, 0))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n 0,\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n item of areaItems(area);\r\n track trackItem(item);\r\n let i = $index\r\n ) {\r\n @if (item.type === \"module\") {\r\n <div\r\n class=\"workspace-draggable-item flex min-h-11 cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, item, {\r\n type: 'area',\r\n area: area,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n item.name\r\n }}</span>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"workspace-group-card grid cursor-grab gap-3 rounded-md border border-surface-200 bg-surface-0 p-3 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"onGroupDragStart($event, item, area)\"\r\n (onDragEnd)=\"onDragEnd()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeGroupDrop($event, area, item.id)\"\r\n >\r\n <div\r\n class=\"group-header flex flex-wrap items-center gap-2 rounded-lg border-2 border-surface-200 bg-surface-50/80 px-2 py-2\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <mt-button\r\n class=\"expand-btn\"\r\n [icon]=\"\r\n isGroupExpanded(item.id)\r\n ? 'arrow.chevron-up'\r\n : 'arrow.chevron-down'\r\n \"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n (onClick)=\"toggleGroup(item.id)\"\r\n />\r\n <span\r\n class=\"group-drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n\r\n <span\r\n class=\"min-w-0 flex-1 truncate text-lg mx-1 font-semibold text-surface-600\"\r\n >{{ item.name }}</span\r\n >\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('rename-group')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"startRenameGroup(item)\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete-group')\"\r\n severity=\"danger\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"deleteGroup(item.id, $event)\"\r\n />\r\n </div>\r\n\r\n @if (isGroupExpanded(item.id)) {\r\n <div\r\n class=\"group-modules grid gap-2 border-t-2 border-dashed border-surface-300 pt-3\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0),\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n 0,\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n module of item.modules;\r\n track module.id;\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"workspace-draggable-item workspace-group-module-item ms-3 flex min-h-11 cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [pDraggable]=\"dropScope\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"\r\n onNativeGroupModuleDrop(\r\n $event,\r\n area,\r\n item.id,\r\n j\r\n )\r\n \"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, module, {\r\n type: 'group',\r\n area: area,\r\n groupId: item.id,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n module.name\r\n }}</span>\r\n <mt-button\r\n icon=\"general.minus\"\r\n [tooltip]=\"t('remove')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeModuleFromGroup(\r\n area,\r\n item.id,\r\n module.id\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, j + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1),\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n j + 1,\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, i + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isAreaDropSlotDisabled(area, i + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, i + 1),\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, i + 1))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n i + 1,\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n\r\n @if (areaItems(area).length === 0) {\r\n <div\r\n class=\"empty-area grid min-h-32 place-items-center rounded-lg border border-dashed border-surface-300 bg-surface-0/80 px-4 py-6 text-center text-sm text-surface-500\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, 0)\"\r\n >\r\n {{ t(\"empty-area\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (showHeader()) {\r\n <mt-page [title]=\"t('title')\" avatarIcon=\"layout.layout-grid-01\">\r\n <ng-template #headerEnd>\r\n @if (!autoSave()) {\r\n <div class=\"flex items-center\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <div class=\"w-full overflow-y-auto p-5\">\r\n @if (!autoSave()) {\r\n <div class=\"mb-4 flex justify-end\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".workspace-area-body{transition:background-color .18s ease,box-shadow .18s ease}.workspace-area-body.drag-active{cursor:grabbing}.workspace-draggable-item.p-draggable-dragging,.workspace-group-card.p-draggable-dragging{transform:scale(.985);box-shadow:0 12px 30px color-mix(in srgb,var(--p-text-color) 14%,transparent)}.drag-handle,.group-drag-handle{user-select:none;-webkit-user-select:none;touch-action:none;transition:transform .15s ease,border-color .15s ease,background-color .15s ease,color .15s ease}.drag-handle:active,.group-drag-handle:active{transform:scale(.96)}.workspace-area-body.drag-active .drag-handle,.workspace-area-body.drag-active .group-drag-handle{cursor:grabbing}.drop-slot{width:100%;height:.4rem;border:1px solid transparent;border-radius:9999px;background:transparent;opacity:0;transition:height .15s ease,border-color .15s ease,background-color .15s ease,box-shadow .15s ease,transform .15s ease,opacity .15s ease}.workspace-area-body.drag-active .drop-slot{height:.65rem;border-color:var(--p-surface-300);background:color-mix(in srgb,var(--p-surface-100) 55%,transparent);opacity:.28;transform:scaleX(.98)}.workspace-area-body.drag-active .drop-slot.drop-slot-disabled{opacity:0;height:.4rem;pointer-events:none}.empty-area.p-droppable-enter{border-color:var(--p-primary-400);background:var(--p-primary-50)}.drop-slot.p-droppable-enter,.workspace-area-body.drag-active .drop-slot:hover,.workspace-area-body.drag-active .drop-slot.drop-slot-active{height:2.5rem;border-width:1px;border-color:color-mix(in srgb,var(--p-primary-500) 55%,var(--p-surface-300));background:color-mix(in srgb,var(--p-primary-50) 45%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-300) 22%,transparent);opacity:1;transform:scaleX(1.01)}\n"] }]
|
|
1453
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [DialogService], template: "<ng-container *transloco=\"let t; prefix: 'workspace-builder'\">\r\n <ng-template #builderContent>\r\n @if (isLoadingLayout()) {\r\n <div class=\"flex flex-col gap-5 w-1/2 mx-auto h-full min-h-0\">\r\n <div class=\"flex flex-col gap-5 flex-1 min-h-0\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"flex-1 min-h-0 overflow-hidden bg-surface-0\"\r\n >\r\n <div\r\n class=\"grid min-h-full content-start gap-4 bg-surface-50/60 p-5 pt-4\"\r\n >\r\n @for (row of loadingSkeletonRows; track row) {\r\n <div\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 px-3 py-3 shadow-sm\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <p-skeleton size=\"2rem\" borderRadius=\"0.75rem\" />\r\n <div class=\"grid flex-1 gap-2\">\r\n <p-skeleton width=\"75%\" height=\"1rem\" />\r\n <p-skeleton width=\"45%\" height=\"0.8rem\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n } @else if (layoutError(); as error) {\r\n <div\r\n class=\"grid gap-4 rounded-xl border border-red-200 bg-red-50 px-5 py-6 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"grid gap-1\">\r\n <div class=\"text-sm font-semibold\">\r\n {{ t(\"load-error-title\") }}\r\n </div>\r\n <p class=\"m-0 text-sm text-red-600\">\r\n {{ error || t(\"load-error-description\") }}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <mt-button\r\n [label]=\"t('retry')\"\r\n icon=\"arrow.refresh-cw-01\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"reloadLayout()\"\r\n />\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-5 h-full min-h-0\">\r\n @if (validationErrors().length > 0) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-4 py-3.5 text-red-700 shadow-sm\"\r\n >\r\n <div class=\"mb-2 text-sm font-semibold\">\r\n {{ t(\"validation-title\") }}\r\n </div>\r\n <ul class=\"m-0 list-disc ps-4\">\r\n @for (error of validationErrors(); track error) {\r\n <li>{{ error }}</li>\r\n }\r\n </ul>\r\n </div>\r\n }\r\n\r\n <div class=\"flex flex-col gap-5 w-1/2 mx-auto flex-1 min-h-0\">\r\n @for (area of areas; track area) {\r\n <mt-card\r\n [title]=\"t(area)\"\r\n [paddingless]=\"true\"\r\n class=\"flex-1 min-h-0 overflow-hidden bg-surface-0\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n >\r\n <ng-template #cardEnd>\r\n <mt-button\r\n [label]=\"t('add-group')\"\r\n icon=\"general.plus\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"openCreateGroupDialog(area)\"\r\n />\r\n </ng-template>\r\n\r\n <div\r\n class=\"workspace-area-body grid h-full overflow-y-auto content-start gap-1 bg-surface-50/60 p-5 pt-2\"\r\n [class.drag-active]=\"isDragging()\"\r\n (dragover)=\"onAreaBodyDragOver($event)\"\r\n (dragleave)=\"onAreaBodyDragLeave($event)\"\r\n (drop)=\"onNativeAreaDrop($event, area)\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, areaItems(area).length)\"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"isAreaDropSlotDisabled(area, 0)\"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, 0),\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, 0))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n 0,\r\n isAreaDropSlotDisabled(area, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n item of areaItems(area);\r\n track trackItem(item);\r\n let i = $index\r\n ) {\r\n @if (item.type === \"module\") {\r\n <div\r\n class=\"workspace-draggable-item flex cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, item, {\r\n type: 'area',\r\n area: area,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n item.name\r\n }}</span>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"workspace-group-card grid cursor-grab gap-3 rounded-md border border-surface-200 bg-surface-0 p-3 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [attr.data-area]=\"area\"\r\n [attr.data-item-index]=\"i\"\r\n [pDraggable]=\"dropScope\"\r\n (onDragStart)=\"onGroupDragStart($event, item, area)\"\r\n (onDragEnd)=\"onDragEnd()\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"onNativeGroupDrop($event, area, item.id)\"\r\n >\r\n <div\r\n class=\"group-header flex flex-wrap items-center gap-2 rounded-lg border-2 border-surface-200 bg-surface-50/80 px-2 py-2\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <mt-button\r\n class=\"expand-btn\"\r\n [icon]=\"\r\n isGroupExpanded(item.id)\r\n ? 'arrow.chevron-up'\r\n : 'arrow.chevron-down'\r\n \"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n (onClick)=\"toggleGroup(item.id)\"\r\n />\r\n <span\r\n class=\"group-drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n\r\n <span\r\n class=\"min-w-0 flex-1 truncate text-lg mx-1 font-semibold text-surface-600\"\r\n >{{ item.name }}</span\r\n >\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('rename-group')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"startRenameGroup(item)\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('delete-group')\"\r\n severity=\"danger\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"deleteGroup(item.id, $event)\"\r\n />\r\n </div>\r\n\r\n @if (isGroupExpanded(item.id)) {\r\n <div\r\n class=\"group-modules grid gap-2 border-t-2 border-dashed border-surface-300 pt-3\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n item.modules.length\r\n )\r\n \"\r\n >\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, 0)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0),\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, 0)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n 0,\r\n isGroupDropSlotDisabled(area, item.id, 0)\r\n )\r\n \"\r\n ></div>\r\n\r\n @for (\r\n module of item.modules;\r\n track module.id;\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"workspace-draggable-item workspace-group-module-item ms-3 flex cursor-grab items-center gap-3 rounded-lg border border-surface-200 bg-surface-0 px-3 py-2.5 transition-all duration-150 hover:-translate-y-0.5 hover:border-surface-300 hover:shadow-sm active:cursor-grabbing\"\r\n [pDraggable]=\"dropScope\"\r\n (dragover)=\"allowNativeDrop($event)\"\r\n (drop)=\"\r\n onNativeGroupModuleDrop(\r\n $event,\r\n area,\r\n item.id,\r\n j\r\n )\r\n \"\r\n (onDragStart)=\"\r\n onModuleDragStart($event, module, {\r\n type: 'group',\r\n area: area,\r\n groupId: item.id,\r\n })\r\n \"\r\n (onDragEnd)=\"onDragEnd()\"\r\n >\r\n <span\r\n class=\"drag-handle flex size-8 shrink-0 items-center justify-center text-surface-500\"\r\n draggable=\"false\"\r\n >\r\n <mt-icon\r\n class=\"pointer-events-none text-xl text-primary\"\r\n icon=\"general.menu-05\"\r\n />\r\n </span>\r\n <span class=\"min-w-0 flex-1 truncate py-1.5\">{{\r\n module.name\r\n }}</span>\r\n <mt-button\r\n icon=\"general.minus\"\r\n [tooltip]=\"t('remove')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"\r\n removeModuleFromGroup(\r\n area,\r\n item.id,\r\n module.id\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() ===\r\n groupDropSlotKey(area, item.id, j + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1),\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave(\r\n $event,\r\n groupDropSlotKey(area, item.id, j + 1)\r\n )\r\n \"\r\n (onDrop)=\"\r\n onDropToGroup(\r\n $event,\r\n area,\r\n item.id,\r\n j + 1,\r\n isGroupDropSlotDisabled(area, item.id, j + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"drop-slot\"\r\n [class.drop-slot-active]=\"\r\n activeDropSlotKey() === areaDropSlotKey(area, i + 1)\r\n \"\r\n [class.drop-slot-disabled]=\"\r\n isAreaDropSlotDisabled(area, i + 1)\r\n \"\r\n [pDroppable]=\"dropScope\"\r\n (dragover)=\"\r\n onDropSlotDragOver(\r\n $event,\r\n areaDropSlotKey(area, i + 1),\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n (dragleave)=\"\r\n onDropSlotDragLeave($event, areaDropSlotKey(area, i + 1))\r\n \"\r\n (onDrop)=\"\r\n onDropToArea(\r\n $event,\r\n area,\r\n i + 1,\r\n isAreaDropSlotDisabled(area, i + 1)\r\n )\r\n \"\r\n ></div>\r\n }\r\n\r\n @if (areaItems(area).length === 0) {\r\n <div\r\n class=\"empty-area grid min-h-32 place-items-center rounded-lg border border-dashed border-surface-300 bg-surface-0/80 px-4 py-6 text-center text-sm text-surface-500\"\r\n [pDroppable]=\"dropScope\"\r\n (onDrop)=\"onDropToArea($event, area, 0)\"\r\n >\r\n {{ t(\"empty-area\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n @if (showHeader()) {\r\n <mt-page [title]=\"t('title')\" avatarIcon=\"layout.layout-grid-01\">\r\n <ng-template #headerEnd>\r\n @if (!autoSave()) {\r\n <div class=\"flex items-center\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n </ng-template>\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <div class=\"w-full h-full flex flex-col overflow-hidden p-5\">\r\n @if (!autoSave()) {\r\n <div class=\"mb-4 flex justify-end\">\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n [loading]=\"isSavingLayout()\"\r\n [disabled]=\"\r\n isLoadingLayout() ||\r\n !!layoutError() ||\r\n isSavingLayout() ||\r\n validationErrors().length > 0\r\n \"\r\n (onClick)=\"onSaveClick()\"\r\n />\r\n </div>\r\n }\r\n\r\n <ng-container [ngTemplateOutlet]=\"builderContent\" />\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".workspace-area-body{transition:background-color .18s ease,box-shadow .18s ease}.workspace-area-body.drag-active{cursor:grabbing}.workspace-draggable-item.p-draggable-dragging,.workspace-group-card.p-draggable-dragging{transform:scale(.985);box-shadow:0 12px 30px color-mix(in srgb,var(--p-text-color) 14%,transparent)}.drag-handle,.group-drag-handle{user-select:none;-webkit-user-select:none;touch-action:none;transition:transform .15s ease,border-color .15s ease,background-color .15s ease,color .15s ease}.drag-handle:active,.group-drag-handle:active{transform:scale(.96)}.workspace-area-body.drag-active .drag-handle,.workspace-area-body.drag-active .group-drag-handle{cursor:grabbing}.drop-slot{width:100%;height:.4rem;border:1px solid transparent;border-radius:9999px;background:transparent;opacity:0;transition:height .15s ease,border-color .15s ease,background-color .15s ease,box-shadow .15s ease,transform .15s ease,opacity .15s ease}.workspace-area-body.drag-active .drop-slot{height:.65rem;border-color:var(--p-surface-300);background:color-mix(in srgb,var(--p-surface-100) 55%,transparent);opacity:.28;transform:scaleX(.98)}.workspace-area-body.drag-active .drop-slot.drop-slot-disabled{opacity:0;height:.4rem;pointer-events:none}.empty-area.p-droppable-enter{border-color:var(--p-primary-400);background:var(--p-primary-50)}.drop-slot.p-droppable-enter,.workspace-area-body.drag-active .drop-slot:hover,.workspace-area-body.drag-active .drop-slot.drop-slot-active{height:2.5rem;border-width:1px;border-color:color-mix(in srgb,var(--p-primary-500) 55%,var(--p-surface-300));background:color-mix(in srgb,var(--p-primary-50) 45%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--p-primary-300) 22%,transparent);opacity:1;transform:scaleX(1.01)}\n"] }]
|
|
1490
1454
|
}], ctorParameters: () => [], propDecorators: { levelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelId", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], autoSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSave", required: false }] }] } });
|
|
1491
1455
|
|
|
1492
1456
|
/**
|