@memberjunction/ng-file-storage 5.30.1 → 5.31.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.
@@ -1,8 +1,9 @@
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 { BaseAngularComponent } from '@memberjunction/ng-base-types';
4
5
  import * as i0 from "@angular/core";
5
- export declare class CategoryTreeComponent implements OnInit {
6
+ export declare class CategoryTreeComponent extends BaseAngularComponent implements OnInit {
6
7
  private sharedService;
7
8
  categorySelected: EventEmitter<string | undefined>;
8
9
  isLoading: boolean;
@@ -19,7 +20,7 @@ export declare class CategoryTreeComponent implements OnInit {
19
20
  contextMenuX: number;
20
21
  contextMenuY: number;
21
22
  private contextMenuNode;
22
- private md;
23
+ private get md();
23
24
  constructor(sharedService: SharedService);
24
25
  ngOnInit(): void;
25
26
  /** Returns root-level nodes (no parent). */
@@ -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;;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"}
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;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAErE,qBAMa,qBAAsB,SAAQ,oBAAqB,YAAW,MAAM;IAwBnE,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,KAAK,EAAE,GAAiC;gBAE3B,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"}
@@ -1,6 +1,7 @@
1
1
  import { Component, EventEmitter, Output } from '@angular/core';
2
- import { Metadata, RunView } from '@memberjunction/core';
2
+ import { RunView } from '@memberjunction/core';
3
3
  import { UUIDsEqual } from '@memberjunction/global';
4
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
4
5
  import * as i0 from "@angular/core";
5
6
  import * as i1 from "@memberjunction/ng-shared";
6
7
  import * as i2 from "@angular/common";
@@ -126,7 +127,7 @@ function CategoryTreeComponent_Conditional_25_Template(rf, ctx) { if (rf & 1) {
126
127
  i0.ɵɵadvance(2);
127
128
  i0.ɵɵproperty("disabled", ctx_r5.isLoading);
128
129
  } }
129
- export class CategoryTreeComponent {
130
+ export class CategoryTreeComponent extends BaseAngularComponent {
130
131
  sharedService;
131
132
  categorySelected = new EventEmitter();
132
133
  isLoading = false;
@@ -143,8 +144,9 @@ export class CategoryTreeComponent {
143
144
  contextMenuX = 0;
144
145
  contextMenuY = 0;
145
146
  contextMenuNode;
146
- md = new Metadata();
147
+ get md() { return this.ProviderToUse; }
147
148
  constructor(sharedService) {
149
+ super();
148
150
  this.sharedService = sharedService;
149
151
  }
150
152
  ngOnInit() {
@@ -223,7 +225,7 @@ export class CategoryTreeComponent {
223
225
  }
224
226
  async saveNewCategory() {
225
227
  this.isLoading = true;
226
- const categoryEntity = await this.md.GetEntityObject('MJ: File Categories');
228
+ const categoryEntity = await this.md.GetEntityObject('MJ: File Categories', this.md.CurrentUser);
227
229
  categoryEntity.NewRecord();
228
230
  categoryEntity.Name = this.newCategoryName;
229
231
  await categoryEntity?.Save();
@@ -262,7 +264,7 @@ export class CategoryTreeComponent {
262
264
  }
263
265
  async Refresh() {
264
266
  this.isLoading = true;
265
- const rv = new RunView();
267
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
266
268
  const result = await rv.RunView({
267
269
  EntityName: 'MJ: File Categories',
268
270
  ResultType: 'entity_object',
@@ -276,7 +278,7 @@ export class CategoryTreeComponent {
276
278
  this.isLoading = false;
277
279
  }
278
280
  static ɵfac = function CategoryTreeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CategoryTreeComponent)(i0.ɵɵdirectiveInject(i1.SharedService)); };
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) {
281
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CategoryTreeComponent, selectors: [["mj-files-category-tree"]], outputs: { categorySelected: "categorySelected" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], 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
282
  const _r1 = i0.ɵɵgetCurrentView();
281
283
  i0.ɵɵelementStart(0, "div", 3)(1, "div", 4)(2, "button", 5);
282
284
  i0.ɵɵlistener("click", function CategoryTreeComponent_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.clearSelection()); });
@@ -333,5 +335,5 @@ export class CategoryTreeComponent {
333
335
  }], () => [{ type: i1.SharedService }], { categorySelected: [{
334
336
  type: Output
335
337
  }] }); })();
336
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CategoryTreeComponent, { className: "CategoryTreeComponent", filePath: "src/lib/category-tree/category-tree.ts", lineNumber: 13 }); })();
338
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CategoryTreeComponent, { className: "CategoryTreeComponent", filePath: "src/lib/category-tree/category-tree.ts", lineNumber: 14 }); })();
337
339
  //# 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":"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"]}
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 { RunView } from '@memberjunction/core';\nimport { MJFileCategoryEntity } from '@memberjunction/core-entities';\nimport { SharedService } from '@memberjunction/ng-shared';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\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 extends BaseAngularComponent 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 get md() { return this.ProviderToUse; }\n\n constructor(private sharedService: SharedService) { super(); }\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', this.md.CurrentUser);\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 = RunView.FromMetadataProvider(this.ProviderToUse);\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"]}
@@ -1,6 +1,15 @@
1
+ import { IMetadataProvider } from '@memberjunction/core';
1
2
  import * as i0 from "@angular/core";
