@masterteam/workspace-builder 0.0.9 → 0.0.10
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 +2 -0
- package/assets/i18n/en.json +2 -0
- package/assets/workspace-builder.css +1 -1
- package/fesm2022/masterteam-workspace-builder.mjs +134 -73
- package/fesm2022/masterteam-workspace-builder.mjs.map +1 -1
- package/package.json +2 -2
- package/types/masterteam-workspace-builder.d.ts +14 -13
|
@@ -1,32 +1,29 @@
|
|
|
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, input, signal, Component, booleanAttribute, effect, ChangeDetectionStrategy } from '@angular/core';
|
|
4
|
+
import { inject, Injectable, computed, input, signal, linkedSignal, Component, booleanAttribute, effect, ChangeDetectionStrategy } from '@angular/core';
|
|
5
5
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
6
|
-
import
|
|
7
|
-
import { TranslocoModule, TranslocoService, TranslocoDirective } from '@jsverse/transloco';
|
|
8
|
-
import * as i1 from '@angular/forms';
|
|
9
|
-
import { FormsModule } from '@angular/forms';
|
|
6
|
+
import { TranslocoService, TranslocoDirective } from '@jsverse/transloco';
|
|
10
7
|
import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
11
8
|
import { DynamicDialogConfig, ModalRef, DialogService } from '@masterteam/components/dialog';
|
|
12
9
|
import { ModalService } from '@masterteam/components/modal';
|
|
13
10
|
import { Page } from '@masterteam/components/page';
|
|
14
11
|
import { Card } from '@masterteam/components/card';
|
|
15
|
-
import { TextField } from '@masterteam/components/text-field';
|
|
16
12
|
import { ToastService } from '@masterteam/components/toast';
|
|
17
|
-
import * as
|
|
13
|
+
import * as i3 from 'primeng/contextmenu';
|
|
18
14
|
import { ContextMenuModule } from 'primeng/contextmenu';
|
|
19
|
-
import * as
|
|
15
|
+
import * as i2 from 'primeng/dragdrop';
|
|
20
16
|
import { DragDropModule } from 'primeng/dragdrop';
|
|
21
|
-
import * as
|
|
17
|
+
import * as i4 from 'primeng/skeleton';
|
|
22
18
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
23
19
|
import { finalize } from 'rxjs';
|
|
24
20
|
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
25
21
|
import { HttpClient } from '@angular/common/http';
|
|
26
|
-
import { CrudStateBase, handleApiRequest } from '@masterteam/components';
|
|
22
|
+
import { CrudStateBase, handleApiRequest, ValidatorConfig } from '@masterteam/components';
|
|
23
|
+
import * as i1 from '@angular/forms';
|
|
24
|
+
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
27
25
|
import { Button } from '@masterteam/components/button';
|
|
28
|
-
import
|
|
29
|
-
import { InputTextModule } from 'primeng/inputtext';
|
|
26
|
+
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
30
27
|
import { Icon } from '@masterteam/icons';
|
|
31
28
|
|
|
32
29
|
class SetWorkspaceBuilderLevelId {
|
|
@@ -117,6 +114,17 @@ function normalizeName(value) {
|
|
|
117
114
|
}
|
|
118
115
|
return '';
|
|
119
116
|
}
|
|
117
|
+
function extractLocalizedTitle(value) {
|
|
118
|
+
if (value && typeof value === 'object') {
|
|
119
|
+
const loc = value;
|
|
120
|
+
return {
|
|
121
|
+
en: typeof loc['en'] === 'string' ? loc['en'] : '',
|
|
122
|
+
ar: typeof loc['ar'] === 'string' ? loc['ar'] : '',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const str = typeof value === 'string' ? value : '';
|
|
126
|
+
return { en: str, ar: str };
|
|
127
|
+
}
|
|
120
128
|
function createEmptyLayout(levelId = 0) {
|
|
121
129
|
return {
|
|
122
130
|
levelId,
|
|
@@ -137,6 +145,7 @@ function cloneItem(item) {
|
|
|
137
145
|
type: 'group',
|
|
138
146
|
id: item.id,
|
|
139
147
|
name: item.name,
|
|
148
|
+
localizedName: { ...item.localizedName },
|
|
140
149
|
order: item.order,
|
|
141
150
|
modules: item.modules.map((module) => ({
|
|
142
151
|
id: module.id,
|
|
@@ -172,6 +181,7 @@ function normalizeAreaItems(items) {
|
|
|
172
181
|
type: 'group',
|
|
173
182
|
id: String(item?.id ?? ''),
|
|
174
183
|
name: normalizeName(item?.name),
|
|
184
|
+
localizedName: extractLocalizedTitle(item?.name),
|
|
175
185
|
order: index + 1,
|
|
176
186
|
modules: normalizeGroupModules(item?.modules ?? []),
|
|
177
187
|
};
|
|
@@ -289,7 +299,8 @@ function insertGroupIntoLayout(layout, groupId, title, area, order) {
|
|
|
289
299
|
const group = {
|
|
290
300
|
type: 'group',
|
|
291
301
|
id: groupId,
|
|
292
|
-
name: title,
|
|
302
|
+
name: title.en || title.ar,
|
|
303
|
+
localizedName: { ...title },
|
|
293
304
|
order: 0,
|
|
294
305
|
modules: [],
|
|
295
306
|
};
|
|
@@ -301,7 +312,8 @@ function renameGroupInLayout(layout, groupId, title) {
|
|
|
301
312
|
for (const area of AREAS) {
|
|
302
313
|
const group = next[area].find((item) => item.type === 'group' && item.id === groupId);
|
|
303
314
|
if (group) {
|
|
304
|
-
group.name = title;
|
|
315
|
+
group.name = title.en || title.ar;
|
|
316
|
+
group.localizedName = { ...title };
|
|
305
317
|
break;
|
|
306
318
|
}
|
|
307
319
|
}
|
|
@@ -662,41 +674,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
662
674
|
|
|
663
675
|
class WorkspaceBuilderCreateGroupDialog {
|
|
664
676
|
area = input(null, ...(ngDevMode ? [{ debugName: "area" }] : []));
|
|
665
|
-
title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
666
677
|
modal = inject(ModalService);
|
|
667
678
|
config = inject(DynamicDialogConfig, { optional: true });
|
|
668
679
|
ref = inject(ModalRef);
|
|
680
|
+
facade = inject(WorkspaceBuilderFacade);
|
|
681
|
+
ts = inject(ToastService);
|
|
682
|
+
translocoService = inject(TranslocoService);
|
|
683
|
+
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
684
|
+
formControl = new FormControl(null);
|
|
685
|
+
dynamicFormConfig = linkedSignal(() => ({
|
|
686
|
+
sections: [
|
|
687
|
+
{
|
|
688
|
+
key: '',
|
|
689
|
+
label: '',
|
|
690
|
+
type: 'header',
|
|
691
|
+
order: 1,
|
|
692
|
+
fields: [
|
|
693
|
+
{
|
|
694
|
+
key: 'title.en',
|
|
695
|
+
label: this.translocoService.translate('workspace-builder.title-en'),
|
|
696
|
+
placeholder: this.translocoService.translate('workspace-builder.title-en'),
|
|
697
|
+
validators: [ValidatorConfig.required()],
|
|
698
|
+
order: 1,
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
key: 'title.ar',
|
|
702
|
+
label: this.translocoService.translate('workspace-builder.title-ar'),
|
|
703
|
+
placeholder: this.translocoService.translate('workspace-builder.title-ar'),
|
|
704
|
+
validators: [ValidatorConfig.required()],
|
|
705
|
+
order: 2,
|
|
706
|
+
},
|
|
707
|
+
],
|
|
708
|
+
},
|
|
709
|
+
],
|
|
710
|
+
}), ...(ngDevMode ? [{ debugName: "dynamicFormConfig" }] : []));
|
|
711
|
+
get isEditMode() {
|
|
712
|
+
return !!this.dialogData.groupId;
|
|
713
|
+
}
|
|
714
|
+
get dialogData() {
|
|
715
|
+
return (this.config?.data ?? {});
|
|
716
|
+
}
|
|
717
|
+
constructor() {
|
|
718
|
+
const initial = this.dialogData.localizedName;
|
|
719
|
+
if (initial) {
|
|
720
|
+
this.formControl.patchValue({
|
|
721
|
+
title: {
|
|
722
|
+
en: initial.en ?? '',
|
|
723
|
+
ar: initial.ar ?? '',
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
669
728
|
resolvedArea() {
|
|
670
|
-
return
|
|
671
|
-
this.config?.data?.area ??
|
|
672
|
-
'main');
|
|
729
|
+
return this.area() ?? this.dialogData.area ?? 'main';
|
|
673
730
|
}
|
|
674
731
|
submit() {
|
|
675
|
-
const
|
|
676
|
-
|
|
732
|
+
const value = this.formControl.value;
|
|
733
|
+
const en = (value?.title?.en ?? '').trim();
|
|
734
|
+
const ar = (value?.title?.ar ?? '').trim();
|
|
735
|
+
if (!en && !ar) {
|
|
677
736
|
return;
|
|
678
737
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
738
|
+
const title = { en, ar };
|
|
739
|
+
this.isSaving.set(true);
|
|
740
|
+
if (this.isEditMode) {
|
|
741
|
+
this.facade.renameGroup(this.dialogData.groupId, title).subscribe({
|
|
742
|
+
next: () => {
|
|
743
|
+
this.ts.success(this.translocoService.translate('workspace-builder.group-update-success'));
|
|
744
|
+
this.facade.getLayout();
|
|
745
|
+
this.ref.close(true);
|
|
746
|
+
},
|
|
747
|
+
error: () => {
|
|
748
|
+
this.isSaving.set(false);
|
|
749
|
+
this.ts.error(this.translocoService.translate('workspace-builder.group-update-error'));
|
|
750
|
+
},
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
const area = this.resolvedArea();
|
|
755
|
+
const order = this.dialogData.order;
|
|
756
|
+
this.facade.createGroup(title, area, order).subscribe({
|
|
757
|
+
next: () => {
|
|
758
|
+
this.ts.success(this.translocoService.translate('workspace-builder.group-create-success'));
|
|
759
|
+
this.facade.getLayout();
|
|
760
|
+
this.ref.close(true);
|
|
761
|
+
},
|
|
762
|
+
error: () => {
|
|
763
|
+
this.isSaving.set(false);
|
|
764
|
+
this.ts.error(this.translocoService.translate('workspace-builder.group-create-error'));
|
|
765
|
+
},
|
|
766
|
+
});
|
|
767
|
+
}
|
|
683
768
|
}
|
|
684
769
|
cancel() {
|
|
685
770
|
this.ref.close(null);
|
|
686
771
|
}
|
|
687
772
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkspaceBuilderCreateGroupDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
688
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: WorkspaceBuilderCreateGroupDialog, isStandalone: true, selector: "mt-workspace-builder-create-group-dialog", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null } }, 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 <
|
|
773
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: WorkspaceBuilderCreateGroupDialog, isStandalone: true, selector: "mt-workspace-builder-create-group-dialog", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null } }, 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"] }] });
|
|
689
774
|
}
|
|
690
775
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkspaceBuilderCreateGroupDialog, decorators: [{
|
|
691
776
|
type: Component,
|
|
692
777
|
args: [{ selector: 'mt-workspace-builder-create-group-dialog', standalone: true, imports: [
|
|
693
778
|
CommonModule,
|
|
694
|
-
|
|
695
|
-
InputTextModule,
|
|
779
|
+
ReactiveFormsModule,
|
|
696
780
|
Button,
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
781
|
+
DynamicForm,
|
|
782
|
+
TranslocoDirective,
|
|
783
|
+
], 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: () => [], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }] } });
|
|
700
785
|
|
|
701
786
|
const DRAG_PAYLOAD_MIME = 'application/x-workspace-builder';
|
|
702
787
|
class WorkspaceBuilder {
|
|
@@ -707,8 +792,6 @@ class WorkspaceBuilder {
|
|
|
707
792
|
dropScope = 'workspace-builder-item';
|
|
708
793
|
loadingSkeletonRows = [0, 1, 2, 3];
|
|
709
794
|
createGroupArea = signal('main', ...(ngDevMode ? [{ debugName: "createGroupArea" }] : []));
|
|
710
|
-
editingGroupId = signal(null, ...(ngDevMode ? [{ debugName: "editingGroupId" }] : []));
|
|
711
|
-
editingGroupTitle = signal('', ...(ngDevMode ? [{ debugName: "editingGroupTitle" }] : []));
|
|
712
795
|
isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
|
|
713
796
|
activeDropSlotKey = signal(null, ...(ngDevMode ? [{ debugName: "activeDropSlotKey" }] : []));
|
|
714
797
|
expandedGroups = signal({}, ...(ngDevMode ? [{ debugName: "expandedGroups" }] : []));
|
|
@@ -948,54 +1031,33 @@ class WorkspaceBuilder {
|
|
|
948
1031
|
contextMenu.show(event);
|
|
949
1032
|
}
|
|
950
1033
|
openCreateGroupDialog(area) {
|
|
951
|
-
const
|
|
1034
|
+
const order = this.layout()[area].length + 1;
|
|
1035
|
+
const data = { area, order };
|
|
1036
|
+
this.modal.openModal(WorkspaceBuilderCreateGroupDialog, 'dialog', {
|
|
952
1037
|
header: this.transloco.translate('workspace-builder.create-group'),
|
|
953
1038
|
styleClass: '!w-[28rem]',
|
|
954
1039
|
height: 'auto',
|
|
955
1040
|
appendTo: 'body',
|
|
956
1041
|
dismissableMask: true,
|
|
957
|
-
data
|
|
1042
|
+
data,
|
|
958
1043
|
inputValues: { area },
|
|
959
1044
|
});
|
|
960
|
-
ref.onClose.subscribe((result) => {
|
|
961
|
-
const title = result?.title?.trim();
|
|
962
|
-
if (!title) {
|
|
963
|
-
return;
|
|
964
|
-
}
|
|
965
|
-
const order = this.layout()[area].length + 1;
|
|
966
|
-
this.facade.createGroup(title, area, order).subscribe({
|
|
967
|
-
next: () => {
|
|
968
|
-
this.ts.success(this.getSuccessMessage(WorkspaceBuilderActionKey.CreateGroup, 'workspace-builder.group-create-success'));
|
|
969
|
-
},
|
|
970
|
-
error: () => {
|
|
971
|
-
this.ts.error(this.getErrorMessage(WorkspaceBuilderActionKey.CreateGroup, 'workspace-builder.group-create-error'));
|
|
972
|
-
},
|
|
973
|
-
});
|
|
974
|
-
});
|
|
975
1045
|
}
|
|
976
1046
|
startRenameGroup(group) {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
},
|
|
990
|
-
error: () => {
|
|
991
|
-
this.ts.error(this.getErrorMessage(WorkspaceBuilderActionKey.UpdateGroup, 'workspace-builder.group-update-error'));
|
|
992
|
-
},
|
|
1047
|
+
const data = {
|
|
1048
|
+
groupId: group.id,
|
|
1049
|
+
localizedName: group.localizedName,
|
|
1050
|
+
};
|
|
1051
|
+
this.modal.openModal(WorkspaceBuilderCreateGroupDialog, 'dialog', {
|
|
1052
|
+
header: this.transloco.translate('workspace-builder.rename-group'),
|
|
1053
|
+
styleClass: '!w-[28rem]',
|
|
1054
|
+
height: 'auto',
|
|
1055
|
+
appendTo: 'body',
|
|
1056
|
+
dismissableMask: true,
|
|
1057
|
+
data,
|
|
1058
|
+
inputValues: { area: null },
|
|
993
1059
|
});
|
|
994
1060
|
}
|
|
995
|
-
cancelRenameGroup() {
|
|
996
|
-
this.editingGroupId.set(null);
|
|
997
|
-
this.editingGroupTitle.set('');
|
|
998
|
-
}
|
|
999
1061
|
onSaveClick() {
|
|
1000
1062
|
this.triggerAutoSave({ notifyOnSuccess: true });
|
|
1001
1063
|
}
|
|
@@ -1379,6 +1441,7 @@ class WorkspaceBuilder {
|
|
|
1379
1441
|
type: 'group',
|
|
1380
1442
|
id: item.id,
|
|
1381
1443
|
name: item.name,
|
|
1444
|
+
localizedName: { ...item.localizedName },
|
|
1382
1445
|
order: item.order,
|
|
1383
1446
|
modules: item.modules.map((module) => ({
|
|
1384
1447
|
id: module.id,
|
|
@@ -1409,23 +1472,21 @@ class WorkspaceBuilder {
|
|
|
1409
1472
|
return this.transloco.translate(fallbackTranslationKey);
|
|
1410
1473
|
}
|
|
1411
1474
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkspaceBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1412
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", 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 @if (editingGroupId() === item.id) {\r\n <mt-text-field\r\n [(ngModel)]=\"editingGroupTitle\"\r\n class=\"min-w-[12rem] flex-1\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n severity=\"success\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"saveRenameGroup(item.id)\"\r\n />\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"cancelRenameGroup()\"\r\n />\r\n } @else {\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\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: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3$1.Draggable, selector: "[pDraggable]", inputs: ["pDraggable", "dragEffect", "dragHandle", "pDraggableDisabled"], outputs: ["onDragStart", "onDragEnd", "onDrag"] }, { kind: "directive", type: i3$1.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: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i4.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: i5.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1475
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", 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 });
|
|
1413
1476
|
}
|
|
1414
1477
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: WorkspaceBuilder, decorators: [{
|
|
1415
1478
|
type: Component,
|
|
1416
1479
|
args: [{ selector: 'mt-workspace-builder', standalone: true, imports: [
|
|
1417
1480
|
CommonModule,
|
|
1418
|
-
FormsModule,
|
|
1419
1481
|
TranslocoDirective,
|
|
1420
1482
|
DragDropModule,
|
|
1421
1483
|
Button,
|
|
1422
1484
|
Icon,
|
|
1423
1485
|
Page,
|
|
1424
1486
|
Card,
|
|
1425
|
-
TextField,
|
|
1426
1487
|
ContextMenuModule,
|
|
1427
1488
|
SkeletonModule,
|
|
1428
|
-
], 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 @if (editingGroupId() === item.id) {\r\n <mt-text-field\r\n [(ngModel)]=\"editingGroupTitle\"\r\n class=\"min-w-[12rem] flex-1\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n severity=\"success\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"saveRenameGroup(item.id)\"\r\n />\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"cancelRenameGroup()\"\r\n />\r\n } @else {\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\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"] }]
|
|
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"] }]
|
|
1429
1490
|
}], 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 }] }] } });
|
|
1430
1491
|
|
|
1431
1492
|
/**
|