@memberjunction/ng-file-storage 5.22.0 → 5.23.0
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/dist/lib/category-tree/category-tree.d.ts +29 -5
- package/dist/lib/category-tree/category-tree.d.ts.map +1 -1
- package/dist/lib/category-tree/category-tree.js +226 -104
- package/dist/lib/category-tree/category-tree.js.map +1 -1
- package/dist/lib/file-browser/file-grid.component.js +1 -2
- package/dist/lib/file-browser/file-grid.component.js.map +1 -1
- package/dist/lib/file-browser/folder-tree.component.js +4 -4
- package/dist/lib/file-browser/folder-tree.component.js.map +1 -1
- package/dist/lib/file-upload/file-upload.d.ts +15 -5
- package/dist/lib/file-upload/file-upload.d.ts.map +1 -1
- package/dist/lib/file-upload/file-upload.js +54 -33
- package/dist/lib/file-upload/file-upload.js.map +1 -1
- package/dist/lib/files-grid/files-grid.d.ts +14 -0
- package/dist/lib/files-grid/files-grid.d.ts.map +1 -1
- package/dist/lib/files-grid/files-grid.js +123 -71
- package/dist/lib/files-grid/files-grid.js.map +1 -1
- package/dist/lib/module.d.ts +6 -17
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +13 -53
- package/dist/lib/module.js.map +1 -1
- package/package.json +11 -19
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { EventEmitter, OnInit } from '@angular/core';
|
|
2
2
|
import { MJFileCategoryEntity } from '@memberjunction/core-entities';
|
|
3
3
|
import { SharedService } from '@memberjunction/ng-shared';
|
|
4
|
-
import { ContextMenuSelectEvent } from '@progress/kendo-angular-menu';
|
|
5
|
-
import { TreeItemAddRemoveArgs } from '@progress/kendo-angular-treeview';
|
|
6
4
|
import * as i0 from "@angular/core";
|
|
7
5
|
export declare class CategoryTreeComponent implements OnInit {
|
|
8
6
|
private sharedService;
|
|
@@ -10,19 +8,45 @@ export declare class CategoryTreeComponent implements OnInit {
|
|
|
10
8
|
isLoading: boolean;
|
|
11
9
|
showNew: boolean;
|
|
12
10
|
newCategoryName: string;
|
|
13
|
-
selectedKeys: never[];
|
|
14
11
|
renameFileCategory: MJFileCategoryEntity | undefined;
|
|
15
12
|
categoriesData: MJFileCategoryEntity[];
|
|
13
|
+
/** Expanded node IDs for the tree */
|
|
14
|
+
expandedIds: Set<string>;
|
|
15
|
+
/** Currently selected node ID */
|
|
16
|
+
private selectedId;
|
|
17
|
+
/** Context menu state */
|
|
18
|
+
contextMenuVisible: boolean;
|
|
19
|
+
contextMenuX: number;
|
|
20
|
+
contextMenuY: number;
|
|
21
|
+
private contextMenuNode;
|
|
16
22
|
private md;
|
|
17
23
|
constructor(sharedService: SharedService);
|
|
18
24
|
ngOnInit(): void;
|
|
25
|
+
/** Returns root-level nodes (no parent). */
|
|
26
|
+
get rootNodes(): MJFileCategoryEntity[];
|
|
27
|
+
/** Checks if a node has children. */
|
|
28
|
+
hasChildren(node: MJFileCategoryEntity): boolean;
|
|
29
|
+
/** Returns children of a node. */
|
|
30
|
+
getChildren(node: MJFileCategoryEntity): MJFileCategoryEntity[];
|
|
31
|
+
/** Checks if a node is expanded. */
|
|
32
|
+
isExpanded(node: MJFileCategoryEntity): boolean;
|
|
33
|
+
/** Toggles expand/collapse on a node. */
|
|
34
|
+
toggleExpand(node: MJFileCategoryEntity, event: Event): void;
|
|
35
|
+
/** Checks if a node is the currently selected node. */
|
|
36
|
+
isSelected(node: MJFileCategoryEntity): boolean;
|
|
37
|
+
/** Selects a node and emits event. */
|
|
38
|
+
selectNode(node: MJFileCategoryEntity): void;
|
|
39
|
+
/** Opens context menu on right-click. */
|
|
40
|
+
onContextMenu(event: MouseEvent, node: MJFileCategoryEntity): void;
|
|
41
|
+
/** Closes the context menu. */
|
|
42
|
+
closeContextMenu(): void;
|
|
43
|
+
/** Handles context menu action selection. */
|
|
44
|
+
onContextMenuAction(action: string): void;
|
|
19
45
|
createNewCategory(): Promise<void>;
|
|
20
46
|
cancelNewCategory(): void;
|
|
21
|
-
handleDrop(e: TreeItemAddRemoveArgs): Promise<void>;
|
|
22
47
|
saveNewCategory(): Promise<void>;
|
|
23
48
|
deleteCategory(fileCategory: MJFileCategoryEntity): Promise<void>;
|
|
24
49
|
clearSelection(): void;
|
|
25
|
-
handleMenuSelect(e: ContextMenuSelectEvent): void;
|
|
26
50
|
cancelRename(): void;
|
|
27
51
|
saveRename(): Promise<void>;
|
|
28
52
|
Refresh(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"category-tree.d.ts","sourceRoot":"","sources":["../../../src/lib/category-tree/category-tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC
|
|
1
|
+
{"version":3,"file":"category-tree.d.ts","sourceRoot":"","sources":["../../../src/lib/category-tree/category-tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;;AAG1D,qBAMa,qBAAsB,YAAW,MAAM;IAwBtC,OAAO,CAAC,aAAa;IAvBvB,gBAAgB,mCAA0C;IAE7D,SAAS,EAAE,OAAO,CAAS;IAC3B,OAAO,EAAE,OAAO,CAAS;IACzB,eAAe,SAAM;IACrB,kBAAkB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAErD,cAAc,EAAE,oBAAoB,EAAE,CAAM;IAEnD,qCAAqC;IAC9B,WAAW,cAAqB;IAEvC,iCAAiC;IACjC,OAAO,CAAC,UAAU,CAAqB;IAEvC,yBAAyB;IAClB,kBAAkB,UAAS;IAC3B,YAAY,SAAK;IACjB,YAAY,SAAK;IACxB,OAAO,CAAC,eAAe,CAAmC;IAE1D,OAAO,CAAC,EAAE,CAAkB;gBAER,aAAa,EAAE,aAAa;IAEhD,QAAQ,IAAI,IAAI;IAIhB,4CAA4C;IAC5C,IAAI,SAAS,IAAI,oBAAoB,EAAE,CAEtC;IAED,qCAAqC;IACrC,WAAW,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO;IAIhD,kCAAkC;IAClC,WAAW,CAAC,IAAI,EAAE,oBAAoB,GAAG,oBAAoB,EAAE;IAI/D,oCAAoC;IACpC,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO;IAI/C,yCAAyC;IACzC,YAAY,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAS5D,uDAAuD;IACvD,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO;IAI/C,sCAAsC;IACtC,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI;IAK5C,yCAAyC;IACzC,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,oBAAoB,GAAG,IAAI;IASlE,+BAA+B;IAC/B,gBAAgB,IAAI,IAAI;IAKxB,6CAA6C;IAC7C,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAiBnC,iBAAiB;IAIvB,iBAAiB;IAIX,eAAe;IAYf,cAAc,CAAC,YAAY,EAAE,oBAAoB;IAgBvD,cAAc;IAKd,YAAY;IAKN,UAAU;IAOV,OAAO;yCA9JF,qBAAqB;2CAArB,qBAAqB;CA8KjC"}
|
|
@@ -3,85 +3,128 @@ import { Metadata, RunView } from '@memberjunction/core';
|
|
|
3
3
|
import { UUIDsEqual } from '@memberjunction/global';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
import * as i1 from "@memberjunction/ng-shared";
|
|
6
|
-
import * as i2 from "@
|
|
6
|
+
import * as i2 from "@angular/common";
|
|
7
7
|
import * as i3 from "@angular/forms";
|
|
8
|
-
import * as i4 from "@
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
i0.ɵɵ
|
|
8
|
+
import * as i4 from "@memberjunction/ng-ui-components";
|
|
9
|
+
const _c0 = a0 => ({ $implicit: a0, level: 0 });
|
|
10
|
+
const _c1 = (a0, a1) => ({ $implicit: a0, level: a1 });
|
|
11
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
12
|
+
function CategoryTreeComponent_For_8_ng_container_0_Template(rf, ctx) { if (rf & 1) {
|
|
13
|
+
i0.ɵɵelementContainer(0);
|
|
14
|
+
} }
|
|
15
|
+
function CategoryTreeComponent_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
16
|
+
i0.ɵɵtemplate(0, CategoryTreeComponent_For_8_ng_container_0_Template, 1, 0, "ng-container", 17);
|
|
17
|
+
} if (rf & 2) {
|
|
18
|
+
const node_r2 = ctx.$implicit;
|
|
19
|
+
i0.ɵɵnextContext();
|
|
20
|
+
const treeNode_r3 = i0.ɵɵreference(10);
|
|
21
|
+
i0.ɵɵproperty("ngTemplateOutlet", treeNode_r3)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, node_r2));
|
|
22
|
+
} }
|
|
23
|
+
function CategoryTreeComponent_ng_template_9_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
24
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
25
|
+
i0.ɵɵelementStart(0, "button", 24);
|
|
26
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_ng_template_9_Conditional_2_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const node_r5 = i0.ɵɵnextContext().$implicit; const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.toggleExpand(node_r5, $event)); });
|
|
27
|
+
i0.ɵɵelement(1, "i", 25);
|
|
17
28
|
i0.ɵɵelementEnd();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
i0.ɵɵ
|
|
29
|
+
} if (rf & 2) {
|
|
30
|
+
const node_r5 = i0.ɵɵnextContext().$implicit;
|
|
31
|
+
const ctx_r5 = i0.ɵɵnextContext();
|
|
32
|
+
i0.ɵɵadvance();
|
|
33
|
+
i0.ɵɵclassProp("fa-chevron-right", !ctx_r5.isExpanded(node_r5))("fa-chevron-down", ctx_r5.isExpanded(node_r5));
|
|
34
|
+
} }
|
|
35
|
+
function CategoryTreeComponent_ng_template_9_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
36
|
+
i0.ɵɵelement(0, "span", 21);
|
|
37
|
+
} }
|
|
38
|
+
function CategoryTreeComponent_ng_template_9_Conditional_7_For_1_ng_container_0_Template(rf, ctx) { if (rf & 1) {
|
|
39
|
+
i0.ɵɵelementContainer(0);
|
|
40
|
+
} }
|
|
41
|
+
function CategoryTreeComponent_ng_template_9_Conditional_7_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
42
|
+
i0.ɵɵtemplate(0, CategoryTreeComponent_ng_template_9_Conditional_7_For_1_ng_container_0_Template, 1, 0, "ng-container", 17);
|
|
43
|
+
} if (rf & 2) {
|
|
44
|
+
const child_r8 = ctx.$implicit;
|
|
45
|
+
const level_r9 = i0.ɵɵnextContext(2).level;
|
|
46
|
+
i0.ɵɵnextContext();
|
|
47
|
+
const treeNode_r3 = i0.ɵɵreference(10);
|
|
48
|
+
i0.ɵɵproperty("ngTemplateOutlet", treeNode_r3)("ngTemplateOutletContext", i0.ɵɵpureFunction2(2, _c1, child_r8, level_r9 + 1));
|
|
49
|
+
} }
|
|
50
|
+
function CategoryTreeComponent_ng_template_9_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
51
|
+
i0.ɵɵrepeaterCreate(0, CategoryTreeComponent_ng_template_9_Conditional_7_For_1_Template, 1, 5, "ng-container", null, _forTrack0);
|
|
52
|
+
} if (rf & 2) {
|
|
53
|
+
const node_r5 = i0.ɵɵnextContext().$implicit;
|
|
54
|
+
const ctx_r5 = i0.ɵɵnextContext();
|
|
55
|
+
i0.ɵɵrepeater(ctx_r5.getChildren(node_r5));
|
|
56
|
+
} }
|
|
57
|
+
function CategoryTreeComponent_ng_template_9_Template(rf, ctx) { if (rf & 1) {
|
|
58
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
59
|
+
i0.ɵɵelementStart(0, "div", 18)(1, "div", 19);
|
|
60
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_ng_template_9_Template_div_click_1_listener() { const node_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.selectNode(node_r5)); })("contextmenu", function CategoryTreeComponent_ng_template_9_Template_div_contextmenu_1_listener($event) { const node_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.onContextMenu($event, node_r5)); });
|
|
61
|
+
i0.ɵɵconditionalCreate(2, CategoryTreeComponent_ng_template_9_Conditional_2_Template, 2, 4, "button", 20)(3, CategoryTreeComponent_ng_template_9_Conditional_3_Template, 1, 0, "span", 21);
|
|
62
|
+
i0.ɵɵelement(4, "i", 22);
|
|
63
|
+
i0.ɵɵelementStart(5, "span", 23);
|
|
64
|
+
i0.ɵɵtext(6);
|
|
65
|
+
i0.ɵɵelementEnd()();
|
|
66
|
+
i0.ɵɵconditionalCreate(7, CategoryTreeComponent_ng_template_9_Conditional_7_Template, 2, 0);
|
|
21
67
|
i0.ɵɵelementEnd();
|
|
22
68
|
} if (rf & 2) {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
i0.ɵɵ
|
|
26
|
-
i0.ɵɵ
|
|
69
|
+
const node_r5 = ctx.$implicit;
|
|
70
|
+
const level_r9 = ctx.level;
|
|
71
|
+
const ctx_r5 = i0.ɵɵnextContext();
|
|
72
|
+
i0.ɵɵstyleProp("padding-left", level_r9 * 20, "px");
|
|
27
73
|
i0.ɵɵadvance();
|
|
28
|
-
i0.ɵɵ
|
|
74
|
+
i0.ɵɵclassProp("selected", ctx_r5.isSelected(node_r5));
|
|
29
75
|
i0.ɵɵadvance();
|
|
30
|
-
i0.ɵɵ
|
|
76
|
+
i0.ɵɵconditional(ctx_r5.hasChildren(node_r5) ? 2 : 3);
|
|
77
|
+
i0.ɵɵadvance(4);
|
|
78
|
+
i0.ɵɵtextInterpolate(node_r5.Name);
|
|
31
79
|
i0.ɵɵadvance();
|
|
32
|
-
i0.ɵɵ
|
|
80
|
+
i0.ɵɵconditional(ctx_r5.isExpanded(node_r5) ? 7 : -1);
|
|
33
81
|
} }
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
i0.ɵɵelementStart(0, "
|
|
37
|
-
i0.ɵɵlistener("
|
|
38
|
-
i0.ɵɵelementStart(1, "
|
|
39
|
-
i0.ɵɵ
|
|
40
|
-
i0.ɵɵ
|
|
41
|
-
i0.ɵɵ
|
|
42
|
-
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_8_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelNewCategory()); });
|
|
43
|
-
i0.ɵɵtext(8, "Cancel");
|
|
82
|
+
function CategoryTreeComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
83
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
84
|
+
i0.ɵɵelementStart(0, "div", 26);
|
|
85
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_11_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.closeContextMenu()); }, i0.ɵɵresolveDocument);
|
|
86
|
+
i0.ɵɵelementStart(1, "button", 27);
|
|
87
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_11_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r10); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.onContextMenuAction("rename")); });
|
|
88
|
+
i0.ɵɵelement(2, "i", 28);
|
|
89
|
+
i0.ɵɵtext(3, " Rename ");
|
|
44
90
|
i0.ɵɵelementEnd();
|
|
45
|
-
i0.ɵɵelementStart(
|
|
46
|
-
i0.ɵɵlistener("click", function
|
|
47
|
-
i0.ɵɵ
|
|
48
|
-
i0.ɵɵ
|
|
91
|
+
i0.ɵɵelementStart(4, "button", 29);
|
|
92
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_11_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r10); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.onContextMenuAction("delete")); });
|
|
93
|
+
i0.ɵɵelement(5, "i", 30);
|
|
94
|
+
i0.ɵɵtext(6, " Delete ");
|
|
95
|
+
i0.ɵɵelementEnd()();
|
|
49
96
|
} if (rf & 2) {
|
|
50
|
-
const
|
|
51
|
-
i0.ɵɵ
|
|
52
|
-
i0.ɵɵadvance(5);
|
|
53
|
-
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newCategoryName);
|
|
54
|
-
i0.ɵɵproperty("showSuccessIcon", ctx_r1.newCategoryName.length > 0)("disabled", ctx_r1.isLoading);
|
|
55
|
-
i0.ɵɵadvance(2);
|
|
56
|
-
i0.ɵɵproperty("disabled", ctx_r1.isLoading);
|
|
57
|
-
i0.ɵɵadvance(2);
|
|
58
|
-
i0.ɵɵproperty("disabled", ctx_r1.isLoading);
|
|
97
|
+
const ctx_r5 = i0.ɵɵnextContext();
|
|
98
|
+
i0.ɵɵstyleProp("top", ctx_r5.contextMenuY, "px")("left", ctx_r5.contextMenuX, "px");
|
|
59
99
|
} }
|
|
60
|
-
function
|
|
61
|
-
const
|
|
62
|
-
i0.ɵɵelementStart(0, "
|
|
63
|
-
i0.ɵɵlistener("
|
|
64
|
-
i0.ɵɵelementStart(1, "div",
|
|
65
|
-
i0.ɵɵ
|
|
66
|
-
i0.ɵɵelementEnd()()()();
|
|
67
|
-
i0.ɵɵelementStart(6, "kendo-dialog-actions")(7, "button", 16);
|
|
68
|
-
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_9_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelRename()); });
|
|
69
|
-
i0.ɵɵtext(8, "Cancel");
|
|
100
|
+
function CategoryTreeComponent_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
101
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
102
|
+
i0.ɵɵelementStart(0, "mj-dialog", 31);
|
|
103
|
+
i0.ɵɵlistener("Close", function CategoryTreeComponent_Conditional_25_Template_mj_dialog_Close_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.cancelRename()); });
|
|
104
|
+
i0.ɵɵelementStart(1, "div", 10)(2, "form", null, 2)(4, "label", 11)(5, "span", 12);
|
|
105
|
+
i0.ɵɵtext(6, "Name");
|
|
70
106
|
i0.ɵɵelementEnd();
|
|
71
|
-
i0.ɵɵelementStart(
|
|
72
|
-
i0.ɵɵ
|
|
107
|
+
i0.ɵɵelementStart(7, "input", 32);
|
|
108
|
+
i0.ɵɵtwoWayListener("ngModelChange", function CategoryTreeComponent_Conditional_25_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r5 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r5.renameFileCategory.Name, $event) || (ctx_r5.renameFileCategory.Name = $event); return i0.ɵɵresetView($event); });
|
|
109
|
+
i0.ɵɵelementEnd()()()();
|
|
110
|
+
i0.ɵɵelementStart(8, "mj-dialog-actions")(9, "button", 14);
|
|
111
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_25_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r11); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.saveRename()); });
|
|
73
112
|
i0.ɵɵtext(10, "Save");
|
|
113
|
+
i0.ɵɵelementEnd();
|
|
114
|
+
i0.ɵɵelementStart(11, "button", 15);
|
|
115
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Conditional_25_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r11); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.cancelRename()); });
|
|
116
|
+
i0.ɵɵtext(12, "Cancel");
|
|
74
117
|
i0.ɵɵelementEnd()()();
|
|
75
118
|
} if (rf & 2) {
|
|
76
|
-
const
|
|
77
|
-
i0.ɵɵproperty("
|
|
78
|
-
i0.ɵɵadvance(
|
|
79
|
-
i0.ɵɵtwoWayProperty("ngModel",
|
|
80
|
-
i0.ɵɵproperty("
|
|
119
|
+
const ctx_r5 = i0.ɵɵnextContext();
|
|
120
|
+
i0.ɵɵproperty("Visible", true)("Width", 450)("MinWidth", 250);
|
|
121
|
+
i0.ɵɵadvance(7);
|
|
122
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r5.renameFileCategory.Name);
|
|
123
|
+
i0.ɵɵproperty("disabled", ctx_r5.isLoading);
|
|
81
124
|
i0.ɵɵadvance(2);
|
|
82
|
-
i0.ɵɵproperty("disabled",
|
|
125
|
+
i0.ɵɵproperty("disabled", ctx_r5.isLoading || !ctx_r5.renameFileCategory.Dirty);
|
|
83
126
|
i0.ɵɵadvance(2);
|
|
84
|
-
i0.ɵɵproperty("disabled",
|
|
127
|
+
i0.ɵɵproperty("disabled", ctx_r5.isLoading);
|
|
85
128
|
} }
|
|
86
129
|
export class CategoryTreeComponent {
|
|
87
130
|
sharedService;
|
|
@@ -89,9 +132,17 @@ export class CategoryTreeComponent {
|
|
|
89
132
|
isLoading = false;
|
|
90
133
|
showNew = false;
|
|
91
134
|
newCategoryName = '';
|
|
92
|
-
selectedKeys = [];
|
|
93
135
|
renameFileCategory;
|
|
94
136
|
categoriesData = [];
|
|
137
|
+
/** Expanded node IDs for the tree */
|
|
138
|
+
expandedIds = new Set();
|
|
139
|
+
/** Currently selected node ID */
|
|
140
|
+
selectedId;
|
|
141
|
+
/** Context menu state */
|
|
142
|
+
contextMenuVisible = false;
|
|
143
|
+
contextMenuX = 0;
|
|
144
|
+
contextMenuY = 0;
|
|
145
|
+
contextMenuNode;
|
|
95
146
|
md = new Metadata();
|
|
96
147
|
constructor(sharedService) {
|
|
97
148
|
this.sharedService = sharedService;
|
|
@@ -99,21 +150,77 @@ export class CategoryTreeComponent {
|
|
|
99
150
|
ngOnInit() {
|
|
100
151
|
this.Refresh();
|
|
101
152
|
}
|
|
153
|
+
/** Returns root-level nodes (no parent). */
|
|
154
|
+
get rootNodes() {
|
|
155
|
+
return this.categoriesData.filter((c) => !c.ParentID);
|
|
156
|
+
}
|
|
157
|
+
/** Checks if a node has children. */
|
|
158
|
+
hasChildren(node) {
|
|
159
|
+
return this.categoriesData.some((c) => UUIDsEqual(c.ParentID, node.ID));
|
|
160
|
+
}
|
|
161
|
+
/** Returns children of a node. */
|
|
162
|
+
getChildren(node) {
|
|
163
|
+
return this.categoriesData.filter((c) => UUIDsEqual(c.ParentID, node.ID));
|
|
164
|
+
}
|
|
165
|
+
/** Checks if a node is expanded. */
|
|
166
|
+
isExpanded(node) {
|
|
167
|
+
return this.expandedIds.has(node.ID);
|
|
168
|
+
}
|
|
169
|
+
/** Toggles expand/collapse on a node. */
|
|
170
|
+
toggleExpand(node, event) {
|
|
171
|
+
event.stopPropagation();
|
|
172
|
+
if (this.expandedIds.has(node.ID)) {
|
|
173
|
+
this.expandedIds.delete(node.ID);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
this.expandedIds.add(node.ID);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/** Checks if a node is the currently selected node. */
|
|
180
|
+
isSelected(node) {
|
|
181
|
+
return this.selectedId != null && UUIDsEqual(this.selectedId, node.ID);
|
|
182
|
+
}
|
|
183
|
+
/** Selects a node and emits event. */
|
|
184
|
+
selectNode(node) {
|
|
185
|
+
this.selectedId = node.ID;
|
|
186
|
+
this.categorySelected.emit(node.ID);
|
|
187
|
+
}
|
|
188
|
+
/** Opens context menu on right-click. */
|
|
189
|
+
onContextMenu(event, node) {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
event.stopPropagation();
|
|
192
|
+
this.contextMenuNode = node;
|
|
193
|
+
this.contextMenuX = event.clientX;
|
|
194
|
+
this.contextMenuY = event.clientY;
|
|
195
|
+
this.contextMenuVisible = true;
|
|
196
|
+
}
|
|
197
|
+
/** Closes the context menu. */
|
|
198
|
+
closeContextMenu() {
|
|
199
|
+
this.contextMenuVisible = false;
|
|
200
|
+
this.contextMenuNode = undefined;
|
|
201
|
+
}
|
|
202
|
+
/** Handles context menu action selection. */
|
|
203
|
+
onContextMenuAction(action) {
|
|
204
|
+
const node = this.contextMenuNode;
|
|
205
|
+
this.closeContextMenu();
|
|
206
|
+
if (!node) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
switch (action) {
|
|
210
|
+
case 'rename':
|
|
211
|
+
this.renameFileCategory = node;
|
|
212
|
+
break;
|
|
213
|
+
case 'delete':
|
|
214
|
+
this.deleteCategory(node);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
102
218
|
async createNewCategory() {
|
|
103
219
|
this.showNew = true;
|
|
104
220
|
}
|
|
105
221
|
cancelNewCategory() {
|
|
106
222
|
this.showNew = false;
|
|
107
223
|
}
|
|
108
|
-
async handleDrop(e) {
|
|
109
|
-
console.log(e);
|
|
110
|
-
const sourceCategory = e.sourceItem.item.dataItem;
|
|
111
|
-
const targetCategory = e.destinationItem.item.dataItem;
|
|
112
|
-
sourceCategory.ParentID = targetCategory.ID;
|
|
113
|
-
this.isLoading = true;
|
|
114
|
-
await sourceCategory.Save();
|
|
115
|
-
this.isLoading = false;
|
|
116
|
-
}
|
|
117
224
|
async saveNewCategory() {
|
|
118
225
|
this.isLoading = true;
|
|
119
226
|
const categoryEntity = await this.md.GetEntityObject('MJ: File Categories');
|
|
@@ -122,6 +229,7 @@ export class CategoryTreeComponent {
|
|
|
122
229
|
await categoryEntity?.Save();
|
|
123
230
|
this.categoriesData = [...this.categoriesData, categoryEntity];
|
|
124
231
|
this.showNew = false;
|
|
232
|
+
this.newCategoryName = '';
|
|
125
233
|
this.isLoading = false;
|
|
126
234
|
}
|
|
127
235
|
async deleteCategory(fileCategory) {
|
|
@@ -131,6 +239,7 @@ export class CategoryTreeComponent {
|
|
|
131
239
|
if (!success) {
|
|
132
240
|
console.error('Unable to delete file category:', fileCategory);
|
|
133
241
|
this.sharedService.CreateSimpleNotification(`Unable to delete category '${fileCategory.Name}'`, 'error');
|
|
242
|
+
this.isLoading = false;
|
|
134
243
|
return;
|
|
135
244
|
}
|
|
136
245
|
this.categoriesData = this.categoriesData.filter((c) => !UUIDsEqual(c.ID, ID));
|
|
@@ -138,22 +247,9 @@ export class CategoryTreeComponent {
|
|
|
138
247
|
this.isLoading = false;
|
|
139
248
|
}
|
|
140
249
|
clearSelection() {
|
|
141
|
-
this.
|
|
250
|
+
this.selectedId = undefined;
|
|
142
251
|
this.categorySelected.emit(undefined);
|
|
143
252
|
}
|
|
144
|
-
handleMenuSelect(e) {
|
|
145
|
-
const action = e.item?.text?.toLowerCase() ?? '';
|
|
146
|
-
switch (action) {
|
|
147
|
-
case 'rename':
|
|
148
|
-
this.renameFileCategory = e.item.data;
|
|
149
|
-
break;
|
|
150
|
-
case 'delete':
|
|
151
|
-
this.deleteCategory(e.item.data);
|
|
152
|
-
break;
|
|
153
|
-
default:
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
253
|
cancelRename() {
|
|
158
254
|
this.renameFileCategory?.Revert();
|
|
159
255
|
this.renameFileCategory = undefined;
|
|
@@ -180,36 +276,62 @@ export class CategoryTreeComponent {
|
|
|
180
276
|
this.isLoading = false;
|
|
181
277
|
}
|
|
182
278
|
static ɵfac = function CategoryTreeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CategoryTreeComponent)(i0.ɵɵdirectiveInject(i1.SharedService)); };
|
|
183
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CategoryTreeComponent, selectors: [["mj-files-category-tree"]], outputs: { categorySelected: "categorySelected" }, standalone: false, decls:
|
|
184
|
-
|
|
185
|
-
i0.ɵɵ
|
|
279
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CategoryTreeComponent, selectors: [["mj-files-category-tree"]], outputs: { categorySelected: "categorySelected" }, standalone: false, decls: 26, vars: 9, consts: [["treeNode", ""], ["newForm", "ngForm"], ["renameForm", "ngForm"], [1, "container"], [1, "tree-header"], ["mjButton", "", 3, "click"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "category-tree"], [1, "context-menu", 3, "top", "left"], ["Title", "New file category", 3, "Close", "Visible", "Width", "MinWidth"], [1, "dialog-form-container"], [1, "mj-form-field"], [1, "mj-form-label"], ["name", "name", "required", "", 1, "mj-input", 3, "ngModelChange", "ngModel", "disabled"], ["mjButton", "", "variant", "primary", 3, "click", "disabled"], ["mjButton", "", 3, "click", "disabled"], ["Title", "Rename file category", 3, "Visible", "Width", "MinWidth"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "tree-node"], [1, "tree-node-row", 3, "click", "contextmenu"], [1, "tree-expand-btn"], [1, "tree-expand-placeholder"], [1, "fa-solid", "fa-folder", "tree-folder-icon"], [1, "tree-node-label"], [1, "tree-expand-btn", 3, "click"], [1, "fa-solid"], [1, "context-menu", 3, "click"], [1, "context-menu-item", 3, "click"], [1, "fa-solid", "fa-pen"], ["disabled", "", 1, "context-menu-item", 3, "click"], [1, "fa-solid", "fa-trash-can"], ["Title", "Rename file category", 3, "Close", "Visible", "Width", "MinWidth"], ["name", "Name", "required", "", 1, "mj-input", 3, "ngModelChange", "ngModel", "disabled"]], template: function CategoryTreeComponent_Template(rf, ctx) { if (rf & 1) {
|
|
280
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
281
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
|
|
282
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.clearSelection()); });
|
|
186
283
|
i0.ɵɵtext(3, "All Files");
|
|
187
284
|
i0.ɵɵelementEnd();
|
|
188
|
-
i0.ɵɵelementStart(4, "button",
|
|
189
|
-
i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_4_listener() { return ctx.createNewCategory(); });
|
|
285
|
+
i0.ɵɵelementStart(4, "button", 6);
|
|
286
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.createNewCategory()); });
|
|
190
287
|
i0.ɵɵtext(5, "Add category");
|
|
191
288
|
i0.ɵɵelementEnd()();
|
|
192
|
-
i0.ɵɵelementStart(6, "
|
|
193
|
-
i0.ɵɵ
|
|
194
|
-
i0.ɵɵ
|
|
289
|
+
i0.ɵɵelementStart(6, "div", 7);
|
|
290
|
+
i0.ɵɵrepeaterCreate(7, CategoryTreeComponent_For_8_Template, 1, 4, "ng-container", null, _forTrack0);
|
|
291
|
+
i0.ɵɵelementEnd();
|
|
292
|
+
i0.ɵɵtemplate(9, CategoryTreeComponent_ng_template_9_Template, 8, 7, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
|
|
293
|
+
i0.ɵɵconditionalCreate(11, CategoryTreeComponent_Conditional_11_Template, 7, 4, "div", 8);
|
|
294
|
+
i0.ɵɵelementStart(12, "mj-dialog", 9);
|
|
295
|
+
i0.ɵɵlistener("Close", function CategoryTreeComponent_Template_mj_dialog_Close_12_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.cancelNewCategory()); });
|
|
296
|
+
i0.ɵɵelementStart(13, "div", 10)(14, "form", null, 1)(16, "label", 11)(17, "span", 12);
|
|
297
|
+
i0.ɵɵtext(18, "Name");
|
|
195
298
|
i0.ɵɵelementEnd();
|
|
196
|
-
i0.ɵɵ
|
|
197
|
-
i0.ɵɵ
|
|
299
|
+
i0.ɵɵelementStart(19, "input", 13);
|
|
300
|
+
i0.ɵɵtwoWayListener("ngModelChange", function CategoryTreeComponent_Template_input_ngModelChange_19_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.newCategoryName, $event) || (ctx.newCategoryName = $event); return i0.ɵɵresetView($event); });
|
|
301
|
+
i0.ɵɵelementEnd()()()();
|
|
302
|
+
i0.ɵɵelementStart(20, "mj-dialog-actions")(21, "button", 14);
|
|
303
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.saveNewCategory()); });
|
|
304
|
+
i0.ɵɵtext(22, "Save");
|
|
305
|
+
i0.ɵɵelementEnd();
|
|
306
|
+
i0.ɵɵelementStart(23, "button", 15);
|
|
307
|
+
i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.cancelNewCategory()); });
|
|
308
|
+
i0.ɵɵtext(24, "Cancel");
|
|
309
|
+
i0.ɵɵelementEnd()()();
|
|
310
|
+
i0.ɵɵconditionalCreate(25, CategoryTreeComponent_Conditional_25_Template, 13, 7, "mj-dialog", 16);
|
|
198
311
|
i0.ɵɵelementEnd();
|
|
199
312
|
} if (rf & 2) {
|
|
200
|
-
i0.ɵɵadvance(
|
|
201
|
-
i0.ɵɵ
|
|
202
|
-
i0.ɵɵadvance(
|
|
203
|
-
i0.ɵɵconditional(ctx.
|
|
313
|
+
i0.ɵɵadvance(7);
|
|
314
|
+
i0.ɵɵrepeater(ctx.rootNodes);
|
|
315
|
+
i0.ɵɵadvance(4);
|
|
316
|
+
i0.ɵɵconditional(ctx.contextMenuVisible ? 11 : -1);
|
|
204
317
|
i0.ɵɵadvance();
|
|
205
|
-
i0.ɵɵ
|
|
206
|
-
|
|
318
|
+
i0.ɵɵproperty("Visible", ctx.showNew)("Width", 450)("MinWidth", 250);
|
|
319
|
+
i0.ɵɵadvance(7);
|
|
320
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx.newCategoryName);
|
|
321
|
+
i0.ɵɵproperty("disabled", ctx.isLoading);
|
|
322
|
+
i0.ɵɵadvance(2);
|
|
323
|
+
i0.ɵɵproperty("disabled", ctx.isLoading);
|
|
324
|
+
i0.ɵɵadvance(2);
|
|
325
|
+
i0.ɵɵproperty("disabled", ctx.isLoading);
|
|
326
|
+
i0.ɵɵadvance(2);
|
|
327
|
+
i0.ɵɵconditional(!!ctx.renameFileCategory ? 25 : -1);
|
|
328
|
+
} }, dependencies: [i2.NgTemplateOutlet, i3.ɵNgNoValidate, i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgControlStatusGroup, i3.RequiredValidator, i3.NgModel, i3.NgForm, i4.MJButtonDirective, i4.MJDialogComponent, i4.MJDialogActionsComponent], styles: ["\n\n.container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n}\n\n.category-tree[_ngcontent-%COMP%] {\n width: 250px;\n max-height: 500px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n}\n\n.tree-header[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding-right: 4px;\n margin-bottom: 4px;\n}\n\n.tree-node-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 4px;\n transition: background-color 0.15s;\n user-select: none;\n}\n\n.tree-node-row[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n.tree-node-row.selected[_ngcontent-%COMP%] {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.tree-expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n.tree-expand-placeholder[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n display: inline-block;\n}\n\n.tree-folder-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.tree-node-label[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n\n\n.context-menu[_ngcontent-%COMP%] {\n position: fixed;\n z-index: 10000;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n box-shadow: 0 4px 12px var(--mj-bg-overlay);\n padding: 4px 0;\n min-width: 140px;\n}\n\n.context-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 16px;\n border: none;\n background: none;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n}\n\n.context-menu-item[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu-item[_ngcontent-%COMP%]:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.dialog-form-container[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.mj-form-field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n align-items: center;\n column-gap: 12px;\n margin-bottom: 8px;\n}\n\n.mj-form-label[_ngcontent-%COMP%] {\n min-width: 80px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.mj-form-field[_ngcontent-%COMP%] .mj-input[_ngcontent-%COMP%] {\n width: 100%;\n}"] });
|
|
207
329
|
}
|
|
208
330
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CategoryTreeComponent, [{
|
|
209
331
|
type: Component,
|
|
210
|
-
args: [{ standalone: false, selector: 'mj-files-category-tree', template: "<div class=\"container\">\n <div class=\"tree-header\">\n <button
|
|
332
|
+
args: [{ standalone: false, selector: 'mj-files-category-tree', template: "<div class=\"container\">\n <div class=\"tree-header\">\n <button mjButton (click)=\"clearSelection()\">All Files</button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"createNewCategory()\">Add category</button>\n </div>\n\n <div class=\"category-tree\">\n @for (node of rootNodes; track node.ID) {\n <ng-container *ngTemplateOutlet=\"treeNode; context: { $implicit: node, level: 0 }\"></ng-container>\n }\n </div>\n\n <ng-template #treeNode let-node let-level=\"level\">\n <div class=\"tree-node\" [style.padding-left.px]=\"level * 20\">\n <div class=\"tree-node-row\"\n [class.selected]=\"isSelected(node)\"\n (click)=\"selectNode(node)\"\n (contextmenu)=\"onContextMenu($event, node)\">\n @if (hasChildren(node)) {\n <button class=\"tree-expand-btn\" (click)=\"toggleExpand(node, $event)\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!isExpanded(node)\" [class.fa-chevron-down]=\"isExpanded(node)\"></i>\n </button>\n } @else {\n <span class=\"tree-expand-placeholder\"></span>\n }\n <i class=\"fa-solid fa-folder tree-folder-icon\"></i>\n <span class=\"tree-node-label\">{{ node.Name }}</span>\n </div>\n @if (isExpanded(node)) {\n @for (child of getChildren(node); track child.ID) {\n <ng-container *ngTemplateOutlet=\"treeNode; context: { $implicit: child, level: level + 1 }\"></ng-container>\n }\n }\n </div>\n </ng-template>\n\n <!-- Context Menu -->\n @if (contextMenuVisible) {\n <div class=\"context-menu\"\n [style.top.px]=\"contextMenuY\"\n [style.left.px]=\"contextMenuX\"\n (document:click)=\"closeContextMenu()\">\n <button class=\"context-menu-item\" (click)=\"onContextMenuAction('rename')\">\n <i class=\"fa-solid fa-pen\"></i> Rename\n </button>\n <button class=\"context-menu-item\" (click)=\"onContextMenuAction('delete')\" disabled>\n <i class=\"fa-solid fa-trash-can\"></i> Delete\n </button>\n </div>\n }\n\n <mj-dialog\n [Visible]=\"showNew\"\n Title=\"New file category\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"cancelNewCategory()\">\n <div class=\"dialog-form-container\">\n <form #newForm=\"ngForm\">\n <label class=\"mj-form-field\">\n <span class=\"mj-form-label\">Name</span>\n <input\n class=\"mj-input\"\n name=\"name\"\n [(ngModel)]=\"newCategoryName\"\n required\n [disabled]=\"isLoading\" />\n </label>\n </form>\n </div>\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"saveNewCategory()\" [disabled]=\"isLoading\">Save</button>\n <button mjButton (click)=\"cancelNewCategory()\" [disabled]=\"isLoading\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n\n @if (!!renameFileCategory) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Rename file category\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"cancelRename()\">\n <div class=\"dialog-form-container\">\n <form #renameForm=\"ngForm\">\n <label class=\"mj-form-field\">\n <span class=\"mj-form-label\">Name</span>\n <input\n class=\"mj-input\"\n name=\"Name\"\n [(ngModel)]=\"renameFileCategory.Name\"\n required\n [disabled]=\"isLoading\" />\n </label>\n </form>\n </div>\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"saveRename()\" [disabled]=\"isLoading || !renameFileCategory.Dirty\">Save</button>\n <button mjButton (click)=\"cancelRename()\" [disabled]=\"isLoading\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n }\n</div>\n", styles: ["/* Styles for category tree */\n.container {\n display: flex;\n flex-direction: column;\n}\n\n.category-tree {\n width: 250px;\n max-height: 500px;\n overflow-y: auto;\n border: 1px solid var(--mj-border-subtle);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n}\n\n.tree-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding-right: 4px;\n margin-bottom: 4px;\n}\n\n.tree-node-row {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n cursor: pointer;\n border-radius: 4px;\n transition: background-color 0.15s;\n user-select: none;\n}\n\n.tree-node-row:hover {\n background-color: var(--mj-bg-surface-hover);\n}\n\n.tree-node-row.selected {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.tree-expand-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 10px;\n}\n\n.tree-expand-placeholder {\n width: 16px;\n height: 16px;\n display: inline-block;\n}\n\n.tree-folder-icon {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.tree-node-label {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n/* Context Menu */\n.context-menu {\n position: fixed;\n z-index: 10000;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n box-shadow: 0 4px 12px var(--mj-bg-overlay);\n padding: 4px 0;\n min-width: 140px;\n}\n\n.context-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 16px;\n border: none;\n background: none;\n color: var(--mj-text-primary);\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n}\n\n.context-menu-item:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu-item:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.dialog-form-container {\n padding: 8px 0;\n}\n\n.mj-form-field {\n display: flex;\n flex-direction: row;\n align-items: center;\n column-gap: 12px;\n margin-bottom: 8px;\n}\n\n.mj-form-label {\n min-width: 80px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.mj-form-field .mj-input {\n width: 100%;\n}\n"] }]
|
|
211
333
|
}], () => [{ type: i1.SharedService }], { categorySelected: [{
|
|
212
334
|
type: Output
|
|
213
335
|
}] }); })();
|
|
214
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CategoryTreeComponent, { className: "CategoryTreeComponent", filePath: "src/lib/category-tree/category-tree.ts", lineNumber:
|
|
336
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CategoryTreeComponent, { className: "CategoryTreeComponent", filePath: "src/lib/category-tree/category-tree.ts", lineNumber: 13 }); })();
|
|
215
337
|
//# sourceMappingURL=category-tree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"category-tree.js","sourceRoot":"","sources":["../../../src/lib/category-tree/category-tree.ts","../../../src/lib/category-tree/category-tree.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, OnInit, Output } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJFileCategoryEntity } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\n\nimport { ContextMenuSelectEvent } from '@progress/kendo-angular-menu';\nimport { TreeItemAddRemoveArgs } from '@progress/kendo-angular-treeview';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n@Component({\n standalone: false,\n selector: 'mj-files-category-tree',\n templateUrl: './category-tree.html',\n styleUrls: ['./category-tree.css'],\n})\nexport class CategoryTreeComponent implements OnInit {\n @Output() categorySelected = new EventEmitter<string | undefined>();\n\n public isLoading: boolean = false;\n public showNew: boolean = false;\n public newCategoryName = '';\n public selectedKeys = [];\n public renameFileCategory: MJFileCategoryEntity | undefined;\n\n public categoriesData: MJFileCategoryEntity[] = [];\n\n private md = new Metadata();\n\n constructor(private sharedService: SharedService) {}\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async createNewCategory() {\n this.showNew = true;\n }\n\n cancelNewCategory() {\n this.showNew = false;\n }\n\n async handleDrop(e: TreeItemAddRemoveArgs) {\n console.log(e);\n const sourceCategory: MJFileCategoryEntity = e.sourceItem.item.dataItem;\n const targetCategory: MJFileCategoryEntity = e.destinationItem.item.dataItem;\n sourceCategory.ParentID = targetCategory.ID;\n\n this.isLoading = true;\n await sourceCategory.Save();\n this.isLoading = false;\n }\n\n async saveNewCategory() {\n this.isLoading = true;\n const categoryEntity: MJFileCategoryEntity = await this.md.GetEntityObject('MJ: File Categories');\n categoryEntity.NewRecord();\n categoryEntity.Name = this.newCategoryName;\n await categoryEntity?.Save();\n this.categoriesData = [...this.categoriesData, categoryEntity];\n this.showNew = false;\n this.isLoading = false;\n }\n\n async deleteCategory(fileCategory: MJFileCategoryEntity) {\n this.isLoading = true;\n const { ID } = fileCategory;\n const success = await fileCategory.Delete();\n if (!success) {\n console.error('Unable to delete file category:', fileCategory);\n this.sharedService.CreateSimpleNotification(`Unable to delete category '${fileCategory.Name}'`, 'error');\n return;\n }\n\n this.categoriesData = this.categoriesData.filter((c) => !UUIDsEqual(c.ID, ID));\n this.clearSelection();\n this.isLoading = false;\n }\n\n clearSelection() {\n this.selectedKeys = [];\n this.categorySelected.emit(undefined);\n }\n\n handleMenuSelect(e: ContextMenuSelectEvent) {\n const action = e.item?.text?.toLowerCase() ?? '';\n switch (action) {\n case 'rename':\n this.renameFileCategory = e.item.data;\n break;\n\n case 'delete':\n this.deleteCategory(e.item.data);\n break;\n\n default:\n break;\n }\n }\n\n cancelRename() {\n this.renameFileCategory?.Revert();\n this.renameFileCategory = undefined;\n }\n\n async saveRename() {\n this.isLoading = true;\n await this.renameFileCategory?.Save();\n this.renameFileCategory = undefined;\n this.isLoading = false;\n }\n\n async Refresh() {\n this.isLoading = true;\n\n const rv = new RunView();\n const result = await rv.RunView({\n EntityName: 'MJ: File Categories',\n ResultType: 'entity_object',\n });\n\n if (result.Success) {\n this.categoriesData = <MJFileCategoryEntity[]>result.Results;\n } else {\n throw new Error('Error loading file categories: ' + result.ErrorMessage);\n }\n this.isLoading = false;\n }\n}\n","<div class=\"container\">\n <div class=\"tree-header\">\n <button kendoButton (click)=\"clearSelection()\">All Files</button>\n <button kendoButton (click)=\"createNewCategory()\" size=\"small\">Add category</button>\n </div>\n <kendo-treeview\n [nodes]=\"categoriesData\"\n textField=\"Name\"\n kendoTreeViewExpandable\n kendoTreeViewFlatDataBinding\n idField=\"ID\"\n parentIdField=\"ParentID\"\n (selectionChange)=\"categorySelected.emit($event.dataItem.ID)\"\n kendoTreeViewDragAndDrop\n kendoTreeViewSelectable\n (addItem)=\"handleDrop($event)\"\n [selectedKeys]=\"selectedKeys\"\n >\n <ng-template kendoTreeViewNodeTemplate let-dataItem>\n <span #target>{{ dataItem.Name }} </span>\n <kendo-contextmenu [target]=\"target\" (select)=\"handleMenuSelect($event)\">\n <kendo-menu-item text=\"Rename\" [data]=\"dataItem\"> </kendo-menu-item>\n <kendo-menu-item text=\"Delete\" [data]=\"dataItem\" [disabled]=\"true\"> </kendo-menu-item>\n </kendo-contextmenu>\n </ng-template>\n </kendo-treeview>\n\n @if (showNew) {\n <kendo-dialog title=\"New file category\" (close)=\"cancelNewCategory()\" [minWidth]=\"250\" [width]=\"450\">\n <div class=\"container\">\n <form #templateForm=\"ngForm\">\n <kendo-label class=\"k-form\" text=\"Name\">\n <kendo-textbox\n name=\"name\"\n [(ngModel)]=\"newCategoryName\"\n [showSuccessIcon]=\"newCategoryName.length > 0\"\n showErrorIcon=\"initial\"\n required\n [disabled]=\"isLoading\"\n ></kendo-textbox>\n </kendo-label>\n </form>\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelNewCategory()\" [disabled]=\"isLoading\">Cancel</button>\n <button kendoButton (click)=\"saveNewCategory()\" [disabled]=\"isLoading\" themeColor=\"primary\">Save</button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n\n @if (!!renameFileCategory) {\n <kendo-dialog title=\"Rename file category\" (close)=\"cancelRename()\" [minWidth]=\"250\" [width]=\"450\">\n <div class=\"container\">\n <form #templateForm=\"ngForm\">\n <kendo-label class=\"k-form\" text=\"Name\">\n <kendo-textbox\n name=\"Name\"\n [(ngModel)]=\"renameFileCategory.Name\"\n [showSuccessIcon]=\"renameFileCategory.Name.length > 0\"\n showErrorIcon=\"initial\"\n required\n [disabled]=\"isLoading\"\n ></kendo-textbox>\n </kendo-label>\n </form>\n </div>\n <kendo-dialog-actions>\n <button kendoButton (click)=\"cancelRename()\" [disabled]=\"isLoading\">Cancel</button>\n <button kendoButton (click)=\"saveRename()\" [disabled]=\"isLoading || !renameFileCategory.Dirty\" themeColor=\"primary\">Save</button>\n </kendo-dialog-actions>\n </kendo-dialog>\n }\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"category-tree.js","sourceRoot":"","sources":["../../../src/lib/category-tree/category-tree.ts","../../../src/lib/category-tree/category-tree.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAU,MAAM,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;;;;;;;;ICI9C,wBAAkG;;;IAAlG,+FAAmF;;;;;IAAxC,AAA5B,8CAA4B,gEAAsC;;;;IAW7E,kCAAqE;IAArC,2PAAS,oCAA0B,KAAC;IAClE,wBAAgH;IAClH,iBAAS;;;;IADa,cAA4C;IAAC,AAA7C,+DAA4C,+CAA2C;;;IAG7G,2BAA6C;;;IAO7C,wBAA2G;;;IAA3G,2HAA4F;;;;;;IAAjD,AAA5B,8CAA4B,+EAA+C;;;IAD5F,gIAEC;;;;IAFD,cAAA,2BAAiB,CAEhB;;;;IAjBH,AADF,+BAA4D,cAIT;IAA5C,AADA,gNAAS,0BAAgB,KAAC,qNACX,qCAA2B,KAAC;IAK5C,AAJF,yGAAyB,iFAIhB;IAGT,wBAAmD;IACnD,gCAA8B;IAAA,YAAe;IAC/C,AAD+C,iBAAO,EAChD;IACN,2FAAwB;IAK1B,iBAAM;;;;;IApBiB,mDAAoC;IAEpD,cAAmC;IAAnC,sDAAmC;IAGtC,cAMC;IAND,qDAMC;IAE6B,eAAe;IAAf,kCAAe;IAE/C,cAIC;IAJD,qDAIC;;;;IAMH,+BAG2C;IAAtC,wLAAkB,yBAAkB,2BAAC;IACxC,kCAA0E;IAAxC,2LAAS,2BAAoB,QAAQ,CAAC,KAAC;IACvE,wBAA+B;IAAC,wBAClC;IAAA,iBAAS;IACT,kCAAmF;IAAjD,2LAAS,2BAAoB,QAAQ,CAAC,KAAC;IACvE,wBAAqC;IAAC,wBACxC;IACF,AADE,iBAAS,EACL;;;IARD,AADA,gDAA6B,mCACC;;;;IAqCnC,qCAK2B;IAAzB,8LAAS,qBAAc,KAAC;IAIlB,AADF,AADF,AADF,+BAAmC,oBACN,gBACI,eACC;IAAA,oBAAI;IAAA,iBAAO;IACvC,iCAK2B;IAFzB,6UAAqC;IAK7C,AADE,AADE,AANE,iBAK2B,EACrB,EACH,EACH;IAEJ,AADF,yCAAmB,iBAC6F;IAA3E,2LAAS,mBAAY,KAAC;IAAqD,qBAAI;IAAA,iBAAS;IAC3H,mCAAiE;IAAhD,4LAAS,qBAAc,KAAC;IAAwB,uBAAM;IAE3E,AADE,AADyE,iBAAS,EAC9D,EACV;;;IAnBV,AADA,AAFA,8BAAgB,cAEH,iBACG;IASR,eAAqC;IAArC,8DAAqC;IAErC,2CAAsB;IAK8B,eAAmD;IAAnD,+EAAmD;IACnE,eAAsB;IAAtB,2CAAsB;;ADtFxE,MAAM,OAAO,qBAAqB;IAwBZ;IAvBV,gBAAgB,GAAG,IAAI,YAAY,EAAsB,CAAC;IAE7D,SAAS,GAAY,KAAK,CAAC;IAC3B,OAAO,GAAY,KAAK,CAAC;IACzB,eAAe,GAAG,EAAE,CAAC;IACrB,kBAAkB,CAAmC;IAErD,cAAc,GAA2B,EAAE,CAAC;IAEnD,qCAAqC;IAC9B,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,iCAAiC;IACzB,UAAU,CAAqB;IAEvC,yBAAyB;IAClB,kBAAkB,GAAG,KAAK,CAAC;IAC3B,YAAY,GAAG,CAAC,CAAC;IACjB,YAAY,GAAG,CAAC,CAAC;IAChB,eAAe,CAAmC;IAElD,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE5B,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD,QAAQ;QACN,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,4CAA4C;IAC5C,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,qCAAqC;IACrC,WAAW,CAAC,IAA0B;QACpC,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,kCAAkC;IAClC,WAAW,CAAC,IAA0B;QACpC,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,oCAAoC;IACpC,UAAU,CAAC,IAA0B;QACnC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,YAAY,CAAC,IAA0B,EAAE,KAAY;QACnD,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,UAAU,CAAC,IAA0B;QACnC,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,sCAAsC;IACtC,UAAU,CAAC,IAA0B;QACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,yCAAyC;IACzC,aAAa,CAAC,KAAiB,EAAE,IAA0B;QACzD,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;QAClC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;QAClC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;IACjC,CAAC;IAED,+BAA+B;IAC/B,gBAAgB;QACd,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;IACnC,CAAC;IAED,6CAA6C;IAC7C,mBAAmB,CAAC,MAAc;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC;QAClC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,QAAQ;gBACX,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;gBAC/B,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAC1B,MAAM;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,cAAc,GAAyB,MAAM,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC;QAClG,cAAc,CAAC,SAAS,EAAE,CAAC;QAC3B,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC;QAC3C,MAAM,cAAc,EAAE,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,YAAkC;QACrD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE,GAAG,YAAY,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,YAAY,CAAC,CAAC;YAC/D,IAAI,CAAC,aAAa,CAAC,wBAAwB,CAAC,8BAA8B,YAAY,CAAC,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;YACzG,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,YAAY;QACV,IAAI,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,IAAI,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;YAC9B,UAAU,EAAE,qBAAqB;YACjC,UAAU,EAAE,eAAe;SAC5B,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,GAA2B,MAAM,CAAC,OAAO,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;+GA7KU,qBAAqB;6DAArB,qBAAqB;;YCV9B,AADF,AADF,8BAAuB,aACI,gBACqB;YAA3B,wIAAS,oBAAgB,KAAC;YAAC,yBAAS;YAAA,iBAAS;YAC9D,iCAA2E;YAA9B,wIAAS,uBAAmB,KAAC;YAAC,4BAAY;YACzF,AADyF,iBAAS,EAC5F;YAEN,8BAA2B;YACzB,oGAEC;YACH,iBAAM;YAEN,uHAAkD;YAyBlD,yFAA0B;YAc1B,qCAKgC;YAA9B,4IAAS,uBAAmB,KAAC;YAIvB,AADF,AADF,AADF,gCAAmC,qBACT,iBACO,gBACC;YAAA,qBAAI;YAAA,iBAAO;YACvC,kCAK2B;YAFzB,qQAA6B;YAKrC,AADE,AADE,AANE,iBAK2B,EACrB,EACH,EACH;YAEJ,AADF,0CAAmB,kBACqE;YAAnD,yIAAS,qBAAiB,KAAC;YAAwB,qBAAI;YAAA,iBAAS;YACnG,mCAAsE;YAArD,yIAAS,uBAAmB,KAAC;YAAwB,uBAAM;YAEhF,AADE,AAD8E,iBAAS,EACnE,EACV;YAEZ,iGAA4B;YA0B9B,iBAAM;;YA/FF,eAEC;YAFD,4BAEC;YA4BH,eAYC;YAZD,kDAYC;YAGC,cAAmB;YAGnB,AADA,AAFA,qCAAmB,cAEN,iBACG;YASR,eAA6B;YAA7B,mDAA6B;YAE7B,wCAAsB;YAKmC,eAAsB;YAAtB,wCAAsB;YACtC,eAAsB;YAAtB,wCAAsB;YAIzE,eAyBC;YAzBD,oDAyBC;;;iFDzFU,qBAAqB;cANjC,SAAS;6BACI,KAAK,YACP,wBAAwB;;kBAKjC,MAAM;;kFADI,qBAAqB","sourcesContent":["import { Component, EventEmitter, OnInit, Output } from '@angular/core';\nimport { Metadata, RunView } from '@memberjunction/core';\nimport { MJFileCategoryEntity } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n@Component({\n standalone: false,\n selector: 'mj-files-category-tree',\n templateUrl: './category-tree.html',\n styleUrls: ['./category-tree.css'],\n})\nexport class CategoryTreeComponent implements OnInit {\n @Output() categorySelected = new EventEmitter<string | undefined>();\n\n public isLoading: boolean = false;\n public showNew: boolean = false;\n public newCategoryName = '';\n public renameFileCategory: MJFileCategoryEntity | undefined;\n\n public categoriesData: MJFileCategoryEntity[] = [];\n\n /** Expanded node IDs for the tree */\n public expandedIds = new Set<string>();\n\n /** Currently selected node ID */\n private selectedId: string | undefined;\n\n /** Context menu state */\n public contextMenuVisible = false;\n public contextMenuX = 0;\n public contextMenuY = 0;\n private contextMenuNode: MJFileCategoryEntity | undefined;\n\n private md = new Metadata();\n\n constructor(private sharedService: SharedService) {}\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n /** Returns root-level nodes (no parent). */\n get rootNodes(): MJFileCategoryEntity[] {\n return this.categoriesData.filter((c) => !c.ParentID);\n }\n\n /** Checks if a node has children. */\n hasChildren(node: MJFileCategoryEntity): boolean {\n return this.categoriesData.some((c) => UUIDsEqual(c.ParentID, node.ID));\n }\n\n /** Returns children of a node. */\n getChildren(node: MJFileCategoryEntity): MJFileCategoryEntity[] {\n return this.categoriesData.filter((c) => UUIDsEqual(c.ParentID, node.ID));\n }\n\n /** Checks if a node is expanded. */\n isExpanded(node: MJFileCategoryEntity): boolean {\n return this.expandedIds.has(node.ID);\n }\n\n /** Toggles expand/collapse on a node. */\n toggleExpand(node: MJFileCategoryEntity, event: Event): void {\n event.stopPropagation();\n if (this.expandedIds.has(node.ID)) {\n this.expandedIds.delete(node.ID);\n } else {\n this.expandedIds.add(node.ID);\n }\n }\n\n /** Checks if a node is the currently selected node. */\n isSelected(node: MJFileCategoryEntity): boolean {\n return this.selectedId != null && UUIDsEqual(this.selectedId, node.ID);\n }\n\n /** Selects a node and emits event. */\n selectNode(node: MJFileCategoryEntity): void {\n this.selectedId = node.ID;\n this.categorySelected.emit(node.ID);\n }\n\n /** Opens context menu on right-click. */\n onContextMenu(event: MouseEvent, node: MJFileCategoryEntity): void {\n event.preventDefault();\n event.stopPropagation();\n this.contextMenuNode = node;\n this.contextMenuX = event.clientX;\n this.contextMenuY = event.clientY;\n this.contextMenuVisible = true;\n }\n\n /** Closes the context menu. */\n closeContextMenu(): void {\n this.contextMenuVisible = false;\n this.contextMenuNode = undefined;\n }\n\n /** Handles context menu action selection. */\n onContextMenuAction(action: string): void {\n const node = this.contextMenuNode;\n this.closeContextMenu();\n if (!node) {\n return;\n }\n\n switch (action) {\n case 'rename':\n this.renameFileCategory = node;\n break;\n case 'delete':\n this.deleteCategory(node);\n break;\n }\n }\n\n async createNewCategory() {\n this.showNew = true;\n }\n\n cancelNewCategory() {\n this.showNew = false;\n }\n\n async saveNewCategory() {\n this.isLoading = true;\n const categoryEntity: MJFileCategoryEntity = await this.md.GetEntityObject('MJ: File Categories');\n categoryEntity.NewRecord();\n categoryEntity.Name = this.newCategoryName;\n await categoryEntity?.Save();\n this.categoriesData = [...this.categoriesData, categoryEntity];\n this.showNew = false;\n this.newCategoryName = '';\n this.isLoading = false;\n }\n\n async deleteCategory(fileCategory: MJFileCategoryEntity) {\n this.isLoading = true;\n const { ID } = fileCategory;\n const success = await fileCategory.Delete();\n if (!success) {\n console.error('Unable to delete file category:', fileCategory);\n this.sharedService.CreateSimpleNotification(`Unable to delete category '${fileCategory.Name}'`, 'error');\n this.isLoading = false;\n return;\n }\n\n this.categoriesData = this.categoriesData.filter((c) => !UUIDsEqual(c.ID, ID));\n this.clearSelection();\n this.isLoading = false;\n }\n\n clearSelection() {\n this.selectedId = undefined;\n this.categorySelected.emit(undefined);\n }\n\n cancelRename() {\n this.renameFileCategory?.Revert();\n this.renameFileCategory = undefined;\n }\n\n async saveRename() {\n this.isLoading = true;\n await this.renameFileCategory?.Save();\n this.renameFileCategory = undefined;\n this.isLoading = false;\n }\n\n async Refresh() {\n this.isLoading = true;\n\n const rv = new RunView();\n const result = await rv.RunView({\n EntityName: 'MJ: File Categories',\n ResultType: 'entity_object',\n });\n\n if (result.Success) {\n this.categoriesData = <MJFileCategoryEntity[]>result.Results;\n } else {\n throw new Error('Error loading file categories: ' + result.ErrorMessage);\n }\n this.isLoading = false;\n }\n}\n","<div class=\"container\">\n <div class=\"tree-header\">\n <button mjButton (click)=\"clearSelection()\">All Files</button>\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"createNewCategory()\">Add category</button>\n </div>\n\n <div class=\"category-tree\">\n @for (node of rootNodes; track node.ID) {\n <ng-container *ngTemplateOutlet=\"treeNode; context: { $implicit: node, level: 0 }\"></ng-container>\n }\n </div>\n\n <ng-template #treeNode let-node let-level=\"level\">\n <div class=\"tree-node\" [style.padding-left.px]=\"level * 20\">\n <div class=\"tree-node-row\"\n [class.selected]=\"isSelected(node)\"\n (click)=\"selectNode(node)\"\n (contextmenu)=\"onContextMenu($event, node)\">\n @if (hasChildren(node)) {\n <button class=\"tree-expand-btn\" (click)=\"toggleExpand(node, $event)\">\n <i class=\"fa-solid\" [class.fa-chevron-right]=\"!isExpanded(node)\" [class.fa-chevron-down]=\"isExpanded(node)\"></i>\n </button>\n } @else {\n <span class=\"tree-expand-placeholder\"></span>\n }\n <i class=\"fa-solid fa-folder tree-folder-icon\"></i>\n <span class=\"tree-node-label\">{{ node.Name }}</span>\n </div>\n @if (isExpanded(node)) {\n @for (child of getChildren(node); track child.ID) {\n <ng-container *ngTemplateOutlet=\"treeNode; context: { $implicit: child, level: level + 1 }\"></ng-container>\n }\n }\n </div>\n </ng-template>\n\n <!-- Context Menu -->\n @if (contextMenuVisible) {\n <div class=\"context-menu\"\n [style.top.px]=\"contextMenuY\"\n [style.left.px]=\"contextMenuX\"\n (document:click)=\"closeContextMenu()\">\n <button class=\"context-menu-item\" (click)=\"onContextMenuAction('rename')\">\n <i class=\"fa-solid fa-pen\"></i> Rename\n </button>\n <button class=\"context-menu-item\" (click)=\"onContextMenuAction('delete')\" disabled>\n <i class=\"fa-solid fa-trash-can\"></i> Delete\n </button>\n </div>\n }\n\n <mj-dialog\n [Visible]=\"showNew\"\n Title=\"New file category\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"cancelNewCategory()\">\n <div class=\"dialog-form-container\">\n <form #newForm=\"ngForm\">\n <label class=\"mj-form-field\">\n <span class=\"mj-form-label\">Name</span>\n <input\n class=\"mj-input\"\n name=\"name\"\n [(ngModel)]=\"newCategoryName\"\n required\n [disabled]=\"isLoading\" />\n </label>\n </form>\n </div>\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"saveNewCategory()\" [disabled]=\"isLoading\">Save</button>\n <button mjButton (click)=\"cancelNewCategory()\" [disabled]=\"isLoading\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n\n @if (!!renameFileCategory) {\n <mj-dialog\n [Visible]=\"true\"\n Title=\"Rename file category\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"cancelRename()\">\n <div class=\"dialog-form-container\">\n <form #renameForm=\"ngForm\">\n <label class=\"mj-form-field\">\n <span class=\"mj-form-label\">Name</span>\n <input\n class=\"mj-input\"\n name=\"Name\"\n [(ngModel)]=\"renameFileCategory.Name\"\n required\n [disabled]=\"isLoading\" />\n </label>\n </form>\n </div>\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"saveRename()\" [disabled]=\"isLoading || !renameFileCategory.Dirty\">Save</button>\n <button mjButton (click)=\"cancelRename()\" [disabled]=\"isLoading\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n }\n</div>\n"]}
|