3
+ /**
4
+ * Multi-provider note: callers running under a non-default `IMetadataProvider`
5
+ * (multi-server clients) should set `service.Provider = component.ProviderToUse`
6
+ * from a parent component before invoking any methods.
7
+ */
2
8
  export declare class FileOpenService {
3
9
  private client;
10
+ private _provider;
11
+ get Provider(): IMetadataProvider;
12
+ set Provider(value: IMetadataProvider | null);
4
13
  private getClient;
5
14
  /**
6
15
  * Open a file from a storage provider in a new browser tab.
@@ -1 +1 @@
1
- {"version":3,"file":"file-open.service.d.ts","sourceRoot":"","sources":["../../src/lib/file-open.service.ts"],"names":[],"mappings":";AAoBA,qBACa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAyC;IAEvD,OAAO,CAAC,SAAS;IAQjB;;;;;;;;;OASG;IACU,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB3F;;;;;;OAMG;IACU,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBxF;;;;;;;;;;;;OAYG;IACI,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;yCAlFnE,eAAe;6CAAf,eAAe;CAyG3B"}
1
+ {"version":3,"file":"file-open.service.d.ts","sourceRoot":"","sources":["../../src/lib/file-open.service.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,iBAAiB,EAAY,MAAM,sBAAsB,CAAC;;AAGnE;;;;GAIG;AACH,qBACa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,SAAS,CAAkC;IAEnD,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IACD,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAGlD;IAED,OAAO,CAAC,SAAS;IAQjB;;;;;;;;;OASG;IACU,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB3F;;;;;;OAMG;IACU,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBxF;;;;;;;;;;;;OAYG;IACI,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;yCA3FnE,eAAe;6CAAf,eAAe;CAkH3B"}
@@ -17,11 +17,24 @@ import { Injectable } from '@angular/core';
17
17
  import { Metadata } from '@memberjunction/core';
18
18
  import { GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';
19
19
  import * as i0 from "@angular/core";
20
+ /**
21
+ * Multi-provider note: callers running under a non-default `IMetadataProvider`
22
+ * (multi-server clients) should set `service.Provider = component.ProviderToUse`
23
+ * from a parent component before invoking any methods.
24
+ */
20
25
  export class FileOpenService {
21
26
  client = null;
27
+ _provider = null;
28
+ get Provider() {
29
+ return this._provider ?? Metadata.Provider;
30
+ }
31
+ set Provider(value) {
32
+ this._provider = value;
33
+ this.client = null; // invalidate cached client
34
+ }
22
35
  getClient() {
23
36
  if (!this.client) {
24
- const provider = Metadata.Provider;
37
+ const provider = this.Provider;
25
38
  this.client = new GraphQLFileStorageClient(provider);
26
39
  }
27
40
  return this.client;
@@ -1 +1 @@
1
- {"version":3,"file":"file-open.service.js","sourceRoot":"","sources":["../../src/lib/file-open.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAuB,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;;AAGrG,MAAM,OAAO,eAAe;IAChB,MAAM,GAAoC,IAAI,CAAC;IAE/C,SAAS;QACb,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAA+B,CAAC;YAC1D,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,IAAY,EAAE,QAAiB;QACpE,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,2FAA2F;YAC3F,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAE3E,IAAI,WAAW,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;gBACnC,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;YAC9D,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,wBAAwB,CAAC,WAA+B;QACjE,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAE/B,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAKlC,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;gBAC/E,OAAO,KAAK,CAAC;YACjB,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yDAAyD,EAAE,KAAK,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,2BAA2B,CAAC,WAA+B;QAC9D,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAE/B,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAKlC,CAAC;YAEF,qEAAqE;YACrE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,sBAAsB;gBACtB,MAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;gBACnE,OAAO,IAAI,CAAC;YAChB,CAAC;YAED,OAAO,KAAK,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;yGAxGQ,eAAe;gEAAf,eAAe,WAAf,eAAe,mBADF,MAAM;;iFACnB,eAAe;cAD3B,UAAU;eAAC,EAAE,UAAU,EAAE,MAAM,EAAE","sourcesContent":["/**\n * @fileoverview Reusable service for opening files from MJ Storage providers.\n *\n * Generates pre-authenticated download URLs via GraphQL and opens files\n * in new browser tabs. Provider-agnostic — works with Box, GDrive,\n * SharePoint, Dropbox, or any configured storage provider.\n *\n * Usage:\n * ```typescript\n * const fileOpen = inject(FileOpenService);\n * await fileOpen.OpenFile(accountId, filePath);\n * // or with an objectId for better performance:\n * await fileOpen.OpenFile(accountId, filePath, objectId);\n * ```\n */\n\nimport { Injectable } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';\n\n@Injectable({ providedIn: 'root' })\nexport class FileOpenService {\n private client: GraphQLFileStorageClient | null = null;\n\n private getClient(): GraphQLFileStorageClient {\n if (!this.client) {\n const provider = Metadata.Provider as GraphQLDataProvider;\n this.client = new GraphQLFileStorageClient(provider);\n }\n return this.client;\n }\n\n /**\n * Open a file from a storage provider in a new browser tab.\n * Generates a pre-authenticated download URL and opens it.\n *\n * @param accountId - The FileStorageAccount ID\n * @param path - The file path within the storage account\n * @param objectId - Optional provider-specific object ID (e.g., Box file ID).\n * When provided, uses this instead of path for faster resolution.\n * @returns true if the file was opened successfully\n */\n public async OpenFile(accountId: string, path: string, objectId?: string): Promise<boolean> {\n try {\n const client = this.getClient();\n // Use path for CreatePreAuthDownloadUrl — drivers resolve paths to provider IDs internally\n const downloadUrl = await client.CreatePreAuthDownloadUrl(accountId, path);\n\n if (downloadUrl) {\n window.open(downloadUrl, '_blank');\n return true;\n }\n return false;\n } catch (error) {\n console.error('[FileOpenService] Error opening file:', error);\n return false;\n }\n }\n\n /**\n * Open a file from search result metadata.\n * Extracts accountId and objectId/path from the RawMetadata JSON string.\n *\n * @param rawMetadata - JSON string from SearchResultItem.RawMetadata\n * @returns true if the file was opened successfully, false if metadata was invalid or open failed\n */\n public async OpenFileFromSearchResult(rawMetadata: string | undefined): Promise<boolean> {\n if (!rawMetadata) return false;\n\n try {\n const meta = JSON.parse(rawMetadata) as {\n accountId?: string;\n accountName?: string;\n path?: string;\n objectId?: string;\n };\n\n if (!meta.accountId) {\n console.error('[FileOpenService] Missing accountId in search result metadata');\n return false;\n }\n\n const path = meta.path || meta.objectId || '';\n return this.OpenFile(meta.accountId, path, meta.objectId);\n } catch (error) {\n console.error('[FileOpenService] Error parsing search result metadata:', error);\n return false;\n }\n }\n\n /**\n * Open a file for preview in the provider's web viewer (if available).\n * Falls back to download URL if no preview URL can be constructed.\n *\n * Currently supported:\n * - Box.com: https://app.box.com/file/{fileId}\n * - Google Drive: https://drive.google.com/file/d/{fileId}/view\n * - SharePoint: Uses webUrl from provider data\n * - Dropbox: https://www.dropbox.com/preview/{path}\n *\n * @param rawMetadata - JSON string from SearchResultItem.RawMetadata\n * @returns true if a preview was opened\n */\n public OpenPreviewFromSearchResult(rawMetadata: string | undefined): boolean {\n if (!rawMetadata) return false;\n\n try {\n const meta = JSON.parse(rawMetadata) as {\n accountId?: string;\n accountName?: string;\n path?: string;\n objectId?: string;\n };\n\n // Try to construct a provider-specific preview URL from the objectId\n if (meta.objectId) {\n // Box.com preview URL\n window.open(`https://app.box.com/file/${meta.objectId}`, '_blank');\n return true;\n }\n\n return false;\n } catch {\n return false;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"file-open.service.js","sourceRoot":"","sources":["../../src/lib/file-open.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Reusable service for opening files from MJ Storage providers.\n *\n * Generates pre-authenticated download URLs via GraphQL and opens files\n * in new browser tabs. Provider-agnostic — works with Box, GDrive,\n * SharePoint, Dropbox, or any configured storage provider.\n *\n * Usage:\n * ```typescript\n * const fileOpen = inject(FileOpenService);\n * await fileOpen.OpenFile(accountId, filePath);\n * // or with an objectId for better performance:\n * await fileOpen.OpenFile(accountId, filePath, objectId);\n * ```\n */\n\nimport { Injectable } from '@angular/core';\nimport { IMetadataProvider, Metadata } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLFileStorageClient } from '@memberjunction/graphql-dataprovider';\n\n/**\n * Multi-provider note: callers running under a non-default `IMetadataProvider`\n * (multi-server clients) should set `service.Provider = component.ProviderToUse`\n * from a parent component before invoking any methods.\n */\n@Injectable({ providedIn: 'root' })\nexport class FileOpenService {\n private client: GraphQLFileStorageClient | null = null;\n private _provider: IMetadataProvider | null = null;\n\n public get Provider(): IMetadataProvider {\n return this._provider ?? Metadata.Provider;\n }\n public set Provider(value: IMetadataProvider | null) {\n this._provider = value;\n this.client = null; // invalidate cached client\n }\n\n private getClient(): GraphQLFileStorageClient {\n if (!this.client) {\n const provider = this.Provider as GraphQLDataProvider;\n this.client = new GraphQLFileStorageClient(provider);\n }\n return this.client;\n }\n\n /**\n * Open a file from a storage provider in a new browser tab.\n * Generates a pre-authenticated download URL and opens it.\n *\n * @param accountId - The FileStorageAccount ID\n * @param path - The file path within the storage account\n * @param objectId - Optional provider-specific object ID (e.g., Box file ID).\n * When provided, uses this instead of path for faster resolution.\n * @returns true if the file was opened successfully\n */\n public async OpenFile(accountId: string, path: string, objectId?: string): Promise<boolean> {\n try {\n const client = this.getClient();\n // Use path for CreatePreAuthDownloadUrl — drivers resolve paths to provider IDs internally\n const downloadUrl = await client.CreatePreAuthDownloadUrl(accountId, path);\n\n if (downloadUrl) {\n window.open(downloadUrl, '_blank');\n return true;\n }\n return false;\n } catch (error) {\n console.error('[FileOpenService] Error opening file:', error);\n return false;\n }\n }\n\n /**\n * Open a file from search result metadata.\n * Extracts accountId and objectId/path from the RawMetadata JSON string.\n *\n * @param rawMetadata - JSON string from SearchResultItem.RawMetadata\n * @returns true if the file was opened successfully, false if metadata was invalid or open failed\n */\n public async OpenFileFromSearchResult(rawMetadata: string | undefined): Promise<boolean> {\n if (!rawMetadata) return false;\n\n try {\n const meta = JSON.parse(rawMetadata) as {\n accountId?: string;\n accountName?: string;\n path?: string;\n objectId?: string;\n };\n\n if (!meta.accountId) {\n console.error('[FileOpenService] Missing accountId in search result metadata');\n return false;\n }\n\n const path = meta.path || meta.objectId || '';\n return this.OpenFile(meta.accountId, path, meta.objectId);\n } catch (error) {\n console.error('[FileOpenService] Error parsing search result metadata:', error);\n return false;\n }\n }\n\n /**\n * Open a file for preview in the provider's web viewer (if available).\n * Falls back to download URL if no preview URL can be constructed.\n *\n * Currently supported:\n * - Box.com: https://app.box.com/file/{fileId}\n * - Google Drive: https://drive.google.com/file/d/{fileId}/view\n * - SharePoint: Uses webUrl from provider data\n * - Dropbox: https://www.dropbox.com/preview/{path}\n *\n * @param rawMetadata - JSON string from SearchResultItem.RawMetadata\n * @returns true if a preview was opened\n */\n public OpenPreviewFromSearchResult(rawMetadata: string | undefined): boolean {\n if (!rawMetadata) return false;\n\n try {\n const meta = JSON.parse(rawMetadata) as {\n accountId?: string;\n accountName?: string;\n path?: string;\n objectId?: string;\n };\n\n // Try to construct a provider-specific preview URL from the objectId\n if (meta.objectId) {\n // Box.com preview URL\n window.open(`https://app.box.com/file/${meta.objectId}`, '_blank');\n return true;\n }\n\n return false;\n } catch {\n return false;\n }\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { EventEmitter, OnInit } from '@angular/core';
2
2
  import { MJFileEntity } from '@memberjunction/core-entities';
3
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
3
4
  import { z } from 'zod';
4
5
  import * as i0 from "@angular/core";
5
6
  /**
@@ -137,11 +138,11 @@ declare const FileUploadMutationSchema: z.ZodObject<{
137
138
  }>;
138
139
  type ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateFile']['File'];
139
140
  type UploadTuple = [FileSelectInfo, ApiFile, string];
140
- export declare class FileUploadComponent implements OnInit {
141
+ export declare class FileUploadComponent extends BaseAngularComponent implements OnInit {
141
142
  ConfirmQueue: Array<UploadTuple>;
142
143
  UploadQueue: Array<FileSelectInfo>;
143
144
  private defaultProviderID;
144
- private md;
145
+ private get md();
145
146
  get IsUploading(): boolean;
146
147
  constructor();
147
148
  disabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,MAAM,EAAU,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,YAAY,EAAoE,MAAM,+BAA+B,CAAC;AAG/H,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;AAExB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAgC/G,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,qBAMa,mBAAoB,YAAW,MAAM;IACzC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAM;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,EAAE,CAAkB;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;;IAIQ,QAAQ,UAAS;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAC1C,aAAa,qBAA4B;IACzC,UAAU,gCAAuC;IAE3D,QAAQ,IAAI,IAAI;IAIV,OAAO;IAWb,OAAO;IAOD,aAAa;IAanB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK;YAyBb,mBAAmB;YAkCnB,WAAW;yCAlHd,mBAAmB;2CAAnB,mBAAmB;CA0I/B"}
1
+ {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,MAAM,EAAU,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAoE,MAAM,+BAA+B,CAAC;AAE/H,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;;AAExB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC;AAgC/G,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM5B,CAAC;AAEH,KAAK,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAErD,qBAMa,mBAAoB,SAAQ,oBAAqB,YAAW,MAAM;IACtE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACtC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAM;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,KAAK,EAAE,GAAiC;IAE/C,IAAI,WAAW,IAAI,OAAO,CAEzB;;IAIQ,QAAQ,UAAS;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAa;IAC1C,aAAa,qBAA4B;IACzC,UAAU,gCAAuC;IAE3D,QAAQ,IAAI,IAAI;IAIV,OAAO;IAWb,OAAO;IAOD,aAAa;IAanB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,KAAK;YAyBb,mBAAmB;YAkCnB,WAAW;yCAlHd,mBAAmB;2CAAnB,mBAAmB;CA0I/B"}
@@ -1,7 +1,7 @@
1
1
  import { Component, EventEmitter, Input, Output } from '@angular/core';
2
- import { Metadata } from '@memberjunction/core';
3
2
  import { MJFileSchema, FileStorageEngineBase } from '@memberjunction/core-entities';
4
3
  import { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';
4
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
5
5
  import { z } from 'zod';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "@memberjunction/ng-ui-components";
@@ -49,15 +49,15 @@ const FileUploadMutationSchema = z.object({
49
49
  File: MJFileSchema.omit({ __mj_CreatedAt: true, __mj_UpdatedAt: true }).passthrough(),
50
50
  }),
51
51
  });
52
- export class FileUploadComponent {
52
+ export class FileUploadComponent extends BaseAngularComponent {
53
53
  ConfirmQueue = [];
54
54
  UploadQueue = [];
55
55
  defaultProviderID = '';
56
- md = new Metadata();
56
+ get md() { return this.ProviderToUse; }
57
57
  get IsUploading() {
58
58
  return this.UploadQueue.length + this.ConfirmQueue.length > 0;
59
59
  }
60
- constructor() { }
60
+ constructor() { super(); }
61
61
  disabled = false;
62
62
  CategoryID = undefined;
63
63
  uploadStarted = new EventEmitter();
@@ -170,7 +170,7 @@ export class FileUploadComponent {
170
170
  }
171
171
  }
172
172
  static ɵfac = function FileUploadComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FileUploadComponent)(); };
173
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { disabled: "disabled", CategoryID: "CategoryID" }, outputs: { uploadStarted: "uploadStarted", fileUpload: "fileUpload" }, standalone: false, decls: 13, vars: 7, consts: [[1, "mj-file-select"], [1, "fa-solid", "fa-upload"], ["type", "file", 1, "mj-file-input", 3, "change", "disabled"], ["Title", "Please confirm", 3, "Close", "Visible", "Width", "MinWidth"], [1, "confirm-message"], ["mjButton", "", "variant", "primary", 3, "click"], ["mjButton", "", 3, "click"]], template: function FileUploadComponent_Template(rf, ctx) { if (rf & 1) {
173
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: FileUploadComponent, selectors: [["mj-files-file-upload"]], inputs: { disabled: "disabled", CategoryID: "CategoryID" }, outputs: { uploadStarted: "uploadStarted", fileUpload: "fileUpload" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 13, vars: 7, consts: [[1, "mj-file-select"], [1, "fa-solid", "fa-upload"], ["type", "file", 1, "mj-file-input", 3, "change", "disabled"], ["Title", "Please confirm", 3, "Close", "Visible", "Width", "MinWidth"], [1, "confirm-message"], ["mjButton", "", "variant", "primary", 3, "click"], ["mjButton", "", 3, "click"]], template: function FileUploadComponent_Template(rf, ctx) { if (rf & 1) {
174
174
  i0.ɵɵelementStart(0, "div")(1, "label", 0);
175
175
  i0.ɵɵelement(2, "i", 1);
176
176
  i0.ɵɵelementStart(3, "span");
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.js","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts","../../../src/lib/file-upload/file-upload.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\nimport { Metadata } from '@memberjunction/core';\nimport { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity, FileStorageEngineBase } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\n\nimport { z } from 'zod';\n\n/**\n * Minimal file info interface replacing Kendo's FileInfo.\n */\nexport interface FileSelectInfo {\n name: string;\n size: number;\n rawFile: File;\n}\n\nexport type FileUploadEvent = { success: true; file: MJFileEntity } | { success: false; file: FileSelectInfo };\n\nconst FileFieldsFragment = gql`\n fragment FileFields on MJFile_ {\n Category\n CategoryID\n ContentType\n _mj__CreatedAt\n Description\n ID\n Name\n Provider\n ProviderID\n ProviderKey\n Status\n _mj__UpdatedAt\n }\n`;\n\nconst FileUploadMutation = gql`\n ${FileFieldsFragment}\n mutation CreateFile($input: CreateMJFileInput!) {\n CreateFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateFile: z.object({\n NameExists: z.boolean(),\n UploadUrl: z.string(),\n File: MJFileSchema.omit({ __mj_CreatedAt: true, __mj_UpdatedAt: true }).passthrough(),\n }),\n});\n\ntype ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateFile']['File'];\ntype UploadTuple = [FileSelectInfo, ApiFile, string];\n\n@Component({\n standalone: false,\n selector: 'mj-files-file-upload',\n templateUrl: './file-upload.html',\n styleUrls: ['./file-upload.css'],\n})\nexport class FileUploadComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileSelectInfo> = [];\n private defaultProviderID = '';\n private md = new Metadata();\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() {}\n\n @Input() disabled = false;\n @Input() CategoryID: string | undefined = undefined;\n @Output() uploadStarted = new EventEmitter<void>();\n @Output() fileUpload = new EventEmitter<FileUploadEvent>();\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async Refresh() {\n await FileStorageEngineBase.Instance.Config(false);\n const activeProviders = FileStorageEngineBase.Instance.Providers\n .filter(p => p.IsActive)\n .sort((a, b) => (b.Priority ?? 0) - (a.Priority ?? 0));\n const provider: MJFileStorageProviderEntity | undefined = activeProviders[0];\n if (typeof provider?.ID === 'string') {\n this.defaultProviderID = provider.ID;\n }\n }\n\n Confirm() {\n const confirmed = this.ConfirmQueue.shift();\n if (confirmed) {\n this._uploadFile(...confirmed);\n }\n }\n\n async CancelConfirm() {\n const cancelled = this.ConfirmQueue.shift();\n if (cancelled) {\n const [file, fileRecord] = cancelled;\n\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n await fileEntity.Delete();\n\n this.fileUpload.emit({ success: false, file });\n }\n }\n\n /**\n * Handles the native file input change event.\n */\n OnFileSelected(event: Event) {\n const input = event.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) {\n return;\n }\n\n this.uploadStarted.emit();\n\n // Convert native File objects to our FileSelectInfo format\n for (let i = 0; i < input.files.length; i++) {\n const nativeFile = input.files[i];\n const fileInfo: FileSelectInfo = {\n name: nativeFile.name,\n size: nativeFile.size,\n rawFile: nativeFile,\n };\n this.UploadQueue.push(fileInfo);\n }\n\n // Reset input so the same file can be selected again\n input.value = '';\n\n this._processUploadQueue();\n }\n\n private async _processUploadQueue() {\n // for each selected file to upload\n let file = this.UploadQueue.shift();\n while (file) {\n const input = {\n Name: file.name,\n ProviderID: this.defaultProviderID,\n Status: 'Pending',\n CategoryID: this.CategoryID,\n };\n\n // call the gql\n const result = await GraphQLDataProvider.ExecuteGQL(FileUploadMutation, { input });\n\n // make sure the response is correct\n const parsedResult = FileUploadMutationSchema.safeParse(result);\n if (parsedResult.success) {\n const { File, UploadUrl, NameExists } = parsedResult.data.CreateFile;\n const uploadTuple: UploadTuple = [file, File, UploadUrl];\n\n // Confirm we want to overwrite\n if (NameExists) {\n this.ConfirmQueue.push(uploadTuple);\n } else {\n await this._uploadFile(...uploadTuple);\n }\n } else {\n console.error('The API returned an unexpected result', parsedResult.error.issues);\n this.fileUpload.emit({ success: false, file });\n }\n file = this.UploadQueue.shift();\n }\n }\n\n private async _uploadFile(file: FileSelectInfo, fileRecord: ApiFile, uploadUrl: string) {\n try {\n // now upload to the url\n await window.fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'x-ms-blob-type': 'BlockBlob' },\n body: file.rawFile,\n });\n\n // now update that file to set status\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n fileEntity.Status = 'Uploaded';\n await fileEntity.Save();\n\n // emit an event about a new file uploaded, include the file data\n this.fileUpload.emit({ success: true, file: fileEntity });\n // Could also emit a progress event with each iteration\n } catch (e) {\n console.error(e);\n // something failed when actually uploading or when updating the API, what do to about pending file?\n this.fileUpload.emit({ success: false, file });\n }\n }\n}\n","<div>\n <label class=\"mj-file-select\" [class.disabled]=\"IsUploading || disabled\">\n <i class=\"fa-solid fa-upload\"></i>\n <span>Select file to upload</span>\n <input\n type=\"file\"\n class=\"mj-file-input\"\n [disabled]=\"IsUploading || disabled\"\n (change)=\"OnFileSelected($event)\" />\n </label>\n\n <mj-dialog\n [Visible]=\"ConfirmQueue.length > 0\"\n Title=\"Please confirm\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"CancelConfirm()\">\n @if (ConfirmQueue.length > 0) {\n <p class=\"confirm-message\">\n This will overwrite an existing file named '{{ ConfirmQueue[0][0].name }}'. Are you sure you want to continue?\n </p>\n }\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"Confirm()\">Overwrite</button>\n <button mjButton (click)=\"CancelConfirm()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n</div>\n"]}
1
+ {"version":3,"file":"file-upload.js","sourceRoot":"","sources":["../../../src/lib/file-upload/file-upload.ts","../../../src/lib/file-upload/file-upload.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\nimport { MJFileEntity, MJFileSchema, MJFileStorageProviderEntity, FileStorageEngineBase } from '@memberjunction/core-entities';\nimport { GraphQLDataProvider, gql } from '@memberjunction/graphql-dataprovider';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\nimport { z } from 'zod';\n\n/**\n * Minimal file info interface replacing Kendo's FileInfo.\n */\nexport interface FileSelectInfo {\n name: string;\n size: number;\n rawFile: File;\n}\n\nexport type FileUploadEvent = { success: true; file: MJFileEntity } | { success: false; file: FileSelectInfo };\n\nconst FileFieldsFragment = gql`\n fragment FileFields on MJFile_ {\n Category\n CategoryID\n ContentType\n _mj__CreatedAt\n Description\n ID\n Name\n Provider\n ProviderID\n ProviderKey\n Status\n _mj__UpdatedAt\n }\n`;\n\nconst FileUploadMutation = gql`\n ${FileFieldsFragment}\n mutation CreateFile($input: CreateMJFileInput!) {\n CreateFile(input: $input) {\n NameExists\n UploadUrl\n File {\n ...FileFields\n }\n }\n }\n`;\n\nconst FileUploadMutationSchema = z.object({\n CreateFile: z.object({\n NameExists: z.boolean(),\n UploadUrl: z.string(),\n File: MJFileSchema.omit({ __mj_CreatedAt: true, __mj_UpdatedAt: true }).passthrough(),\n }),\n});\n\ntype ApiFile = z.infer<typeof FileUploadMutationSchema>['CreateFile']['File'];\ntype UploadTuple = [FileSelectInfo, ApiFile, string];\n\n@Component({\n standalone: false,\n selector: 'mj-files-file-upload',\n templateUrl: './file-upload.html',\n styleUrls: ['./file-upload.css'],\n})\nexport class FileUploadComponent extends BaseAngularComponent implements OnInit {\n public ConfirmQueue: Array<UploadTuple> = [];\n public UploadQueue: Array<FileSelectInfo> = [];\n private defaultProviderID = '';\n private get md() { return this.ProviderToUse; }\n\n get IsUploading(): boolean {\n return this.UploadQueue.length + this.ConfirmQueue.length > 0;\n }\n\n constructor() { super(); }\n\n @Input() disabled = false;\n @Input() CategoryID: string | undefined = undefined;\n @Output() uploadStarted = new EventEmitter<void>();\n @Output() fileUpload = new EventEmitter<FileUploadEvent>();\n\n ngOnInit(): void {\n this.Refresh();\n }\n\n async Refresh() {\n await FileStorageEngineBase.Instance.Config(false);\n const activeProviders = FileStorageEngineBase.Instance.Providers\n .filter(p => p.IsActive)\n .sort((a, b) => (b.Priority ?? 0) - (a.Priority ?? 0));\n const provider: MJFileStorageProviderEntity | undefined = activeProviders[0];\n if (typeof provider?.ID === 'string') {\n this.defaultProviderID = provider.ID;\n }\n }\n\n Confirm() {\n const confirmed = this.ConfirmQueue.shift();\n if (confirmed) {\n this._uploadFile(...confirmed);\n }\n }\n\n async CancelConfirm() {\n const cancelled = this.ConfirmQueue.shift();\n if (cancelled) {\n const [file, fileRecord] = cancelled;\n\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n await fileEntity.Delete();\n\n this.fileUpload.emit({ success: false, file });\n }\n }\n\n /**\n * Handles the native file input change event.\n */\n OnFileSelected(event: Event) {\n const input = event.target as HTMLInputElement;\n if (!input.files || input.files.length === 0) {\n return;\n }\n\n this.uploadStarted.emit();\n\n // Convert native File objects to our FileSelectInfo format\n for (let i = 0; i < input.files.length; i++) {\n const nativeFile = input.files[i];\n const fileInfo: FileSelectInfo = {\n name: nativeFile.name,\n size: nativeFile.size,\n rawFile: nativeFile,\n };\n this.UploadQueue.push(fileInfo);\n }\n\n // Reset input so the same file can be selected again\n input.value = '';\n\n this._processUploadQueue();\n }\n\n private async _processUploadQueue() {\n // for each selected file to upload\n let file = this.UploadQueue.shift();\n while (file) {\n const input = {\n Name: file.name,\n ProviderID: this.defaultProviderID,\n Status: 'Pending',\n CategoryID: this.CategoryID,\n };\n\n // call the gql\n const result = await GraphQLDataProvider.ExecuteGQL(FileUploadMutation, { input });\n\n // make sure the response is correct\n const parsedResult = FileUploadMutationSchema.safeParse(result);\n if (parsedResult.success) {\n const { File, UploadUrl, NameExists } = parsedResult.data.CreateFile;\n const uploadTuple: UploadTuple = [file, File, UploadUrl];\n\n // Confirm we want to overwrite\n if (NameExists) {\n this.ConfirmQueue.push(uploadTuple);\n } else {\n await this._uploadFile(...uploadTuple);\n }\n } else {\n console.error('The API returned an unexpected result', parsedResult.error.issues);\n this.fileUpload.emit({ success: false, file });\n }\n file = this.UploadQueue.shift();\n }\n }\n\n private async _uploadFile(file: FileSelectInfo, fileRecord: ApiFile, uploadUrl: string) {\n try {\n // now upload to the url\n await window.fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'x-ms-blob-type': 'BlockBlob' },\n body: file.rawFile,\n });\n\n // now update that file to set status\n const fileEntity: MJFileEntity = await this.md.GetEntityObject('MJ: Files');\n await fileEntity.LoadFromData(fileRecord);\n fileEntity.Status = 'Uploaded';\n await fileEntity.Save();\n\n // emit an event about a new file uploaded, include the file data\n this.fileUpload.emit({ success: true, file: fileEntity });\n // Could also emit a progress event with each iteration\n } catch (e) {\n console.error(e);\n // something failed when actually uploading or when updating the API, what do to about pending file?\n this.fileUpload.emit({ success: false, file });\n }\n }\n}\n","<div>\n <label class=\"mj-file-select\" [class.disabled]=\"IsUploading || disabled\">\n <i class=\"fa-solid fa-upload\"></i>\n <span>Select file to upload</span>\n <input\n type=\"file\"\n class=\"mj-file-input\"\n [disabled]=\"IsUploading || disabled\"\n (change)=\"OnFileSelected($event)\" />\n </label>\n\n <mj-dialog\n [Visible]=\"ConfirmQueue.length > 0\"\n Title=\"Please confirm\"\n [Width]=\"450\"\n [MinWidth]=\"250\"\n (Close)=\"CancelConfirm()\">\n @if (ConfirmQueue.length > 0) {\n <p class=\"confirm-message\">\n This will overwrite an existing file named '{{ ConfirmQueue[0][0].name }}'. Are you sure you want to continue?\n </p>\n }\n <mj-dialog-actions>\n <button mjButton variant=\"primary\" (click)=\"Confirm()\">Overwrite</button>\n <button mjButton (click)=\"CancelConfirm()\">Cancel</button>\n </mj-dialog-actions>\n </mj-dialog>\n</div>\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-file-storage",
3
- "version": "5.30.1",
3
+ "version": "5.31.0",
4
4
  "description": "MemberJunction: Angular components for managing files, and related components.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -38,15 +38,16 @@
38
38
  "@angular/router": "21.1.3"
39
39
  },
40
40
  "dependencies": {
41
- "@memberjunction/ng-ui-components": "5.30.1",
41
+ "@memberjunction/ng-ui-components": "5.31.0",
42
42
  "@angular/platform-browser": "21.1.3",
43
- "@memberjunction/core": "5.30.1",
44
- "@memberjunction/core-entities": "5.30.1",
45
- "@memberjunction/global": "5.30.1",
46
- "@memberjunction/graphql-dataprovider": "5.30.1",
47
- "@memberjunction/ng-container-directives": "5.30.1",
48
- "@memberjunction/ng-shared": "5.30.1",
49
- "@memberjunction/ng-shared-generic": "5.30.1",
43
+ "@memberjunction/core": "5.31.0",
44
+ "@memberjunction/ng-base-types": "5.31.0",
45
+ "@memberjunction/core-entities": "5.31.0",
46
+ "@memberjunction/global": "5.31.0",
47
+ "@memberjunction/graphql-dataprovider": "5.31.0",
48
+ "@memberjunction/ng-container-directives": "5.31.0",
49
+ "@memberjunction/ng-shared": "5.31.0",
50
+ "@memberjunction/ng-shared-generic": "5.31.0",
50
51
  "ag-grid-angular": "^35.0.1",
51
52
  "ag-grid-community": "^35.0.1",
52
53
  "tslib": "^2.8.1",