@memberjunction/ng-list-management 5.46.0 → 5.48.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/components/list-management-dialog/list-management-dialog.component.d.ts +15 -3
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.js +37 -4
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.js.map +1 -1
- package/dist/lib/models/list-management.models.d.ts +15 -0
- package/dist/lib/models/list-management.models.d.ts.map +1 -1
- package/dist/lib/models/list-management.models.js.map +1 -1
- package/dist/lib/services/list-management.service.d.ts.map +1 -1
- package/dist/lib/services/list-management.service.js +49 -27
- package/dist/lib/services/list-management.service.js.map +1 -1
- package/dist/lib/utils/record-display-field.d.ts +36 -0
- package/dist/lib/utils/record-display-field.d.ts.map +1 -0
- package/dist/lib/utils/record-display-field.js +37 -0
- package/dist/lib/utils/record-display-field.js.map +1 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +12 -12
|
@@ -19,15 +19,27 @@ export declare class ListManagementDialogComponent extends BaseAngularComponent
|
|
|
19
19
|
private listService;
|
|
20
20
|
private cdr;
|
|
21
21
|
/**
|
|
22
|
-
* Configuration for the dialog
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
* Configuration for the dialog.
|
|
23
|
+
*
|
|
24
|
+
* Initialization is deliberately order-independent with {@link visible}:
|
|
25
|
+
* Angular assigns inputs in template attribute order, so a host binding
|
|
26
|
+
* `[visible]` before `[config]` would otherwise open the dialog while
|
|
27
|
+
* `config` is still undefined — `loadData()` would bail silently and the
|
|
28
|
+
* dialog would render permanently empty.
|
|
29
|
+
*/
|
|
30
|
+
get config(): ListManagementDialogConfig;
|
|
31
|
+
set config(value: ListManagementDialogConfig);
|
|
32
|
+
private _config;
|
|
25
33
|
/**
|
|
26
34
|
* Controls dialog visibility
|
|
27
35
|
*/
|
|
28
36
|
get visible(): boolean;
|
|
29
37
|
set visible(value: boolean);
|
|
30
38
|
private _visible;
|
|
39
|
+
/** Set on each closed→open transition; cleared once init actually runs (requires config). */
|
|
40
|
+
private _pendingInit;
|
|
41
|
+
/** Runs initialization once per open, as soon as BOTH visible and config are available. */
|
|
42
|
+
private tryInitialize;
|
|
31
43
|
/**
|
|
32
44
|
* Emitted when dialog is closed with results
|
|
33
45
|
*/
|
package/dist/lib/components/list-management-dialog/list-management-dialog.component.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management-dialog.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/list-management-dialog/list-management-dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EACZ,MAAM,EACN,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAE/E,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,cAAc,EAGf,MAAM,qCAAqC,CAAC;;AAE7C;;;;;;;;;;GAUG;AACH,qBAMa,6BAA8B,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"list-management-dialog.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/list-management-dialog/list-management-dialog.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -405,9 +405,22 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
405
405
|
listService;
|
|
406
406
|
cdr;
|
|
407
407
|
/**
|
|
408
|
-
* Configuration for the dialog
|
|
408
|
+
* Configuration for the dialog.
|
|
409
|
+
*
|
|
410
|
+
* Initialization is deliberately order-independent with {@link visible}:
|
|
411
|
+
* Angular assigns inputs in template attribute order, so a host binding
|
|
412
|
+
* `[visible]` before `[config]` would otherwise open the dialog while
|
|
413
|
+
* `config` is still undefined — `loadData()` would bail silently and the
|
|
414
|
+
* dialog would render permanently empty.
|
|
409
415
|
*/
|
|
410
|
-
config
|
|
416
|
+
get config() {
|
|
417
|
+
return this._config;
|
|
418
|
+
}
|
|
419
|
+
set config(value) {
|
|
420
|
+
this._config = value;
|
|
421
|
+
this.tryInitialize();
|
|
422
|
+
}
|
|
423
|
+
_config;
|
|
411
424
|
/**
|
|
412
425
|
* Controls dialog visibility
|
|
413
426
|
*/
|
|
@@ -416,11 +429,21 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
416
429
|
}
|
|
417
430
|
set visible(value) {
|
|
418
431
|
if (value && !this._visible) {
|
|
419
|
-
this.
|
|
432
|
+
this._pendingInit = true;
|
|
420
433
|
}
|
|
421
434
|
this._visible = value;
|
|
435
|
+
this.tryInitialize();
|
|
422
436
|
}
|
|
423
437
|
_visible = false;
|
|
438
|
+
/** Set on each closed→open transition; cleared once init actually runs (requires config). */
|
|
439
|
+
_pendingInit = false;
|
|
440
|
+
/** Runs initialization once per open, as soon as BOTH visible and config are available. */
|
|
441
|
+
tryInitialize() {
|
|
442
|
+
if (this._pendingInit && this._visible && this._config) {
|
|
443
|
+
this._pendingInit = false;
|
|
444
|
+
void this.initializeDialog();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
424
447
|
/**
|
|
425
448
|
* Emitted when dialog is closed with results
|
|
426
449
|
*/
|
|
@@ -524,6 +547,10 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
524
547
|
* Initialize dialog when opened
|
|
525
548
|
*/
|
|
526
549
|
async initializeDialog() {
|
|
550
|
+
// Per ListManagementService's multi-provider contract: thread this
|
|
551
|
+
// component's Provider input into the (root-injected) service. Null is
|
|
552
|
+
// fine — the service falls back to the global provider.
|
|
553
|
+
this.listService.Provider = this.Provider;
|
|
527
554
|
this.resetState();
|
|
528
555
|
await this.loadData();
|
|
529
556
|
}
|
|
@@ -806,13 +833,17 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
806
833
|
action: 'apply',
|
|
807
834
|
added: [],
|
|
808
835
|
removed: [],
|
|
809
|
-
newListsCreated: this.newlyCreatedLists
|
|
836
|
+
newListsCreated: this.newlyCreatedLists,
|
|
837
|
+
summary: { added: 0, removed: 0, skipped: 0, failed: 0 }
|
|
810
838
|
};
|
|
811
839
|
try {
|
|
812
840
|
// Process additions
|
|
813
841
|
if (this.addedToLists.size > 0) {
|
|
814
842
|
const addResult = await this.listService.addRecordsToLists([...this.addedToLists], this.config.recordIds, true // Skip duplicates
|
|
815
843
|
);
|
|
844
|
+
result.summary.added += addResult.success;
|
|
845
|
+
result.summary.skipped += addResult.skipped;
|
|
846
|
+
result.summary.failed += addResult.failed;
|
|
816
847
|
for (const listId of this.addedToLists) {
|
|
817
848
|
const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));
|
|
818
849
|
if (vm) {
|
|
@@ -827,6 +858,8 @@ export class ListManagementDialogComponent extends BaseAngularComponent {
|
|
|
827
858
|
// Process removals
|
|
828
859
|
if (this.removedFromLists.size > 0) {
|
|
829
860
|
const removeResult = await this.listService.removeRecordsFromLists([...this.removedFromLists], this.config.recordIds);
|
|
861
|
+
result.summary.removed += removeResult.success;
|
|
862
|
+
result.summary.failed += removeResult.failed;
|
|
830
863
|
for (const listId of this.removedFromLists) {
|
|
831
864
|
const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));
|
|
832
865
|
if (vm) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/components/list-management-dialog/list-management-dialog.component.ts","../../../../src/lib/components/list-management-dialog/list-management-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EAIb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIzD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;;;;;;;;ICgBxC,kCAAqD;IAAxB,iNAAS,oBAAa,KAAC;IAClD,2BAA8C;IAChD,iBAAS;;;;IAKX,kCAAyF;IAA3D,iNAAS,2BAAoB,KAAC;IAC1D,2BAAsC;IACtC,gCAA0B;IAAA,mBAAG;IAC/B,AAD+B,iBAAO,EAC7B;;;IAHoD,gDAA2B;;;IAsE9E,kCAAgC;IAAA,YAAmB;IAAA,iBAAS;;;IAApD,wCAAuB;IAAC,cAAmB;IAAnB,sCAAmB;;;;IAHvD,AADF,+BAAwB,iBACyD;IAApD,uWAA+B;IACxD,kCAAyB;IAAA,2BAAW;IAAA,iBAAS;IAC7C,gJAEC;IAEL,AADE,iBAAS,EACL;;;IANuB,cAA+B;IAA/B,wDAA+B;IAAC,wCAAmB;IACpE,cAAgB;IAAhB,8BAAgB;IACxB,eAEC;IAFD,gCAEC;;;IAUD,2BAAiD;;;;IAxCzD,AADF,+BAAyB,cACS;IAC9B,2BAA6C;IAC7C,4BAAM;IAAA,+BAAe;IACvB,AADuB,iBAAO,EACxB;IAGF,AADF,AADF,+BAA8B,cACJ,gBAQpB;IAHA,2UAAyB;IAEzB,4NAAe,mBAAY,KAAC;IAEhC,AARE,iBAOE,EACE;IAEJ,AADF,+BAAwB,mBAMX;IAFT,4VAAgC;IAGlC,+BAAA;IACF,AADE,iBAAW,EACP;IACN,+HAA6B;IAW3B,AADF,gCAAiC,kBAIc;IAD3C,kNAAS,mBAAY,KAAC;IAEtB,gIAAc;IAGd,8BACF;IAAA,iBAAS;IACT,mCAAmF;IAAjD,kNAAS,yBAAkB,KAAC;IAC5D,yBACF;IAGN,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF;;;IAvCE,eAAyB;IAAzB,kDAAyB;IACzB,wCAAmB;IAQnB,eAAgC;IAAhC,yDAAgC;IAChC,wCAAmB;IAIvB,eASC;IATD,wDASC;IAKG,eAA0C;IAA1C,sEAA0C;IAC1C,cAEC;IAFD,yCAEC;IAG4D,eAAmB;IAAnB,wCAAmB;;;IAWtF,+BAA2B;IACzB,iCAA+D;IACjE,iBAAM;;;IAGJ,qCAI0C;;;;IAE1C,0CAMoC;IAAlC,yOAAU,2BAAoB,KAAC;IANjC,iBAMoC;;;IAFlC,qFAAgE;;;IALlE,AANF,wIAAkB,kHAMT;;;IANT,2CAcC;;;IAmBa,2BAAuC;;;IAEvC,2BAAsC;;;;IAR1C,kCAIiH;IAD/G,kRAAS,+BAAoB,KAAC;IAI5B,AAFF,kJAA2D,4HAElD;IAGX,iBAAS;;;;IARP,8FAAsE;IAEtE,yIAA8G;IAC9G,cAIC;IAJD,4FAIC;;;IAUC,2BAAsC;;;IAEtC,2BAAuC;;;;IAR3C,kCAIsH;IADpH,mRAAS,kCAAuB,KAAC;IAI/B,AAFF,kJAAkE,4HAEzD;IAGX,iBAAS;;;;IARP,qGAA6E;IAE7E,8IAAmH;IACnH,cAIC;IAJD,mGAIC;;;IAWD,gCAA8B;IAAA,mBAAG;IAAA,iBAAO;;;IAKxC,gCAA+B;IAAA,YAAyB;IAAA,iBAAO;IAC/D,gCAA6B;IAAA,sBAAC;IAAA,iBAAO;;;IADN,cAAyB;IAAzB,6CAAyB;;;IAW5D,+BAAmE;IACjE,uBAA6C;IAC7C,gCAA8B;IAAA,YAA2B;IAC3D,AAD2D,iBAAO,EAC5D;;;;IAH4B,gDAAgC;IAC1D,cAA+B;IAA/B,+CAA+B;IACP,eAA2B;IAA3B,sDAA2B;;;IArD7D,AAPF,+BAI4D,cAG5B;IAC5B,sIAAyB;IAazB,sIAAuE;IAazE,iBAAM;IAIJ,AADF,+BAA+B,cACC;IAC5B,2BAAkD;IAClD,gCAAwB;IAAA,YAAkB;IAAA,iBAAO;IACjD,oIAA2C;IAG7C,iBAAM;IACN,gCAA4B;IAC1B,0HAA2B;IAI3B,iCAAyB;IAAA,aAA0D;IAAA,iBAAO;IAC1F,iCAA6B;IAAA,uBAAC;IAAA,iBAAO;IACrC,iCAA2B;IAAA,aAAgC;IAE/D,AADE,AAD6D,iBAAO,EAC9D,EACF;IAGN,qIAAuC;IAMzC,iBAAM;;;;IA3DJ,AADA,AADA,kGAA0E,8FACU,4DAC3B;IAIvD,eAYC;IAZD,uDAYC;IACD,cAYC;IAZD,6GAYC;IAOyB,eAAkB;IAAlB,sCAAkB;IAC1C,cAEC;IAFD,yEAEC;IAGD,eAGC;IAHD,mDAGC;IACwB,eAA0D;IAA1D,uFAA0D;IAExD,eAAgC;IAAhC,2DAAgC;IAK/D,cAKC;IALD,kEAKC;;;IAhEP,+BAAwB;IACtB,gIAiEC;IACH,iBAAM;;;IAlEJ,cAiEC;IAjED,mCAiEC;;;IAUC,gCAA+B;IAC7B,2BAA6C;IAC7C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,2FACF;;;IAGA,gCAAkC;IAChC,2BAA8C;IAC9C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,iGACF;;;IAVF,8HAAoB;IAMpB,8HAAuB;;;IANvB,8CAKC;IACD,cAKC;IALD,iDAKC;;;IAED,gCAA4B;IAAA,0BAAU;IAAA,iBAAO;;;IAY3C,2BAAiD;;;;IA7P7D,8BAAiD;IAArB,8LAAS,iBAAU,KAAC;IAC9C,8BAAiE;IAAnC,iKAAS,wBAAwB,KAAC;IAI1D,AADF,AADF,8BAA2B,aACG,aACD;IACvB,0BAAgD;IAClD,iBAAM;IAEJ,AADF,8BAAyB,YACE;IAAA,YAAiB;IAAA,iBAAK;IAC/C,4BAA2B;IAAA,aAAoB;IAEnD,AADE,AADiD,iBAAI,EAC/C,EACF;IACN,mCAAgE;IAAnC,kMAAS,iBAAU,KAAC;IAC/C,4BAAuC;IAE3C,AADE,iBAAS,EACL;IAIJ,AADF,gCAA4B,eACF;IACtB,4BAAoD;IACpD,kCAME;IADA,uMAAS,4BAAqB,KAAC;IALjC,iBAME;IACF,mHAAkB;IAKpB,iBAAM;IAEN,mHAAoC;IAMtC,iBAAM;IAKF,AADF,AADF,gCAAyB,eACA,kBAIW;IAA9B,kMAAS,oBAAa,KAAK,CAAC,KAAC;IAC7B,sBACF;IAAA,iBAAS;IACT,mCAGqC;IAAnC,kMAAS,oBAAa,UAAU,CAAC,KAAC;IAClC,2BACF;IAAA,iBAAS;IACT,mCAGmC;IAAjC,kMAAS,oBAAa,QAAQ,CAAC,KAAC;IAChC,yBACF;IACF,AADE,iBAAS,EACL;IAEJ,AADF,gCAAwB,kBAC+E;IAApD,0MAAU,yCAAwC,KAAC;IAClG,mCAAqB;IAAA,2BAAU;IAAA,iBAAS;IACxC,mCAAuB;IAAA,6BAAY;IAAA,iBAAS;IAC5C,mCAA2B;IAAA,4BAAW;IAG5C,AADE,AADE,AADwC,iBAAS,EACxC,EACL,EACF;IAGN,iHAAsB;IAuDtB,gCAA0B;IAqBtB,AAhBA,AAJF,gHAAe,+EAI0B,0FAgBhC;IAsEX,iBAAM;IAIJ,AADF,gCAA2B,eACG;IAcxB,AAbF,qGAAkB,2FAaT;IAGX,iBAAM;IAEJ,AADF,gCAA4B,kBACiD;IAAzC,kMAAS,iBAAU,KAAC;IACpD,yBACF;IAAA,iBAAS;IACT,mCAGqC;IADnC,kMAAS,qBAAc,KAAC;IAExB,iHAAc;IAGd,gCACF;IAIR,AADE,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF,EACF;;;IA3P6B,eAAiB;IAAjB,wCAAiB;IACf,eAAoB;IAApB,2CAAoB;IAgB/C,eAAoB;IAApB,yCAAoB;IAGtB,cAIC;IAJD,6CAIC;IAGH,cAKC;IALD,+DAKC;IAQG,eAAoC;IAApC,oDAAoC;IAMpC,eAAyC;IAAzC,yDAAyC;IAMzC,eAAuC;IAAvC,uDAAuC;IAMb,eAAoB;IAApB,yCAAoB;IASpD,eAoDC;IApDD,iDAoDC;IAIC,eAyFC;IAzFD,mFAyFC;IAMC,eAeC;IAfD,6CAeC;IAGsD,eAAmB;IAAnB,wCAAmB;IAMxE,eAAkC;IAAlC,8DAAkC;IAClC,cAEC;IAFD,yCAEC;;ADrOb;;;;;;;;;;GAUG;AAOH,MAAM,OAAO,6BAA8B,SAAQ,oBAAoB;IA4D3D;IACA;IA5DV;;OAEG;IACM,MAAM,CAA8B;IAE7C;;OAEG;IACH,IACI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,CAAC,KAAc;QACxB,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IACO,QAAQ,GAAG,KAAK,CAAC;IAEzB;;OAEG;IACO,QAAQ,GAAG,IAAI,YAAY,EAAwB,CAAC;IAE9D;;OAEG;IACO,MAAM,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE5C,QAAQ;IACR,OAAO,GAAG,KAAK,CAAC;IAChB,MAAM,GAAG,KAAK,CAAC;IACf,UAAU,GAAG,EAAE,CAAC;IAChB,SAAS,GAAkB,KAAK,CAAC;IACjC,UAAU,GAAmB,MAAM,CAAC;IACpC,cAAc,GAAG,KAAK,CAAC;IAEvB,OAAO;IACP,QAAQ,GAAwB,EAAE,CAAC;IACnC,aAAa,GAAwB,EAAE,CAAC;IACxC,UAAU,GAA2B,EAAE,CAAC;IAExC,oBAAoB;IACpB,WAAW,GAAG,EAAE,CAAC;IACjB,kBAAkB,GAAG,EAAE,CAAC;IACxB,iBAAiB,GAAkB,IAAI,CAAC;IAExC,gBAAgB;IACR,kBAAkB,GAAG,IAAI,GAAG,EAAmB,CAAC;IACjD,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC;IACtC,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC1C,iBAAiB,GAAmB,EAAE,CAAC;IAE9C,UAAU;IACF,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,aAAa,GAAG,IAAI,OAAO,EAAU,CAAC;IAE9C,YACU,WAAkC,EAClC,GAAsB;QAEhC,KAAK,EAAE,CAAC;QAHE,gBAAW,GAAX,WAAW,CAAuB;QAClC,QAAG,GAAH,GAAG,CAAmB;IAExB,CAAC;IAET,QAAQ;QACN,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,WAAW,UAAU,CAAC;QAE7E,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YAC1B,KAAK,KAAK;gBACR,OAAO,OAAO,UAAU,WAAW,CAAC;YACtC,KAAK,QAAQ;gBACX,OAAO,UAAU,UAAU,aAAa,CAAC;YAC3C;gBACE,OAAO,wBAAwB,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,SAAS,CAAC;QAExD,IAAI,WAAW,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,UAAU,EAAE,CAAC;QACrE,CAAC;QAED,OAAO,GAAG,WAAW,IAAI,UAAU,UAAU,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC9E,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;IACpC,CAAC;IAED;;OAEG;IACK,mBAAmB;QACzB,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,YAAY,CAAC,GAAG,CAAC,EACjB,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC,SAAS,CAAC,CAAC,UAAkB,EAAE,EAAE;YACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB;QAC5B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;YAE9B,wCAAwC;YACxC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACxD,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,EAAE,CAAC,WAAW,CAAC,EAAE,EACjB,IAAI,CAAC,gBAAgB;iBACtB;gBACD,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,IAAI,CAAC,MAAM,CAAC,SAAS,CACtB;gBACD,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE;aACrC,CAAC,CAAC;YAEH,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAE7B,oBAAoB;YACpB,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,mBAAmB,CACxD,KAAK,EACL,IAAI,CAAC,MAAM,CAAC,SAAS,EACrB,UAAU,CACX,CAAC;YAEF,kCAAkC;YAClC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,eAAe,CAAC,CAAC;YACjF,CAAC;YAED,iCAAiC;YACjC,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBACnC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;oBACpD,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC;wBAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAChC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,KAAY;QACxB,MAAM,KAAK,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,GAAkB;QAC7B,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,MAAsB;QAClC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEhC,sBAAsB;QACtB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAC1B,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC3C,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CACtD,CAAC;QACJ,CAAC;QAED,mBAAmB;QACnB,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,KAAK,UAAU;gBACb,uCAAuC;gBACvC,MAAM;YACR,KAAK,QAAQ;gBACX,uCAAuC;gBACvC,MAAM,GAAG,MAAM;qBACZ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;qBACjE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChB,MAAM;YACR,uDAAuD;QACzD,CAAC;QAED,gBAAgB;QAChB,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9D,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;gBACzE,MAAM;YACR,KAAK,YAAY;gBACf,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;gBACjD,MAAM;QACV,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,EAAqB;QACpC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO;QAE3C,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAE1B,IAAI,EAAE,CAAC,gBAAgB,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,WAAW;YACX,EAAE,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,iBAAiB;YACjB,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC3B,EAAE,CAAC,mBAAmB,GAAG,KAAK,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,EAAqB;QACvC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,KAAK;YAAE,OAAO;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO;QAExE,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAE1B,IAAI,EAAE,CAAC,mBAAmB,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,WAAW;YACX,EAAE,CAAC,mBAAmB,GAAG,KAAK,CAAC;YAC/B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,oBAAoB;YACpB,EAAE,CAAC,mBAAmB,GAAG,IAAI,CAAC;YAC9B,EAAE,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,EAAqB;QACtC,IAAI,EAAE,CAAC,YAAY;YAAE,OAAO,aAAa,CAAC;QAC1C,IAAI,EAAE,CAAC,eAAe;YAAE,OAAO,gBAAgB,CAAC;QAChD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAqB;QACrC,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;YACpB,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,IAAI,EAAE,CAAC,eAAe,EAAE,CAAC;YACvB,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,KAAK,EAAE,CAAC,oBAAoB,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAqB;QACrC,IAAI,EAAE,CAAC,YAAY;YAAE,OAAO,0BAA0B,CAAC;QACvD,IAAI,EAAE,CAAC,eAAe;YAAE,OAAO,gCAAgC,CAAC;QAChE,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAErD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,YAAY,GAAqB;gBACrC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;gBAC7B,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,SAAS;gBACxD,UAAU,EAAE,IAAI,CAAC,iBAAiB,IAAI,SAAS;gBAC/C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;aAC/B,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAEhE,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAErC,wCAAwC;gBACxC,MAAM,EAAE,GAAsB;oBAC5B,IAAI,EAAE,OAAO;oBACb,SAAS,EAAE,CAAC;oBACZ,eAAe,EAAE,CAAC;oBAClB,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM;oBAClD,YAAY,EAAE,KAAK;oBACnB,eAAe,EAAE,KAAK;oBACtB,WAAW,EAAE,IAAI;oBACjB,WAAW,EAAE,IAAI,IAAI,EAAE;oBACvB,gBAAgB,EAAE,IAAI;oBACtB,mBAAmB,EAAE,KAAK;iBAC3B,CAAC;gBAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAElC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;gBAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;gBAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;gBAE9B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,MAAM,MAAM,GAAyB;YACnC,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,eAAe,EAAE,IAAI,CAAC,iBAAiB;SACxC,CAAC;QAEF,IAAI,CAAC;YACH,oBAAoB;YACpB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,CACxD,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,EACtB,IAAI,CAAC,MAAM,CAAC,SAAS,EACrB,IAAI,CAAC,kBAAkB;iBACxB,CAAC;gBAEF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACvC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;4BAChB,MAAM;4BACN,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI;4BACtB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;yBACjC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,mBAAmB;YACnB,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAChE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CACtB,CAAC;gBAEF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;4BAClB,MAAM;4BACN,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI;4BACtB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;yBACjC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,MAAM,GAAyB;YACnC,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,eAAe,EAAE,EAAE;SACpB,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAU;QACnB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAEpC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,OAAO,CAAC;QAEpC,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,EAAqB;QACjC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACjD,OAAO,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,EAAqB;QACpC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC9E,OAAO,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,eAAe,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACnG,CAAC;uHA1jBU,6BAA6B;6DAA7B,6BAA6B;YC3C1C,iGAAe;;YAAf,sCAsQC;;;iFD3NY,6BAA6B;cANzC,SAAS;6BACI,KAAK,YACP,2BAA2B;;kBAQpC,KAAK;;kBAKL,KAAK;;kBAeL,MAAM;;kBAKN,MAAM;;kFA7BI,6BAA6B","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { Metadata } from '@memberjunction/core';\nimport { MJListEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\nimport { ListManagementService } from '../../services/list-management.service';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport {\n ListManagementDialogConfig,\n ListManagementResult,\n ListItemViewModel,\n ListFilterTab,\n ListSortOption,\n CreateListConfig,\n ListOperationDetail\n} from '../../models/list-management.models';\n\n/**\n * A gorgeous, responsive dialog for managing list membership.\n * Supports adding/removing records from multiple lists with membership indicators.\n *\n * Features:\n * - Search and filter lists\n * - Visual membership indicators (full/partial/none)\n * - Inline list creation\n * - Mobile-responsive bottom sheet on small screens\n * - Batch operations with progress feedback\n */\n@Component({\n standalone: false,\n selector: 'mj-list-management-dialog',\n templateUrl: './list-management-dialog.component.html',\n styleUrls: ['./list-management-dialog.component.css']\n})\nexport class ListManagementDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n /**\n * Configuration for the dialog\n */\n @Input() config!: ListManagementDialogConfig;\n\n /**\n * Controls dialog visibility\n */\n @Input()\n get visible(): boolean {\n return this._visible;\n }\n set visible(value: boolean) {\n if (value && !this._visible) {\n this.initializeDialog();\n }\n this._visible = value;\n }\n private _visible = false;\n\n /**\n * Emitted when dialog is closed with results\n */\n @Output() complete = new EventEmitter<ListManagementResult>();\n\n /**\n * Emitted when dialog is cancelled\n */\n @Output() cancel = new EventEmitter<void>();\n\n // State\n loading = false;\n saving = false;\n searchText = '';\n activeTab: ListFilterTab = 'all';\n sortOption: ListSortOption = 'name';\n showCreateForm = false;\n\n // Data\n allLists: ListItemViewModel[] = [];\n filteredLists: ListItemViewModel[] = [];\n categories: MJListCategoryEntity[] = [];\n\n // Create form state\n newListName = '';\n newListDescription = '';\n newListCategoryId: string | null = null;\n\n // Track changes\n private originalMembership = new Map<string, boolean>();\n public addedToLists: Set<string> = new Set();\n public removedFromLists: Set<string> = new Set();\n public newlyCreatedLists: MJListEntity[] = [];\n\n // Cleanup\n private destroy$ = new Subject<void>();\n private searchSubject = new Subject<string>();\n\n constructor(\n private listService: ListManagementService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Get dialog title based on config\n */\n get dialogTitle(): string {\n if (this.config?.dialogTitle) {\n return this.config.dialogTitle;\n }\n\n const recordCount = this.config?.recordIds?.length || 0;\n const recordText = recordCount === 1 ? '1 record' : `${recordCount} records`;\n\n switch (this.config?.mode) {\n case 'add':\n return `Add ${recordText} to Lists`;\n case 'remove':\n return `Remove ${recordText} from Lists`;\n default:\n return `Manage List Membership`;\n }\n }\n\n /**\n * Get subtitle showing context\n */\n get dialogSubtitle(): string {\n const recordCount = this.config?.recordIds?.length || 0;\n const entityName = this.config?.entityName || 'records';\n\n if (recordCount === 1 && this.config?.recordDisplayNames?.[0]) {\n return `\"${this.config.recordDisplayNames[0]}\" from ${entityName}`;\n }\n\n return `${recordCount} ${entityName} record${recordCount !== 1 ? 's' : ''}`;\n }\n\n /**\n * Check if there are pending changes\n */\n get hasChanges(): boolean {\n return this.addedToLists.size > 0 || this.removedFromLists.size > 0;\n }\n\n /**\n * Get count of lists to add to\n */\n get addCount(): number {\n return this.addedToLists.size;\n }\n\n /**\n * Get count of lists to remove from\n */\n get removeCount(): number {\n return this.removedFromLists.size;\n }\n\n /**\n * Setup search with debounce\n */\n private setupSearchDebounce(): void {\n this.searchSubject.pipe(\n debounceTime(300),\n takeUntil(this.destroy$)\n ).subscribe((searchText: string) => {\n this.searchText = searchText;\n this.applyFilters();\n });\n }\n\n /**\n * Initialize dialog when opened\n */\n private async initializeDialog(): Promise<void> {\n this.resetState();\n await this.loadData();\n }\n\n /**\n * Reset all state\n */\n private resetState(): void {\n this.searchText = '';\n this.activeTab = 'all';\n this.sortOption = 'name';\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n this.addedToLists.clear();\n this.removedFromLists.clear();\n this.newlyCreatedLists = [];\n this.originalMembership.clear();\n }\n\n /**\n * Load lists and membership data\n */\n private async loadData(): Promise<void> {\n if (!this.config) return;\n\n this.loading = true;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n\n // Load lists and membership in parallel\n const [lists, membership, categories] = await Promise.all([\n this.listService.getListsForEntity(\n this.config.entityId,\n md.CurrentUser.ID,\n true // Force refresh\n ),\n this.listService.getRecordMembership(\n this.config.entityId,\n this.config.recordIds\n ),\n this.listService.getListCategories()\n ]);\n\n this.categories = categories;\n\n // Build view models\n this.allLists = await this.listService.buildListViewModels(\n lists,\n this.config.recordIds,\n membership\n );\n\n // Store original membership state\n for (const vm of this.allLists) {\n this.originalMembership.set(vm.list.ID, vm.isFullMember || vm.isPartialMember);\n }\n\n // Pre-select lists if configured\n if (this.config.preSelectedListIds) {\n for (const listId of this.config.preSelectedListIds) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n vm.isSelectedForAdd = true;\n this.addedToLists.add(listId);\n }\n }\n }\n\n this.applyFilters();\n } catch (error) {\n console.error('Error loading list data:', error);\n } finally {\n this.loading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handle search input\n */\n onSearchInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.searchSubject.next(value);\n }\n\n /**\n * Clear search\n */\n clearSearch(): void {\n this.searchText = '';\n this.searchSubject.next('');\n }\n\n /**\n * Change active tab\n */\n setActiveTab(tab: ListFilterTab): void {\n this.activeTab = tab;\n this.applyFilters();\n }\n\n /**\n * Change sort option\n */\n setSortOption(option: ListSortOption): void {\n this.sortOption = option;\n this.applyFilters();\n }\n\n /**\n * Apply all filters and sorting\n */\n private applyFilters(): void {\n let result = [...this.allLists];\n\n // Apply search filter\n if (this.searchText.trim()) {\n const search = this.searchText.toLowerCase();\n result = result.filter(vm =>\n vm.list.Name.toLowerCase().includes(search) ||\n (vm.list.Description?.toLowerCase().includes(search))\n );\n }\n\n // Apply tab filter\n switch (this.activeTab) {\n case 'my-lists':\n // Already filtered by user in loadData\n break;\n case 'recent':\n // Sort by last updated and take top 10\n result = result\n .sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime())\n .slice(0, 10);\n break;\n // 'all' and 'shared' - no additional filtering for now\n }\n\n // Apply sorting\n switch (this.sortOption) {\n case 'name':\n result.sort((a, b) => a.list.Name.localeCompare(b.list.Name));\n break;\n case 'recent':\n result.sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime());\n break;\n case 'item-count':\n result.sort((a, b) => b.itemCount - a.itemCount);\n break;\n }\n\n this.filteredLists = result;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle list selection for adding\n */\n toggleListForAdd(vm: ListItemViewModel): void {\n if (this.config?.mode === 'remove') return;\n\n const listId = vm.list.ID;\n\n if (vm.isSelectedForAdd || this.addedToLists.has(listId)) {\n // Deselect\n vm.isSelectedForAdd = false;\n this.addedToLists.delete(listId);\n } else {\n // Select for add\n vm.isSelectedForAdd = true;\n vm.isSelectedForRemove = false;\n this.addedToLists.add(listId);\n this.removedFromLists.delete(listId);\n }\n\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle list selection for removal\n */\n toggleListForRemove(vm: ListItemViewModel): void {\n if (this.config?.mode === 'add') return;\n if (!this.config?.allowRemove && this.config?.mode !== 'manage') return;\n\n const listId = vm.list.ID;\n\n if (vm.isSelectedForRemove || this.removedFromLists.has(listId)) {\n // Deselect\n vm.isSelectedForRemove = false;\n this.removedFromLists.delete(listId);\n } else {\n // Select for remove\n vm.isSelectedForRemove = true;\n vm.isSelectedForAdd = false;\n this.removedFromLists.add(listId);\n this.addedToLists.delete(listId);\n }\n\n this.cdr.detectChanges();\n }\n\n /**\n * Get membership indicator class\n */\n getMembershipClass(vm: ListItemViewModel): string {\n if (vm.isFullMember) return 'full-member';\n if (vm.isPartialMember) return 'partial-member';\n return 'not-member';\n }\n\n /**\n * Get membership indicator text\n */\n getMembershipText(vm: ListItemViewModel): string {\n if (vm.isFullMember) {\n return `${vm.membershipCount}/${vm.totalSelectedRecords}`;\n }\n if (vm.isPartialMember) {\n return `${vm.membershipCount}/${vm.totalSelectedRecords}`;\n }\n return `0/${vm.totalSelectedRecords}`;\n }\n\n /**\n * Get membership icon\n */\n getMembershipIcon(vm: ListItemViewModel): string {\n if (vm.isFullMember) return 'fa-solid fa-check-circle';\n if (vm.isPartialMember) return 'fa-solid fa-circle-half-stroke';\n return 'fa-regular fa-circle';\n }\n\n /**\n * Show create list form\n */\n showCreateListForm(): void {\n this.showCreateForm = true;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n }\n\n /**\n * Cancel create list form\n */\n cancelCreateList(): void {\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n }\n\n /**\n * Create a new list\n */\n async createList(): Promise<void> {\n if (!this.newListName.trim() || !this.config) return;\n\n this.saving = true;\n\n try {\n const createConfig: CreateListConfig = {\n name: this.newListName.trim(),\n description: this.newListDescription.trim() || undefined,\n categoryId: this.newListCategoryId || undefined,\n entityId: this.config.entityId\n };\n\n const newList = await this.listService.createList(createConfig);\n\n if (newList) {\n this.newlyCreatedLists.push(newList);\n\n // Add to view models and select for add\n const vm: ListItemViewModel = {\n list: newList,\n itemCount: 0,\n membershipCount: 0,\n totalSelectedRecords: this.config.recordIds.length,\n isFullMember: false,\n isPartialMember: false,\n isNotMember: true,\n lastUpdated: new Date(),\n isSelectedForAdd: true,\n isSelectedForRemove: false\n };\n\n this.allLists.unshift(vm);\n this.addedToLists.add(newList.ID);\n\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error creating list:', error);\n } finally {\n this.saving = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Apply changes and close dialog\n */\n async applyChanges(): Promise<void> {\n if (!this.config) return;\n\n this.saving = true;\n\n const result: ListManagementResult = {\n action: 'apply',\n added: [],\n removed: [],\n newListsCreated: this.newlyCreatedLists\n };\n\n try {\n // Process additions\n if (this.addedToLists.size > 0) {\n const addResult = await this.listService.addRecordsToLists(\n [...this.addedToLists],\n this.config.recordIds,\n true // Skip duplicates\n );\n\n for (const listId of this.addedToLists) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n result.added.push({\n listId,\n listName: vm.list.Name,\n recordIds: this.config.recordIds\n });\n }\n }\n }\n\n // Process removals\n if (this.removedFromLists.size > 0) {\n const removeResult = await this.listService.removeRecordsFromLists(\n [...this.removedFromLists],\n this.config.recordIds\n );\n\n for (const listId of this.removedFromLists) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n result.removed.push({\n listId,\n listName: vm.list.Name,\n recordIds: this.config.recordIds\n });\n }\n }\n }\n\n this.complete.emit(result);\n } catch (error) {\n console.error('Error applying changes:', error);\n } finally {\n this.saving = false;\n this._visible = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Cancel and close dialog\n */\n onCancel(): void {\n const result: ListManagementResult = {\n action: 'cancel',\n added: [],\n removed: [],\n newListsCreated: []\n };\n\n this._visible = false;\n this.cancel.emit();\n }\n\n /**\n * Format date for display\n */\n formatDate(date: Date): string {\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n\n return date.toLocaleDateString();\n }\n\n /**\n * Check if we should show the add button for a list\n */\n showAddButton(vm: ListItemViewModel): boolean {\n if (this.config?.mode === 'remove') return false;\n return !vm.isFullMember || !this.originalMembership.get(vm.list.ID);\n }\n\n /**\n * Check if we should show the remove button for a list\n */\n showRemoveButton(vm: ListItemViewModel): boolean {\n if (this.config?.mode === 'add') return false;\n if (!this.config?.allowRemove && this.config?.mode !== 'manage') return false;\n return vm.isFullMember || vm.isPartialMember || this.originalMembership.get(vm.list.ID) === true;\n }\n}\n","@if (visible) {\n <div class=\"dialog-overlay\" (click)=\"onCancel()\">\n <div class=\"dialog-container\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"dialog-header\">\n <div class=\"header-content\">\n <div class=\"header-icon\">\n <span class=\"fa-solid fa-rectangle-list\"></span>\n </div>\n <div class=\"header-text\">\n <h2 class=\"dialog-title\">{{ dialogTitle }}</h2>\n <p class=\"dialog-subtitle\">{{ dialogSubtitle }}</p>\n </div>\n </div>\n <button class=\"close-button\" (click)=\"onCancel()\" title=\"Close\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n\n <!-- Search and Filters -->\n <div class=\"search-section\">\n <div class=\"search-bar\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search lists...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchText) {\n <button class=\"clear-search\" (click)=\"clearSearch()\">\n <span class=\"fa-solid fa-times-circle\"></span>\n </button>\n }\n </div>\n\n @if (config.allowCreate !== false) {\n <button class=\"create-button\" (click)=\"showCreateListForm()\" [disabled]=\"showCreateForm\">\n <span class=\"fa-solid fa-plus\"></span>\n <span class=\"button-text\">New</span>\n </button>\n }\n </div>\n\n <!-- Filter Tabs -->\n <div class=\"filter-tabs\">\n <div class=\"tabs-left\">\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'all'\"\n (click)=\"setActiveTab('all')\">\n All\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'my-lists'\"\n (click)=\"setActiveTab('my-lists')\">\n My Lists\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'recent'\"\n (click)=\"setActiveTab('recent')\">\n Recent\n </button>\n </div>\n <div class=\"tabs-right\">\n <select class=\"sort-select\" [value]=\"sortOption\" (change)=\"setSortOption($any($event.target).value)\">\n <option value=\"name\">Sort: Name</option>\n <option value=\"recent\">Sort: Recent</option>\n <option value=\"item-count\">Sort: Items</option>\n </select>\n </div>\n </div>\n\n <!-- Create List Form -->\n @if (showCreateForm) {\n <div class=\"create-form\">\n <div class=\"create-form-header\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n <span>Create New List</span>\n </div>\n <div class=\"create-form-body\">\n <div class=\"form-group\">\n <input\n type=\"text\"\n class=\"form-input\"\n placeholder=\"List name *\"\n [(ngModel)]=\"newListName\"\n [disabled]=\"saving\"\n (keyup.enter)=\"createList()\"\n />\n </div>\n <div class=\"form-group\">\n <textarea\n class=\"form-input form-textarea\"\n placeholder=\"Description (optional)\"\n [(ngModel)]=\"newListDescription\"\n [disabled]=\"saving\"\n rows=\"2\">\n </textarea>\n </div>\n @if (categories.length > 0) {\n <div class=\"form-group\">\n <select class=\"form-input\" [(ngModel)]=\"newListCategoryId\" [disabled]=\"saving\">\n <option [ngValue]=\"null\">No category</option>\n @for (category of categories; track category.ID) {\n <option [ngValue]=\"category.ID\">{{ category.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"create-form-actions\">\n <button\n class=\"btn btn-primary\"\n (click)=\"createList()\"\n [disabled]=\"!newListName.trim() || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Create List\n </button>\n <button class=\"btn btn-secondary\" (click)=\"cancelCreateList()\" [disabled]=\"saving\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- List Content -->\n <div class=\"list-content\">\n @if (loading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading lists...\" size=\"medium\"></mj-loading>\n </div>\n } @else if (filteredLists.length === 0) {\n @if (searchText) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-magnifying-glass\"\n Title=\"No lists found\"\n Message=\"Try a different search term\" />\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-rectangle-list\"\n Title=\"No lists yet\"\n Message=\"Create your first list to get started\"\n [ActionText]=\"config.allowCreate !== false ? 'Create List' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"showCreateListForm()\" />\n }\n } @else {\n <div class=\"list-items\">\n @for (vm of filteredLists; track vm.list.ID) {\n <div\n class=\"list-item\"\n [class.selected-add]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n [class.selected-remove]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n [class.is-member]=\"vm.isFullMember || vm.isPartialMember\">\n\n <!-- Checkbox / Selection Area -->\n <div class=\"list-item-select\">\n @if (showAddButton(vm)) {\n <button\n class=\"select-btn add-btn\"\n [class.selected]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n (click)=\"toggleListForAdd(vm)\"\n [title]=\"(vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) ? 'Remove from selection' : 'Add to this list'\">\n @if (vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-check\"></span>\n } @else {\n <span class=\"fa-solid fa-plus\"></span>\n }\n </button>\n }\n @if (showRemoveButton(vm) && (vm.isFullMember || vm.isPartialMember)) {\n <button\n class=\"select-btn remove-btn\"\n [class.selected]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n (click)=\"toggleListForRemove(vm)\"\n [title]=\"(vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) ? 'Cancel removal' : 'Remove from this list'\">\n @if (vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-undo\"></span>\n } @else {\n <span class=\"fa-solid fa-minus\"></span>\n }\n </button>\n }\n </div>\n\n <!-- List Info -->\n <div class=\"list-item-content\">\n <div class=\"list-item-header\">\n <span class=\"fa-solid fa-folder list-icon\"></span>\n <span class=\"list-name\">{{ vm.list.Name }}</span>\n @if (newlyCreatedLists.includes(vm.list)) {\n <span class=\"badge badge-new\">New</span>\n }\n </div>\n <div class=\"list-item-meta\">\n @if (vm.list.Description) {\n <span class=\"list-description\">{{ vm.list.Description }}</span>\n <span class=\"meta-separator\">•</span>\n }\n <span class=\"list-count\">{{ vm.itemCount }} item{{ vm.itemCount !== 1 ? 's' : '' }}</span>\n <span class=\"meta-separator\">•</span>\n <span class=\"list-updated\">{{ formatDate(vm.lastUpdated) }}</span>\n </div>\n </div>\n\n <!-- Membership Indicator -->\n @if (config.showMembership !== false) {\n <div class=\"membership-indicator\" [class]=\"getMembershipClass(vm)\">\n <span [class]=\"getMembershipIcon(vm)\"></span>\n <span class=\"membership-text\">{{ getMembershipText(vm) }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"dialog-footer\">\n <div class=\"footer-summary\">\n @if (hasChanges) {\n @if (addCount > 0) {\n <span class=\"summary-item add\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n {{ addCount }} list{{ addCount !== 1 ? 's' : '' }}\n </span>\n }\n @if (removeCount > 0) {\n <span class=\"summary-item remove\">\n <span class=\"fa-solid fa-minus-circle\"></span>\n {{ removeCount }} list{{ removeCount !== 1 ? 's' : '' }}\n </span>\n }\n } @else {\n <span class=\"summary-empty\">No changes</span>\n }\n </div>\n <div class=\"footer-actions\">\n <button class=\"btn btn-secondary\" (click)=\"onCancel()\" [disabled]=\"saving\">\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"applyChanges()\"\n [disabled]=\"!hasChanges || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Apply Changes\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"list-management-dialog.component.js","sourceRoot":"","sources":["../../../../src/lib/components/list-management-dialog/list-management-dialog.component.ts","../../../../src/lib/components/list-management-dialog/list-management-dialog.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EAIb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIzD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;;;;;;;;;;ICgBxC,kCAAqD;IAAxB,iNAAS,oBAAa,KAAC;IAClD,2BAA8C;IAChD,iBAAS;;;;IAKX,kCAAyF;IAA3D,iNAAS,2BAAoB,KAAC;IAC1D,2BAAsC;IACtC,gCAA0B;IAAA,mBAAG;IAC/B,AAD+B,iBAAO,EAC7B;;;IAHoD,gDAA2B;;;IAsE9E,kCAAgC;IAAA,YAAmB;IAAA,iBAAS;;;IAApD,wCAAuB;IAAC,cAAmB;IAAnB,sCAAmB;;;;IAHvD,AADF,+BAAwB,iBACyD;IAApD,uWAA+B;IACxD,kCAAyB;IAAA,2BAAW;IAAA,iBAAS;IAC7C,gJAEC;IAEL,AADE,iBAAS,EACL;;;IANuB,cAA+B;IAA/B,wDAA+B;IAAC,wCAAmB;IACpE,cAAgB;IAAhB,8BAAgB;IACxB,eAEC;IAFD,gCAEC;;;IAUD,2BAAiD;;;;IAxCzD,AADF,+BAAyB,cACS;IAC9B,2BAA6C;IAC7C,4BAAM;IAAA,+BAAe;IACvB,AADuB,iBAAO,EACxB;IAGF,AADF,AADF,+BAA8B,cACJ,gBAQpB;IAHA,2UAAyB;IAEzB,4NAAe,mBAAY,KAAC;IAEhC,AARE,iBAOE,EACE;IAEJ,AADF,+BAAwB,mBAMX;IAFT,4VAAgC;IAGlC,+BAAA;IACF,AADE,iBAAW,EACP;IACN,+HAA6B;IAW3B,AADF,gCAAiC,kBAIc;IAD3C,kNAAS,mBAAY,KAAC;IAEtB,gIAAc;IAGd,8BACF;IAAA,iBAAS;IACT,mCAAmF;IAAjD,kNAAS,yBAAkB,KAAC;IAC5D,yBACF;IAGN,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF;;;IAvCE,eAAyB;IAAzB,kDAAyB;IACzB,wCAAmB;IAQnB,eAAgC;IAAhC,yDAAgC;IAChC,wCAAmB;IAIvB,eASC;IATD,wDASC;IAKG,eAA0C;IAA1C,sEAA0C;IAC1C,cAEC;IAFD,yCAEC;IAG4D,eAAmB;IAAnB,wCAAmB;;;IAWtF,+BAA2B;IACzB,iCAA+D;IACjE,iBAAM;;;IAGJ,qCAI0C;;;;IAE1C,0CAMoC;IAAlC,yOAAU,2BAAoB,KAAC;IANjC,iBAMoC;;;IAFlC,qFAAgE;;;IALlE,AANF,wIAAkB,kHAMT;;;IANT,2CAcC;;;IAmBa,2BAAuC;;;IAEvC,2BAAsC;;;;IAR1C,kCAIiH;IAD/G,kRAAS,+BAAoB,KAAC;IAI5B,AAFF,kJAA2D,4HAElD;IAGX,iBAAS;;;;IARP,8FAAsE;IAEtE,yIAA8G;IAC9G,cAIC;IAJD,4FAIC;;;IAUC,2BAAsC;;;IAEtC,2BAAuC;;;;IAR3C,kCAIsH;IADpH,mRAAS,kCAAuB,KAAC;IAI/B,AAFF,kJAAkE,4HAEzD;IAGX,iBAAS;;;;IARP,qGAA6E;IAE7E,8IAAmH;IACnH,cAIC;IAJD,mGAIC;;;IAWD,gCAA8B;IAAA,mBAAG;IAAA,iBAAO;;;IAKxC,gCAA+B;IAAA,YAAyB;IAAA,iBAAO;IAC/D,gCAA6B;IAAA,sBAAC;IAAA,iBAAO;;;IADN,cAAyB;IAAzB,6CAAyB;;;IAW5D,+BAAmE;IACjE,uBAA6C;IAC7C,gCAA8B;IAAA,YAA2B;IAC3D,AAD2D,iBAAO,EAC5D;;;;IAH4B,gDAAgC;IAC1D,cAA+B;IAA/B,+CAA+B;IACP,eAA2B;IAA3B,sDAA2B;;;IArD7D,AAPF,+BAI4D,cAG5B;IAC5B,sIAAyB;IAazB,sIAAuE;IAazE,iBAAM;IAIJ,AADF,+BAA+B,cACC;IAC5B,2BAAkD;IAClD,gCAAwB;IAAA,YAAkB;IAAA,iBAAO;IACjD,oIAA2C;IAG7C,iBAAM;IACN,gCAA4B;IAC1B,0HAA2B;IAI3B,iCAAyB;IAAA,aAA0D;IAAA,iBAAO;IAC1F,iCAA6B;IAAA,uBAAC;IAAA,iBAAO;IACrC,iCAA2B;IAAA,aAAgC;IAE/D,AADE,AAD6D,iBAAO,EAC9D,EACF;IAGN,qIAAuC;IAMzC,iBAAM;;;;IA3DJ,AADA,AADA,kGAA0E,8FACU,4DAC3B;IAIvD,eAYC;IAZD,uDAYC;IACD,cAYC;IAZD,6GAYC;IAOyB,eAAkB;IAAlB,sCAAkB;IAC1C,cAEC;IAFD,yEAEC;IAGD,eAGC;IAHD,mDAGC;IACwB,eAA0D;IAA1D,uFAA0D;IAExD,eAAgC;IAAhC,2DAAgC;IAK/D,cAKC;IALD,kEAKC;;;IAhEP,+BAAwB;IACtB,gIAiEC;IACH,iBAAM;;;IAlEJ,cAiEC;IAjED,mCAiEC;;;IAUC,gCAA+B;IAC7B,2BAA6C;IAC7C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,2FACF;;;IAGA,gCAAkC;IAChC,2BAA8C;IAC9C,YACF;IAAA,iBAAO;;;IADL,eACF;IADE,iGACF;;;IAVF,8HAAoB;IAMpB,8HAAuB;;;IANvB,8CAKC;IACD,cAKC;IALD,iDAKC;;;IAED,gCAA4B;IAAA,0BAAU;IAAA,iBAAO;;;IAY3C,2BAAiD;;;;IA7P7D,8BAAiD;IAArB,8LAAS,iBAAU,KAAC;IAC9C,8BAAiE;IAAnC,iKAAS,wBAAwB,KAAC;IAI1D,AADF,AADF,8BAA2B,aACG,aACD;IACvB,0BAAgD;IAClD,iBAAM;IAEJ,AADF,8BAAyB,YACE;IAAA,YAAiB;IAAA,iBAAK;IAC/C,4BAA2B;IAAA,aAAoB;IAEnD,AADE,AADiD,iBAAI,EAC/C,EACF;IACN,mCAAgE;IAAnC,kMAAS,iBAAU,KAAC;IAC/C,4BAAuC;IAE3C,AADE,iBAAS,EACL;IAIJ,AADF,gCAA4B,eACF;IACtB,4BAAoD;IACpD,kCAME;IADA,uMAAS,4BAAqB,KAAC;IALjC,iBAME;IACF,mHAAkB;IAKpB,iBAAM;IAEN,mHAAoC;IAMtC,iBAAM;IAKF,AADF,AADF,gCAAyB,eACA,kBAIW;IAA9B,kMAAS,oBAAa,KAAK,CAAC,KAAC;IAC7B,sBACF;IAAA,iBAAS;IACT,mCAGqC;IAAnC,kMAAS,oBAAa,UAAU,CAAC,KAAC;IAClC,2BACF;IAAA,iBAAS;IACT,mCAGmC;IAAjC,kMAAS,oBAAa,QAAQ,CAAC,KAAC;IAChC,yBACF;IACF,AADE,iBAAS,EACL;IAEJ,AADF,gCAAwB,kBAC+E;IAApD,0MAAU,yCAAwC,KAAC;IAClG,mCAAqB;IAAA,2BAAU;IAAA,iBAAS;IACxC,mCAAuB;IAAA,6BAAY;IAAA,iBAAS;IAC5C,mCAA2B;IAAA,4BAAW;IAG5C,AADE,AADE,AADwC,iBAAS,EACxC,EACL,EACF;IAGN,iHAAsB;IAuDtB,gCAA0B;IAqBtB,AAhBA,AAJF,gHAAe,+EAI0B,0FAgBhC;IAsEX,iBAAM;IAIJ,AADF,gCAA2B,eACG;IAcxB,AAbF,qGAAkB,2FAaT;IAGX,iBAAM;IAEJ,AADF,gCAA4B,kBACiD;IAAzC,kMAAS,iBAAU,KAAC;IACpD,yBACF;IAAA,iBAAS;IACT,mCAGqC;IADnC,kMAAS,qBAAc,KAAC;IAExB,iHAAc;IAGd,gCACF;IAIR,AADE,AADE,AADE,AADE,iBAAS,EACL,EACF,EACF,EACF;;;IA3P6B,eAAiB;IAAjB,wCAAiB;IACf,eAAoB;IAApB,2CAAoB;IAgB/C,eAAoB;IAApB,yCAAoB;IAGtB,cAIC;IAJD,6CAIC;IAGH,cAKC;IALD,+DAKC;IAQG,eAAoC;IAApC,oDAAoC;IAMpC,eAAyC;IAAzC,yDAAyC;IAMzC,eAAuC;IAAvC,uDAAuC;IAMb,eAAoB;IAApB,yCAAoB;IASpD,eAoDC;IApDD,iDAoDC;IAIC,eAyFC;IAzFD,mFAyFC;IAMC,eAeC;IAfD,6CAeC;IAGsD,eAAmB;IAAnB,wCAAmB;IAMxE,eAAkC;IAAlC,8DAAkC;IAClC,cAEC;IAFD,yCAEC;;ADrOb;;;;;;;;;;GAUG;AAOH,MAAM,OAAO,6BAA8B,SAAQ,oBAAoB;IAsF3D;IACA;IAtFV;;;;;;;;OAQG;IACH,IACI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,IAAI,MAAM,CAAC,KAAiC;QAC1C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IACO,OAAO,CAA8B;IAE7C;;OAEG;IACH,IACI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,CAAC,KAAc;QACxB,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IACO,QAAQ,GAAG,KAAK,CAAC;IAEzB,6FAA6F;IACrF,YAAY,GAAG,KAAK,CAAC;IAE7B,2FAA2F;IACnF,aAAa;QACnB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACO,QAAQ,GAAG,IAAI,YAAY,EAAwB,CAAC;IAE9D;;OAEG;IACO,MAAM,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE5C,QAAQ;IACR,OAAO,GAAG,KAAK,CAAC;IAChB,MAAM,GAAG,KAAK,CAAC;IACf,UAAU,GAAG,EAAE,CAAC;IAChB,SAAS,GAAkB,KAAK,CAAC;IACjC,UAAU,GAAmB,MAAM,CAAC;IACpC,cAAc,GAAG,KAAK,CAAC;IAEvB,OAAO;IACP,QAAQ,GAAwB,EAAE,CAAC;IACnC,aAAa,GAAwB,EAAE,CAAC;IACxC,UAAU,GAA2B,EAAE,CAAC;IAExC,oBAAoB;IACpB,WAAW,GAAG,EAAE,CAAC;IACjB,kBAAkB,GAAG,EAAE,CAAC;IACxB,iBAAiB,GAAkB,IAAI,CAAC;IAExC,gBAAgB;IACR,kBAAkB,GAAG,IAAI,GAAG,EAAmB,CAAC;IACjD,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC;IACtC,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC1C,iBAAiB,GAAmB,EAAE,CAAC;IAE9C,UAAU;IACF,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;IAC/B,aAAa,GAAG,IAAI,OAAO,EAAU,CAAC;IAE9C,YACU,WAAkC,EAClC,GAAsB;QAEhC,KAAK,EAAE,CAAC;QAHE,gBAAW,GAAX,WAAW,CAAuB;QAClC,QAAG,GAAH,GAAG,CAAmB;IAExB,CAAC;IAET,QAAQ;QACN,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,WAAW,UAAU,CAAC;QAE7E,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YAC1B,KAAK,KAAK;gBACR,OAAO,OAAO,UAAU,WAAW,CAAC;YACtC,KAAK,QAAQ;gBACX,OAAO,UAAU,UAAU,aAAa,CAAC;YAC3C;gBACE,OAAO,wBAAwB,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,SAAS,CAAC;QAExD,IAAI,WAAW,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,UAAU,EAAE,CAAC;QACrE,CAAC;QAED,OAAO,GAAG,WAAW,IAAI,UAAU,UAAU,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC9E,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;IACpC,CAAC;IAED;;OAEG;IACK,mBAAmB;QACzB,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,YAAY,CAAC,GAAG,CAAC,EACjB,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CACzB,CAAC,SAAS,CAAC,CAAC,UAAkB,EAAE,EAAE;YACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,gBAAgB;QAC5B,mEAAmE;QACnE,uEAAuE;QACvE,wDAAwD;QACxD,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;YAE9B,wCAAwC;YACxC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACxD,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,EAAE,CAAC,WAAW,CAAC,EAAE,EACjB,IAAI,CAAC,gBAAgB;iBACtB;gBACD,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,EACpB,IAAI,CAAC,MAAM,CAAC,SAAS,CACtB;gBACD,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE;aACrC,CAAC,CAAC;YAEH,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAE7B,oBAAoB;YACpB,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,mBAAmB,CACxD,KAAK,EACL,IAAI,CAAC,MAAM,CAAC,SAAS,EACrB,UAAU,CACX,CAAC;YAEF,kCAAkC;YAClC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC/B,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,eAAe,CAAC,CAAC;YACjF,CAAC;YAED,iCAAiC;YACjC,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBACnC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;oBACpD,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC;wBAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAChC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,KAAY;QACxB,MAAM,KAAK,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,GAAkB;QAC7B,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;QACrB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,MAAsB;QAClC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEhC,sBAAsB;QACtB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAC1B,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC3C,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CACtD,CAAC;QACJ,CAAC;QAED,mBAAmB;QACnB,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,KAAK,UAAU;gBACb,uCAAuC;gBACvC,MAAM;YACR,KAAK,QAAQ;gBACX,uCAAuC;gBACvC,MAAM,GAAG,MAAM;qBACZ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;qBACjE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChB,MAAM;YACR,uDAAuD;QACzD,CAAC;QAED,gBAAgB;QAChB,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9D,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;gBACzE,MAAM;YACR,KAAK,YAAY;gBACf,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;gBACjD,MAAM;QACV,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,EAAqB;QACpC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO;QAE3C,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAE1B,IAAI,EAAE,CAAC,gBAAgB,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,WAAW;YACX,EAAE,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,iBAAiB;YACjB,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC3B,EAAE,CAAC,mBAAmB,GAAG,KAAK,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,EAAqB;QACvC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,KAAK;YAAE,OAAO;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO;QAExE,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAE1B,IAAI,EAAE,CAAC,mBAAmB,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,WAAW;YACX,EAAE,CAAC,mBAAmB,GAAG,KAAK,CAAC;YAC/B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,oBAAoB;YACpB,EAAE,CAAC,mBAAmB,GAAG,IAAI,CAAC;YAC9B,EAAE,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,EAAqB;QACtC,IAAI,EAAE,CAAC,YAAY;YAAE,OAAO,aAAa,CAAC;QAC1C,IAAI,EAAE,CAAC,eAAe;YAAE,OAAO,gBAAgB,CAAC;QAChD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAqB;QACrC,IAAI,EAAE,CAAC,YAAY,EAAE,CAAC;YACpB,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,IAAI,EAAE,CAAC,eAAe,EAAE,CAAC;YACvB,OAAO,GAAG,EAAE,CAAC,eAAe,IAAI,EAAE,CAAC,oBAAoB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,KAAK,EAAE,CAAC,oBAAoB,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAqB;QACrC,IAAI,EAAE,CAAC,YAAY;YAAE,OAAO,0BAA0B,CAAC;QACvD,IAAI,EAAE,CAAC,eAAe;YAAE,OAAO,gCAAgC,CAAC;QAChE,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAErD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,YAAY,GAAqB;gBACrC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;gBAC7B,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,SAAS;gBACxD,UAAU,EAAE,IAAI,CAAC,iBAAiB,IAAI,SAAS;gBAC/C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;aAC/B,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAEhE,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAErC,wCAAwC;gBACxC,MAAM,EAAE,GAAsB;oBAC5B,IAAI,EAAE,OAAO;oBACb,SAAS,EAAE,CAAC;oBACZ,eAAe,EAAE,CAAC;oBAClB,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM;oBAClD,YAAY,EAAE,KAAK;oBACnB,eAAe,EAAE,KAAK;oBACtB,WAAW,EAAE,IAAI;oBACjB,WAAW,EAAE,IAAI,IAAI,EAAE;oBACvB,gBAAgB,EAAE,IAAI;oBACtB,mBAAmB,EAAE,KAAK;iBAC3B,CAAC;gBAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAElC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;gBAC5B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBACtB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;gBAC7B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;gBAE9B,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,MAAM,MAAM,GAAyB;YACnC,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,eAAe,EAAE,IAAI,CAAC,iBAAiB;YACvC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;SACzD,CAAC;QAEF,IAAI,CAAC;YACH,oBAAoB;YACpB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,CACxD,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,EACtB,IAAI,CAAC,MAAM,CAAC,SAAS,EACrB,IAAI,CAAC,kBAAkB;iBACxB,CAAC;gBACF,MAAM,CAAC,OAAQ,CAAC,KAAK,IAAI,SAAS,CAAC,OAAO,CAAC;gBAC3C,MAAM,CAAC,OAAQ,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC;gBAC7C,MAAM,CAAC,OAAQ,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC;gBAE3C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACvC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;4BAChB,MAAM;4BACN,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI;4BACtB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;yBACjC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,mBAAmB;YACnB,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAChE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CACtB,CAAC;gBACF,MAAM,CAAC,OAAQ,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC;gBAChD,MAAM,CAAC,OAAQ,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC;gBAE9C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;oBAClE,IAAI,EAAE,EAAE,CAAC;wBACP,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;4BAClB,MAAM;4BACN,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI;4BACtB,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;yBACjC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,MAAM,GAAyB;YACnC,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,eAAe,EAAE,EAAE;SACpB,CAAC;QAEF,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAU;QACnB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAEpC,IAAI,OAAO,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,OAAO,CAAC;QAC3C,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,GAAG,KAAK,OAAO,CAAC;QACvC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,OAAO,CAAC;QAEpC,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,EAAqB;QACjC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACjD,OAAO,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,EAAqB;QACpC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC9E,OAAO,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,eAAe,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACnG,CAAC;uHA9lBU,6BAA6B;6DAA7B,6BAA6B;YC3C1C,iGAAe;;YAAf,sCAsQC;;;iFD3NY,6BAA6B;cANzC,SAAS;6BACI,KAAK,YACP,2BAA2B;;kBAcpC,KAAK;;kBAaL,KAAK;;kBA2BL,MAAM;;kBAKN,MAAM;;kFAvDI,6BAA6B","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectorRef\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { Metadata } from '@memberjunction/core';\nimport { MJListEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\nimport { ListManagementService } from '../../services/list-management.service';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport {\n ListManagementDialogConfig,\n ListManagementResult,\n ListItemViewModel,\n ListFilterTab,\n ListSortOption,\n CreateListConfig,\n ListOperationDetail\n} from '../../models/list-management.models';\n\n/**\n * A gorgeous, responsive dialog for managing list membership.\n * Supports adding/removing records from multiple lists with membership indicators.\n *\n * Features:\n * - Search and filter lists\n * - Visual membership indicators (full/partial/none)\n * - Inline list creation\n * - Mobile-responsive bottom sheet on small screens\n * - Batch operations with progress feedback\n */\n@Component({\n standalone: false,\n selector: 'mj-list-management-dialog',\n templateUrl: './list-management-dialog.component.html',\n styleUrls: ['./list-management-dialog.component.css']\n})\nexport class ListManagementDialogComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n /**\n * Configuration for the dialog.\n *\n * Initialization is deliberately order-independent with {@link visible}:\n * Angular assigns inputs in template attribute order, so a host binding\n * `[visible]` before `[config]` would otherwise open the dialog while\n * `config` is still undefined — `loadData()` would bail silently and the\n * dialog would render permanently empty.\n */\n @Input()\n get config(): ListManagementDialogConfig {\n return this._config;\n }\n set config(value: ListManagementDialogConfig) {\n this._config = value;\n this.tryInitialize();\n }\n private _config!: ListManagementDialogConfig;\n\n /**\n * Controls dialog visibility\n */\n @Input()\n get visible(): boolean {\n return this._visible;\n }\n set visible(value: boolean) {\n if (value && !this._visible) {\n this._pendingInit = true;\n }\n this._visible = value;\n this.tryInitialize();\n }\n private _visible = false;\n\n /** Set on each closed→open transition; cleared once init actually runs (requires config). */\n private _pendingInit = false;\n\n /** Runs initialization once per open, as soon as BOTH visible and config are available. */\n private tryInitialize(): void {\n if (this._pendingInit && this._visible && this._config) {\n this._pendingInit = false;\n void this.initializeDialog();\n }\n }\n\n /**\n * Emitted when dialog is closed with results\n */\n @Output() complete = new EventEmitter<ListManagementResult>();\n\n /**\n * Emitted when dialog is cancelled\n */\n @Output() cancel = new EventEmitter<void>();\n\n // State\n loading = false;\n saving = false;\n searchText = '';\n activeTab: ListFilterTab = 'all';\n sortOption: ListSortOption = 'name';\n showCreateForm = false;\n\n // Data\n allLists: ListItemViewModel[] = [];\n filteredLists: ListItemViewModel[] = [];\n categories: MJListCategoryEntity[] = [];\n\n // Create form state\n newListName = '';\n newListDescription = '';\n newListCategoryId: string | null = null;\n\n // Track changes\n private originalMembership = new Map<string, boolean>();\n public addedToLists: Set<string> = new Set();\n public removedFromLists: Set<string> = new Set();\n public newlyCreatedLists: MJListEntity[] = [];\n\n // Cleanup\n private destroy$ = new Subject<void>();\n private searchSubject = new Subject<string>();\n\n constructor(\n private listService: ListManagementService,\n private cdr: ChangeDetectorRef\n ) {\n super();}\n\n ngOnInit(): void {\n this.setupSearchDebounce();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Get dialog title based on config\n */\n get dialogTitle(): string {\n if (this.config?.dialogTitle) {\n return this.config.dialogTitle;\n }\n\n const recordCount = this.config?.recordIds?.length || 0;\n const recordText = recordCount === 1 ? '1 record' : `${recordCount} records`;\n\n switch (this.config?.mode) {\n case 'add':\n return `Add ${recordText} to Lists`;\n case 'remove':\n return `Remove ${recordText} from Lists`;\n default:\n return `Manage List Membership`;\n }\n }\n\n /**\n * Get subtitle showing context\n */\n get dialogSubtitle(): string {\n const recordCount = this.config?.recordIds?.length || 0;\n const entityName = this.config?.entityName || 'records';\n\n if (recordCount === 1 && this.config?.recordDisplayNames?.[0]) {\n return `\"${this.config.recordDisplayNames[0]}\" from ${entityName}`;\n }\n\n return `${recordCount} ${entityName} record${recordCount !== 1 ? 's' : ''}`;\n }\n\n /**\n * Check if there are pending changes\n */\n get hasChanges(): boolean {\n return this.addedToLists.size > 0 || this.removedFromLists.size > 0;\n }\n\n /**\n * Get count of lists to add to\n */\n get addCount(): number {\n return this.addedToLists.size;\n }\n\n /**\n * Get count of lists to remove from\n */\n get removeCount(): number {\n return this.removedFromLists.size;\n }\n\n /**\n * Setup search with debounce\n */\n private setupSearchDebounce(): void {\n this.searchSubject.pipe(\n debounceTime(300),\n takeUntil(this.destroy$)\n ).subscribe((searchText: string) => {\n this.searchText = searchText;\n this.applyFilters();\n });\n }\n\n /**\n * Initialize dialog when opened\n */\n private async initializeDialog(): Promise<void> {\n // Per ListManagementService's multi-provider contract: thread this\n // component's Provider input into the (root-injected) service. Null is\n // fine — the service falls back to the global provider.\n this.listService.Provider = this.Provider;\n this.resetState();\n await this.loadData();\n }\n\n /**\n * Reset all state\n */\n private resetState(): void {\n this.searchText = '';\n this.activeTab = 'all';\n this.sortOption = 'name';\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n this.addedToLists.clear();\n this.removedFromLists.clear();\n this.newlyCreatedLists = [];\n this.originalMembership.clear();\n }\n\n /**\n * Load lists and membership data\n */\n private async loadData(): Promise<void> {\n if (!this.config) return;\n\n this.loading = true;\n this.cdr.detectChanges();\n\n try {\n const md = this.ProviderToUse;\n\n // Load lists and membership in parallel\n const [lists, membership, categories] = await Promise.all([\n this.listService.getListsForEntity(\n this.config.entityId,\n md.CurrentUser.ID,\n true // Force refresh\n ),\n this.listService.getRecordMembership(\n this.config.entityId,\n this.config.recordIds\n ),\n this.listService.getListCategories()\n ]);\n\n this.categories = categories;\n\n // Build view models\n this.allLists = await this.listService.buildListViewModels(\n lists,\n this.config.recordIds,\n membership\n );\n\n // Store original membership state\n for (const vm of this.allLists) {\n this.originalMembership.set(vm.list.ID, vm.isFullMember || vm.isPartialMember);\n }\n\n // Pre-select lists if configured\n if (this.config.preSelectedListIds) {\n for (const listId of this.config.preSelectedListIds) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n vm.isSelectedForAdd = true;\n this.addedToLists.add(listId);\n }\n }\n }\n\n this.applyFilters();\n } catch (error) {\n console.error('Error loading list data:', error);\n } finally {\n this.loading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Handle search input\n */\n onSearchInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.searchSubject.next(value);\n }\n\n /**\n * Clear search\n */\n clearSearch(): void {\n this.searchText = '';\n this.searchSubject.next('');\n }\n\n /**\n * Change active tab\n */\n setActiveTab(tab: ListFilterTab): void {\n this.activeTab = tab;\n this.applyFilters();\n }\n\n /**\n * Change sort option\n */\n setSortOption(option: ListSortOption): void {\n this.sortOption = option;\n this.applyFilters();\n }\n\n /**\n * Apply all filters and sorting\n */\n private applyFilters(): void {\n let result = [...this.allLists];\n\n // Apply search filter\n if (this.searchText.trim()) {\n const search = this.searchText.toLowerCase();\n result = result.filter(vm =>\n vm.list.Name.toLowerCase().includes(search) ||\n (vm.list.Description?.toLowerCase().includes(search))\n );\n }\n\n // Apply tab filter\n switch (this.activeTab) {\n case 'my-lists':\n // Already filtered by user in loadData\n break;\n case 'recent':\n // Sort by last updated and take top 10\n result = result\n .sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime())\n .slice(0, 10);\n break;\n // 'all' and 'shared' - no additional filtering for now\n }\n\n // Apply sorting\n switch (this.sortOption) {\n case 'name':\n result.sort((a, b) => a.list.Name.localeCompare(b.list.Name));\n break;\n case 'recent':\n result.sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime());\n break;\n case 'item-count':\n result.sort((a, b) => b.itemCount - a.itemCount);\n break;\n }\n\n this.filteredLists = result;\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle list selection for adding\n */\n toggleListForAdd(vm: ListItemViewModel): void {\n if (this.config?.mode === 'remove') return;\n\n const listId = vm.list.ID;\n\n if (vm.isSelectedForAdd || this.addedToLists.has(listId)) {\n // Deselect\n vm.isSelectedForAdd = false;\n this.addedToLists.delete(listId);\n } else {\n // Select for add\n vm.isSelectedForAdd = true;\n vm.isSelectedForRemove = false;\n this.addedToLists.add(listId);\n this.removedFromLists.delete(listId);\n }\n\n this.cdr.detectChanges();\n }\n\n /**\n * Toggle list selection for removal\n */\n toggleListForRemove(vm: ListItemViewModel): void {\n if (this.config?.mode === 'add') return;\n if (!this.config?.allowRemove && this.config?.mode !== 'manage') return;\n\n const listId = vm.list.ID;\n\n if (vm.isSelectedForRemove || this.removedFromLists.has(listId)) {\n // Deselect\n vm.isSelectedForRemove = false;\n this.removedFromLists.delete(listId);\n } else {\n // Select for remove\n vm.isSelectedForRemove = true;\n vm.isSelectedForAdd = false;\n this.removedFromLists.add(listId);\n this.addedToLists.delete(listId);\n }\n\n this.cdr.detectChanges();\n }\n\n /**\n * Get membership indicator class\n */\n getMembershipClass(vm: ListItemViewModel): string {\n if (vm.isFullMember) return 'full-member';\n if (vm.isPartialMember) return 'partial-member';\n return 'not-member';\n }\n\n /**\n * Get membership indicator text\n */\n getMembershipText(vm: ListItemViewModel): string {\n if (vm.isFullMember) {\n return `${vm.membershipCount}/${vm.totalSelectedRecords}`;\n }\n if (vm.isPartialMember) {\n return `${vm.membershipCount}/${vm.totalSelectedRecords}`;\n }\n return `0/${vm.totalSelectedRecords}`;\n }\n\n /**\n * Get membership icon\n */\n getMembershipIcon(vm: ListItemViewModel): string {\n if (vm.isFullMember) return 'fa-solid fa-check-circle';\n if (vm.isPartialMember) return 'fa-solid fa-circle-half-stroke';\n return 'fa-regular fa-circle';\n }\n\n /**\n * Show create list form\n */\n showCreateListForm(): void {\n this.showCreateForm = true;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n }\n\n /**\n * Cancel create list form\n */\n cancelCreateList(): void {\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n }\n\n /**\n * Create a new list\n */\n async createList(): Promise<void> {\n if (!this.newListName.trim() || !this.config) return;\n\n this.saving = true;\n\n try {\n const createConfig: CreateListConfig = {\n name: this.newListName.trim(),\n description: this.newListDescription.trim() || undefined,\n categoryId: this.newListCategoryId || undefined,\n entityId: this.config.entityId\n };\n\n const newList = await this.listService.createList(createConfig);\n\n if (newList) {\n this.newlyCreatedLists.push(newList);\n\n // Add to view models and select for add\n const vm: ListItemViewModel = {\n list: newList,\n itemCount: 0,\n membershipCount: 0,\n totalSelectedRecords: this.config.recordIds.length,\n isFullMember: false,\n isPartialMember: false,\n isNotMember: true,\n lastUpdated: new Date(),\n isSelectedForAdd: true,\n isSelectedForRemove: false\n };\n\n this.allLists.unshift(vm);\n this.addedToLists.add(newList.ID);\n\n this.showCreateForm = false;\n this.newListName = '';\n this.newListDescription = '';\n this.newListCategoryId = null;\n\n this.applyFilters();\n }\n } catch (error) {\n console.error('Error creating list:', error);\n } finally {\n this.saving = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Apply changes and close dialog\n */\n async applyChanges(): Promise<void> {\n if (!this.config) return;\n\n this.saving = true;\n\n const result: ListManagementResult = {\n action: 'apply',\n added: [],\n removed: [],\n newListsCreated: this.newlyCreatedLists,\n summary: { added: 0, removed: 0, skipped: 0, failed: 0 }\n };\n\n try {\n // Process additions\n if (this.addedToLists.size > 0) {\n const addResult = await this.listService.addRecordsToLists(\n [...this.addedToLists],\n this.config.recordIds,\n true // Skip duplicates\n );\n result.summary!.added += addResult.success;\n result.summary!.skipped += addResult.skipped;\n result.summary!.failed += addResult.failed;\n\n for (const listId of this.addedToLists) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n result.added.push({\n listId,\n listName: vm.list.Name,\n recordIds: this.config.recordIds\n });\n }\n }\n }\n\n // Process removals\n if (this.removedFromLists.size > 0) {\n const removeResult = await this.listService.removeRecordsFromLists(\n [...this.removedFromLists],\n this.config.recordIds\n );\n result.summary!.removed += removeResult.success;\n result.summary!.failed += removeResult.failed;\n\n for (const listId of this.removedFromLists) {\n const vm = this.allLists.find(l => UUIDsEqual(l.list.ID, listId));\n if (vm) {\n result.removed.push({\n listId,\n listName: vm.list.Name,\n recordIds: this.config.recordIds\n });\n }\n }\n }\n\n this.complete.emit(result);\n } catch (error) {\n console.error('Error applying changes:', error);\n } finally {\n this.saving = false;\n this._visible = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Cancel and close dialog\n */\n onCancel(): void {\n const result: ListManagementResult = {\n action: 'cancel',\n added: [],\n removed: [],\n newListsCreated: []\n };\n\n this._visible = false;\n this.cancel.emit();\n }\n\n /**\n * Format date for display\n */\n formatDate(date: Date): string {\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (hours < 24) return `${hours}h ago`;\n if (days < 7) return `${days}d ago`;\n\n return date.toLocaleDateString();\n }\n\n /**\n * Check if we should show the add button for a list\n */\n showAddButton(vm: ListItemViewModel): boolean {\n if (this.config?.mode === 'remove') return false;\n return !vm.isFullMember || !this.originalMembership.get(vm.list.ID);\n }\n\n /**\n * Check if we should show the remove button for a list\n */\n showRemoveButton(vm: ListItemViewModel): boolean {\n if (this.config?.mode === 'add') return false;\n if (!this.config?.allowRemove && this.config?.mode !== 'manage') return false;\n return vm.isFullMember || vm.isPartialMember || this.originalMembership.get(vm.list.ID) === true;\n }\n}\n","@if (visible) {\n <div class=\"dialog-overlay\" (click)=\"onCancel()\">\n <div class=\"dialog-container\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"dialog-header\">\n <div class=\"header-content\">\n <div class=\"header-icon\">\n <span class=\"fa-solid fa-rectangle-list\"></span>\n </div>\n <div class=\"header-text\">\n <h2 class=\"dialog-title\">{{ dialogTitle }}</h2>\n <p class=\"dialog-subtitle\">{{ dialogSubtitle }}</p>\n </div>\n </div>\n <button class=\"close-button\" (click)=\"onCancel()\" title=\"Close\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n\n <!-- Search and Filters -->\n <div class=\"search-section\">\n <div class=\"search-bar\">\n <span class=\"fa-solid fa-search search-icon\"></span>\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search lists...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($event)\"\n />\n @if (searchText) {\n <button class=\"clear-search\" (click)=\"clearSearch()\">\n <span class=\"fa-solid fa-times-circle\"></span>\n </button>\n }\n </div>\n\n @if (config.allowCreate !== false) {\n <button class=\"create-button\" (click)=\"showCreateListForm()\" [disabled]=\"showCreateForm\">\n <span class=\"fa-solid fa-plus\"></span>\n <span class=\"button-text\">New</span>\n </button>\n }\n </div>\n\n <!-- Filter Tabs -->\n <div class=\"filter-tabs\">\n <div class=\"tabs-left\">\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'all'\"\n (click)=\"setActiveTab('all')\">\n All\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'my-lists'\"\n (click)=\"setActiveTab('my-lists')\">\n My Lists\n </button>\n <button\n class=\"tab-button\"\n [class.active]=\"activeTab === 'recent'\"\n (click)=\"setActiveTab('recent')\">\n Recent\n </button>\n </div>\n <div class=\"tabs-right\">\n <select class=\"sort-select\" [value]=\"sortOption\" (change)=\"setSortOption($any($event.target).value)\">\n <option value=\"name\">Sort: Name</option>\n <option value=\"recent\">Sort: Recent</option>\n <option value=\"item-count\">Sort: Items</option>\n </select>\n </div>\n </div>\n\n <!-- Create List Form -->\n @if (showCreateForm) {\n <div class=\"create-form\">\n <div class=\"create-form-header\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n <span>Create New List</span>\n </div>\n <div class=\"create-form-body\">\n <div class=\"form-group\">\n <input\n type=\"text\"\n class=\"form-input\"\n placeholder=\"List name *\"\n [(ngModel)]=\"newListName\"\n [disabled]=\"saving\"\n (keyup.enter)=\"createList()\"\n />\n </div>\n <div class=\"form-group\">\n <textarea\n class=\"form-input form-textarea\"\n placeholder=\"Description (optional)\"\n [(ngModel)]=\"newListDescription\"\n [disabled]=\"saving\"\n rows=\"2\">\n </textarea>\n </div>\n @if (categories.length > 0) {\n <div class=\"form-group\">\n <select class=\"form-input\" [(ngModel)]=\"newListCategoryId\" [disabled]=\"saving\">\n <option [ngValue]=\"null\">No category</option>\n @for (category of categories; track category.ID) {\n <option [ngValue]=\"category.ID\">{{ category.Name }}</option>\n }\n </select>\n </div>\n }\n <div class=\"create-form-actions\">\n <button\n class=\"btn btn-primary\"\n (click)=\"createList()\"\n [disabled]=\"!newListName.trim() || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Create List\n </button>\n <button class=\"btn btn-secondary\" (click)=\"cancelCreateList()\" [disabled]=\"saving\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- List Content -->\n <div class=\"list-content\">\n @if (loading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading lists...\" size=\"medium\"></mj-loading>\n </div>\n } @else if (filteredLists.length === 0) {\n @if (searchText) {\n <mj-empty-state\n Variant=\"no-results\"\n Icon=\"fa-solid fa-magnifying-glass\"\n Title=\"No lists found\"\n Message=\"Try a different search term\" />\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-rectangle-list\"\n Title=\"No lists yet\"\n Message=\"Create your first list to get started\"\n [ActionText]=\"config.allowCreate !== false ? 'Create List' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"showCreateListForm()\" />\n }\n } @else {\n <div class=\"list-items\">\n @for (vm of filteredLists; track vm.list.ID) {\n <div\n class=\"list-item\"\n [class.selected-add]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n [class.selected-remove]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n [class.is-member]=\"vm.isFullMember || vm.isPartialMember\">\n\n <!-- Checkbox / Selection Area -->\n <div class=\"list-item-select\">\n @if (showAddButton(vm)) {\n <button\n class=\"select-btn add-btn\"\n [class.selected]=\"vm.isSelectedForAdd || addedToLists.has(vm.list.ID)\"\n (click)=\"toggleListForAdd(vm)\"\n [title]=\"(vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) ? 'Remove from selection' : 'Add to this list'\">\n @if (vm.isSelectedForAdd || addedToLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-check\"></span>\n } @else {\n <span class=\"fa-solid fa-plus\"></span>\n }\n </button>\n }\n @if (showRemoveButton(vm) && (vm.isFullMember || vm.isPartialMember)) {\n <button\n class=\"select-btn remove-btn\"\n [class.selected]=\"vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)\"\n (click)=\"toggleListForRemove(vm)\"\n [title]=\"(vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) ? 'Cancel removal' : 'Remove from this list'\">\n @if (vm.isSelectedForRemove || removedFromLists.has(vm.list.ID)) {\n <span class=\"fa-solid fa-undo\"></span>\n } @else {\n <span class=\"fa-solid fa-minus\"></span>\n }\n </button>\n }\n </div>\n\n <!-- List Info -->\n <div class=\"list-item-content\">\n <div class=\"list-item-header\">\n <span class=\"fa-solid fa-folder list-icon\"></span>\n <span class=\"list-name\">{{ vm.list.Name }}</span>\n @if (newlyCreatedLists.includes(vm.list)) {\n <span class=\"badge badge-new\">New</span>\n }\n </div>\n <div class=\"list-item-meta\">\n @if (vm.list.Description) {\n <span class=\"list-description\">{{ vm.list.Description }}</span>\n <span class=\"meta-separator\">•</span>\n }\n <span class=\"list-count\">{{ vm.itemCount }} item{{ vm.itemCount !== 1 ? 's' : '' }}</span>\n <span class=\"meta-separator\">•</span>\n <span class=\"list-updated\">{{ formatDate(vm.lastUpdated) }}</span>\n </div>\n </div>\n\n <!-- Membership Indicator -->\n @if (config.showMembership !== false) {\n <div class=\"membership-indicator\" [class]=\"getMembershipClass(vm)\">\n <span [class]=\"getMembershipIcon(vm)\"></span>\n <span class=\"membership-text\">{{ getMembershipText(vm) }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"dialog-footer\">\n <div class=\"footer-summary\">\n @if (hasChanges) {\n @if (addCount > 0) {\n <span class=\"summary-item add\">\n <span class=\"fa-solid fa-plus-circle\"></span>\n {{ addCount }} list{{ addCount !== 1 ? 's' : '' }}\n </span>\n }\n @if (removeCount > 0) {\n <span class=\"summary-item remove\">\n <span class=\"fa-solid fa-minus-circle\"></span>\n {{ removeCount }} list{{ removeCount !== 1 ? 's' : '' }}\n </span>\n }\n } @else {\n <span class=\"summary-empty\">No changes</span>\n }\n </div>\n <div class=\"footer-actions\">\n <button class=\"btn btn-secondary\" (click)=\"onCancel()\" [disabled]=\"saving\">\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"applyChanges()\"\n [disabled]=\"!hasChanges || saving\">\n @if (saving) {\n <span class=\"fa-solid fa-spinner fa-spin\"></span>\n }\n Apply Changes\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n"]}
|
|
@@ -69,6 +69,21 @@ export interface ListManagementResult {
|
|
|
69
69
|
* New lists that were created during this session
|
|
70
70
|
*/
|
|
71
71
|
newListsCreated: MJListEntity[];
|
|
72
|
+
/**
|
|
73
|
+
* Aggregate outcome of the apply operation, so hosts can tell the user
|
|
74
|
+
* about silently-skipped duplicates or partial failures. Only present
|
|
75
|
+
* when action === 'apply'.
|
|
76
|
+
*/
|
|
77
|
+
summary?: {
|
|
78
|
+
/** Membership rows actually created */
|
|
79
|
+
added: number;
|
|
80
|
+
/** Membership rows actually removed */
|
|
81
|
+
removed: number;
|
|
82
|
+
/** Records skipped because they were already in the target list(s) */
|
|
83
|
+
skipped: number;
|
|
84
|
+
/** Records that failed to add/remove */
|
|
85
|
+
failed: number;
|
|
86
|
+
};
|
|
72
87
|
}
|
|
73
88
|
/**
|
|
74
89
|
* Details of a list operation (add or remove)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management.models.d.ts","sourceRoot":"","sources":["../../../src/lib/models/list-management.models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAsB,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAElC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IAE3B;;OAEG;IACH,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAE7B;;OAEG;IACH,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAE/B;;OAEG;IACH,eAAe,EAAE,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"list-management.models.d.ts","sourceRoot":"","sources":["../../../src/lib/models/list-management.models.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management.models.js","sourceRoot":"","sources":["../../../src/lib/models/list-management.models.ts"],"names":[],"mappings":"","sourcesContent":["import { MJListEntity, MJListDetailEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\n\n/**\n * Configuration for the ListManagementDialog component\n */\nexport interface ListManagementDialogConfig {\n /**\n * Operation mode for the dialog\n * - 'add': Only show add functionality\n * - 'remove': Only show remove functionality\n * - 'manage': Show both add and remove (full management)\n */\n mode: 'add' | 'remove' | 'manage';\n\n /**\n * The Entity ID that the lists are associated with\n */\n entityId: string;\n\n /**\n * Display name of the entity (for UI labels)\n */\n entityName: string;\n\n /**\n * Array of record IDs to add/remove from lists\n */\n recordIds: string[];\n\n /**\n * Optional display names for the records (for better context in UI)\n */\n recordDisplayNames?: string[];\n\n /**\n * Allow inline creation of new lists (default: true)\n */\n allowCreate?: boolean;\n\n /**\n * Allow removing records from lists (default: true in 'manage' mode)\n */\n allowRemove?: boolean;\n\n /**\n * Show membership indicators on lists (default: true)\n */\n showMembership?: boolean;\n\n /**\n * Pre-select specific lists by their IDs\n */\n preSelectedListIds?: string[];\n\n /**\n * Optional title override for the dialog\n */\n dialogTitle?: string;\n}\n\n/**\n * Result returned when the ListManagementDialog is closed\n */\nexport interface ListManagementResult {\n /**\n * Action taken by the user\n * - 'apply': User confirmed changes\n * - 'cancel': User cancelled without applying changes\n */\n action: 'apply' | 'cancel';\n\n /**\n * Lists and records that were added\n */\n added: ListOperationDetail[];\n\n /**\n * Lists and records that were removed\n */\n removed: ListOperationDetail[];\n\n /**\n * New lists that were created during this session\n */\n newListsCreated: MJListEntity[];\n}\n\n/**\n * Details of a list operation (add or remove)\n */\nexport interface ListOperationDetail {\n /**\n * The list ID that was modified\n */\n listId: string;\n\n /**\n * The list name (for display purposes)\n */\n listName: string;\n\n /**\n * Record IDs that were added/removed\n */\n recordIds: string[];\n}\n\n/**\n * View model for displaying a list in the dialog\n */\nexport interface ListItemViewModel {\n /**\n * The underlying list entity\n */\n list: MJListEntity;\n\n /**\n * Total number of items in this list\n */\n itemCount: number;\n\n /**\n * Number of selected records that are already in this list\n */\n membershipCount: number;\n\n /**\n * Total number of records being managed\n */\n totalSelectedRecords: number;\n\n /**\n * True if all selected records are in this list\n */\n isFullMember: boolean;\n\n /**\n * True if some (but not all) selected records are in this list\n */\n isPartialMember: boolean;\n\n /**\n * True if no selected records are in this list\n */\n isNotMember: boolean;\n\n /**\n * Last updated timestamp\n */\n lastUpdated: Date;\n\n /**\n * Category entity if categorized\n */\n category?: MJListCategoryEntity;\n\n /**\n * Whether this list is selected for adding records\n */\n isSelectedForAdd: boolean;\n\n /**\n * Whether this list is selected for removing records\n */\n isSelectedForRemove: boolean;\n}\n\n/**\n * Filter/tab options for the list display\n */\nexport type ListFilterTab = 'all' | 'my-lists' | 'shared' | 'recent';\n\n/**\n * Sort options for the list display\n */\nexport type ListSortOption = 'name' | 'recent' | 'item-count';\n\n/**\n * Configuration for creating a new list inline\n */\nexport interface CreateListConfig {\n /**\n * Name for the new list\n */\n name: string;\n\n /**\n * Optional description\n */\n description?: string;\n\n /**\n * Optional category ID\n */\n categoryId?: string;\n\n /**\n * Entity ID the list is for\n */\n entityId: string;\n}\n\n/**\n * Batch operation result for adding/removing records\n */\nexport interface BatchOperationResult {\n /**\n * Number of successful operations\n */\n success: number;\n\n /**\n * Number of failed operations\n */\n failed: number;\n\n /**\n * Number of skipped operations (e.g., duplicates)\n */\n skipped: number;\n\n /**\n * Error messages if any failures occurred\n */\n errors: string[];\n}\n\n/**\n * Membership info for a single record\n */\nexport interface RecordMembershipInfo {\n /**\n * The record ID\n */\n recordId: string;\n\n /**\n * List IDs this record belongs to\n */\n listIds: string[];\n\n /**\n * Full list entities this record belongs to\n */\n lists: MJListEntity[];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"list-management.models.js","sourceRoot":"","sources":["../../../src/lib/models/list-management.models.ts"],"names":[],"mappings":"","sourcesContent":["import { MJListEntity, MJListDetailEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\n\n/**\n * Configuration for the ListManagementDialog component\n */\nexport interface ListManagementDialogConfig {\n /**\n * Operation mode for the dialog\n * - 'add': Only show add functionality\n * - 'remove': Only show remove functionality\n * - 'manage': Show both add and remove (full management)\n */\n mode: 'add' | 'remove' | 'manage';\n\n /**\n * The Entity ID that the lists are associated with\n */\n entityId: string;\n\n /**\n * Display name of the entity (for UI labels)\n */\n entityName: string;\n\n /**\n * Array of record IDs to add/remove from lists\n */\n recordIds: string[];\n\n /**\n * Optional display names for the records (for better context in UI)\n */\n recordDisplayNames?: string[];\n\n /**\n * Allow inline creation of new lists (default: true)\n */\n allowCreate?: boolean;\n\n /**\n * Allow removing records from lists (default: true in 'manage' mode)\n */\n allowRemove?: boolean;\n\n /**\n * Show membership indicators on lists (default: true)\n */\n showMembership?: boolean;\n\n /**\n * Pre-select specific lists by their IDs\n */\n preSelectedListIds?: string[];\n\n /**\n * Optional title override for the dialog\n */\n dialogTitle?: string;\n}\n\n/**\n * Result returned when the ListManagementDialog is closed\n */\nexport interface ListManagementResult {\n /**\n * Action taken by the user\n * - 'apply': User confirmed changes\n * - 'cancel': User cancelled without applying changes\n */\n action: 'apply' | 'cancel';\n\n /**\n * Lists and records that were added\n */\n added: ListOperationDetail[];\n\n /**\n * Lists and records that were removed\n */\n removed: ListOperationDetail[];\n\n /**\n * New lists that were created during this session\n */\n newListsCreated: MJListEntity[];\n\n /**\n * Aggregate outcome of the apply operation, so hosts can tell the user\n * about silently-skipped duplicates or partial failures. Only present\n * when action === 'apply'.\n */\n summary?: {\n /** Membership rows actually created */\n added: number;\n /** Membership rows actually removed */\n removed: number;\n /** Records skipped because they were already in the target list(s) */\n skipped: number;\n /** Records that failed to add/remove */\n failed: number;\n };\n}\n\n/**\n * Details of a list operation (add or remove)\n */\nexport interface ListOperationDetail {\n /**\n * The list ID that was modified\n */\n listId: string;\n\n /**\n * The list name (for display purposes)\n */\n listName: string;\n\n /**\n * Record IDs that were added/removed\n */\n recordIds: string[];\n}\n\n/**\n * View model for displaying a list in the dialog\n */\nexport interface ListItemViewModel {\n /**\n * The underlying list entity\n */\n list: MJListEntity;\n\n /**\n * Total number of items in this list\n */\n itemCount: number;\n\n /**\n * Number of selected records that are already in this list\n */\n membershipCount: number;\n\n /**\n * Total number of records being managed\n */\n totalSelectedRecords: number;\n\n /**\n * True if all selected records are in this list\n */\n isFullMember: boolean;\n\n /**\n * True if some (but not all) selected records are in this list\n */\n isPartialMember: boolean;\n\n /**\n * True if no selected records are in this list\n */\n isNotMember: boolean;\n\n /**\n * Last updated timestamp\n */\n lastUpdated: Date;\n\n /**\n * Category entity if categorized\n */\n category?: MJListCategoryEntity;\n\n /**\n * Whether this list is selected for adding records\n */\n isSelectedForAdd: boolean;\n\n /**\n * Whether this list is selected for removing records\n */\n isSelectedForRemove: boolean;\n}\n\n/**\n * Filter/tab options for the list display\n */\nexport type ListFilterTab = 'all' | 'my-lists' | 'shared' | 'recent';\n\n/**\n * Sort options for the list display\n */\nexport type ListSortOption = 'name' | 'recent' | 'item-count';\n\n/**\n * Configuration for creating a new list inline\n */\nexport interface CreateListConfig {\n /**\n * Name for the new list\n */\n name: string;\n\n /**\n * Optional description\n */\n description?: string;\n\n /**\n * Optional category ID\n */\n categoryId?: string;\n\n /**\n * Entity ID the list is for\n */\n entityId: string;\n}\n\n/**\n * Batch operation result for adding/removing records\n */\nexport interface BatchOperationResult {\n /**\n * Number of successful operations\n */\n success: number;\n\n /**\n * Number of failed operations\n */\n failed: number;\n\n /**\n * Number of skipped operations (e.g., duplicates)\n */\n skipped: number;\n\n /**\n * Error messages if any failures occurred\n */\n errors: string[];\n}\n\n/**\n * Membership info for a single record\n */\nexport interface RecordMembershipInfo {\n /**\n * The record ID\n */\n recordId: string;\n\n /**\n * List IDs this record belongs to\n */\n listIds: string[];\n\n /**\n * Full list entities this record belongs to\n */\n lists: MJListEntity[];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/list-management.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA+B,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAsB,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EAEpB,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;;AAO1C;;;;;;GAMG;AACH,qBAGa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAG9C,OAAO,CAAC,SAAS,CAAiD;IAClE,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,eAAe,CAAwD;IAG/E,OAAO,CAAC,cAAc,CAAuC;IACtD,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAsC;IAE1E,OAAO,CAAC,SAAS,CAAkC;IAEnD,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IACD,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAElD;;IAID;;OAEG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,EAAE,CAAC;IA4C1B;;OAEG;IACG,iBAAiB,CAAC,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAuBvF;;;OAGG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"list-management.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/list-management.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA+B,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAsB,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACvG,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EAEpB,gBAAgB,EACjB,MAAM,kCAAkC,CAAC;;AAO1C;;;;;;GAMG;AACH,qBAGa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAG9C,OAAO,CAAC,SAAS,CAAiD;IAClE,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,eAAe,CAAwD;IAG/E,OAAO,CAAC,cAAc,CAAuC;IACtD,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAsC;IAE1E,OAAO,CAAC,SAAS,CAAkC;IAEnD,IAAW,QAAQ,IAAI,iBAAiB,CAEvC;IACD,IAAW,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAElD;;IAID;;OAEG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,YAAY,EAAE,CAAC;IA4C1B;;OAEG;IACG,iBAAiB,CAAC,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAuBvF;;;OAGG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAmDjC;;OAEG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC;IA4B1B;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvD;;OAEG;IACG,mBAAmB,CACvB,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAChC,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA0C/B;;OAEG;IACG,iBAAiB,CACrB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,EAAE,EACnB,cAAc,GAAE,OAAc,GAC7B,OAAO,CAAC,oBAAoB,CAAC;IAyFhC;;OAEG;IACG,sBAAsB,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,oBAAoB,CAAC;IAuEhC;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA6BxE;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAUxC;;OAEG;IACH,OAAO,CAAC,mBAAmB;yCArehB,qBAAqB;6CAArB,qBAAqB;CA6ejC"}
|
|
@@ -107,12 +107,14 @@ export class ListManagementService {
|
|
|
107
107
|
this.loadingSubject.next(true);
|
|
108
108
|
try {
|
|
109
109
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
110
|
-
// Get all list details for these records
|
|
110
|
+
// Get all list details for these records — read-only lookup, so
|
|
111
|
+
// 'simple' with narrow Fields (no BaseEntity instantiation overhead)
|
|
111
112
|
const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');
|
|
112
113
|
const result = await rv.RunView({
|
|
113
114
|
EntityName: 'MJ: List Details',
|
|
114
115
|
ExtraFilter: `RecordID IN (${recordIdFilter})`,
|
|
115
|
-
|
|
116
|
+
Fields: ['ListID', 'RecordID'],
|
|
117
|
+
ResultType: 'simple'
|
|
116
118
|
});
|
|
117
119
|
const membership = new Map();
|
|
118
120
|
if (result.Success && result.Results) {
|
|
@@ -139,16 +141,17 @@ export class ListManagementService {
|
|
|
139
141
|
*/
|
|
140
142
|
async getListsForRecord(entityId, recordId) {
|
|
141
143
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
142
|
-
// Get list details for this record
|
|
144
|
+
// Get list details for this record — read-only lookup
|
|
143
145
|
const detailsResult = await rv.RunView({
|
|
144
146
|
EntityName: 'MJ: List Details',
|
|
145
147
|
ExtraFilter: `RecordID = '${recordId}'`,
|
|
146
|
-
|
|
148
|
+
Fields: ['ListID'],
|
|
149
|
+
ResultType: 'simple'
|
|
147
150
|
});
|
|
148
151
|
if (!detailsResult.Success || !detailsResult.Results || detailsResult.Results.length === 0) {
|
|
149
152
|
return [];
|
|
150
153
|
}
|
|
151
|
-
const listIds = [...new Set(detailsResult.Results.map(
|
|
154
|
+
const listIds = [...new Set(detailsResult.Results.map(d => d.ListID))];
|
|
152
155
|
// Get the lists filtered by entity
|
|
153
156
|
const listIdFilter = listIds.map(id => `'${id}'`).join(',');
|
|
154
157
|
const listsResult = await rv.RunView({
|
|
@@ -176,22 +179,19 @@ export class ListManagementService {
|
|
|
176
179
|
async buildListViewModels(lists, recordIds, membership) {
|
|
177
180
|
const viewModels = [];
|
|
178
181
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
179
|
-
// Get item counts for all lists in one
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
// Get counts grouped by list - using a regular query since we need aggregation
|
|
183
|
-
const countsResult = await rv.RunView({
|
|
184
|
-
EntityName: 'MJ: List Details',
|
|
185
|
-
ExtraFilter: listIds.length > 0 ? `ListID IN (${listIdFilter})` : '1=0',
|
|
186
|
-
ResultType: 'entity_object'
|
|
187
|
-
});
|
|
188
|
-
// Build count map
|
|
182
|
+
// Get item counts for all lists in one batched round trip of count_only
|
|
183
|
+
// queries — each an index-seek COUNT server-side. Never download the
|
|
184
|
+
// membership rows just to count them.
|
|
189
185
|
const countMap = new Map();
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
186
|
+
if (lists.length > 0) {
|
|
187
|
+
const countResults = await rv.RunViews(lists.map(list => ({
|
|
188
|
+
EntityName: 'MJ: List Details',
|
|
189
|
+
ExtraFilter: `ListID = '${list.ID}'`,
|
|
190
|
+
ResultType: 'count_only'
|
|
191
|
+
})));
|
|
192
|
+
countResults.forEach((res, idx) => {
|
|
193
|
+
countMap.set(lists[idx].ID, res.Success ? res.TotalRowCount : 0);
|
|
194
|
+
});
|
|
195
195
|
}
|
|
196
196
|
for (const list of lists) {
|
|
197
197
|
const memberRecordIds = membership.get(list.ID) || [];
|
|
@@ -233,7 +233,8 @@ export class ListManagementService {
|
|
|
233
233
|
const existing = await rv.RunView({
|
|
234
234
|
EntityName: 'MJ: List Details',
|
|
235
235
|
ExtraFilter: `ListID IN (${listIdFilter}) AND RecordID IN (${recordIdFilter})`,
|
|
236
|
-
|
|
236
|
+
Fields: ['ListID', 'RecordID'],
|
|
237
|
+
ResultType: 'simple'
|
|
237
238
|
}, md.CurrentUser);
|
|
238
239
|
if (existing.Success && existing.Results) {
|
|
239
240
|
for (const detail of existing.Results) {
|
|
@@ -318,16 +319,29 @@ export class ListManagementService {
|
|
|
318
319
|
result.errors.push('Failed to query existing list details');
|
|
319
320
|
return result;
|
|
320
321
|
}
|
|
321
|
-
|
|
322
|
-
|
|
322
|
+
const toDelete = existingResult.Results || [];
|
|
323
|
+
if (toDelete.length === 0) {
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
// Queue all deletes in one TransactionGroup — a single round trip
|
|
327
|
+
// instead of one per removed membership row. Deliberately atomic (unlike
|
|
328
|
+
// the server-side bulk paths, which trade atomicity for per-record error
|
|
329
|
+
// isolation): if Submit() fails, the transaction rolled back and no rows
|
|
330
|
+
// were removed.
|
|
331
|
+
const tg = await md.CreateTransactionGroup();
|
|
332
|
+
let queued = 0;
|
|
333
|
+
for (const detail of toDelete) {
|
|
323
334
|
try {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
335
|
+
detail.TransactionGroup = tg;
|
|
336
|
+
// With a TransactionGroup set, Delete() returns true once enqueued;
|
|
337
|
+
// false means a pre-enqueue failure (validation/permission) and the
|
|
338
|
+
// row never joined the transaction.
|
|
339
|
+
if (await detail.Delete()) {
|
|
340
|
+
queued++;
|
|
327
341
|
}
|
|
328
342
|
else {
|
|
329
343
|
result.failed++;
|
|
330
|
-
result.errors.push(`Failed to
|
|
344
|
+
result.errors.push(`Failed to queue removal of record ${detail.RecordID} from list ${detail.ListID}: ${detail.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
331
345
|
}
|
|
332
346
|
}
|
|
333
347
|
catch (error) {
|
|
@@ -336,6 +350,14 @@ export class ListManagementService {
|
|
|
336
350
|
result.errors.push(`Error removing record: ${errorMessage}`);
|
|
337
351
|
}
|
|
338
352
|
}
|
|
353
|
+
const submitted = queued === 0 || await tg.Submit();
|
|
354
|
+
if (submitted) {
|
|
355
|
+
result.success = queued;
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
result.failed += queued;
|
|
359
|
+
result.errors.push('Transaction failed to submit');
|
|
360
|
+
}
|
|
339
361
|
// Invalidate caches
|
|
340
362
|
this.membershipCache.clear();
|
|
341
363
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-management.service.js","sourceRoot":"","sources":["../../../src/lib/services/list-management.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { IMetadataProvider, Metadata, RunView, UserInfo } from '@memberjunction/core';\nimport { MJListEntity, MJListDetailEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport {\n ListItemViewModel,\n BatchOperationResult,\n RecordMembershipInfo,\n CreateListConfig\n} from '../models/list-management.models';\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: Date;\n}\n\n/**\n * Service for managing list operations including data loading, caching,\n * and batch add/remove operations.\n *\n * Multi-provider note: callers under a non-default provider should set\n * `service.Provider = component.ProviderToUse` before invoking any methods.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ListManagementService {\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n // Cache storage\n private listCache = new Map<string, CacheEntry<MJListEntity[]>>();\n private categoryCache: CacheEntry<MJListCategoryEntity[]> | null = null;\n private membershipCache = new Map<string, CacheEntry<Map<string, string[]>>>();\n\n // Loading state subjects\n private loadingSubject = new BehaviorSubject<boolean>(false);\n public loading$: Observable<boolean> = this.loadingSubject.asObservable();\n\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 }\n\n constructor() {}\n\n /**\n * Get lists for a specific entity, with optional caching\n */\n async getListsForEntity(\n entityId: string,\n userId?: string,\n forceRefresh: boolean = false\n ): Promise<MJListEntity[]> {\n const cacheKey = `${entityId}_${userId || 'all'}`;\n\n // Check cache first\n if (!forceRefresh) {\n const cached = this.listCache.get(cacheKey);\n if (cached && this.isCacheValid(cached)) {\n return cached.data;\n }\n }\n\n this.loadingSubject.next(true);\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n let filter = `EntityID = '${entityId}'`;\n\n if (userId) {\n filter += ` AND UserID = '${userId}'`;\n }\n\n const result = await rv.RunView<MJListEntity>({\n EntityName: 'MJ: Lists',\n ExtraFilter: filter,\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n const lists = result.Results || [];\n this.listCache.set(cacheKey, {\n data: lists,\n timestamp: new Date()\n });\n return lists;\n } else {\n console.error('Failed to load lists:', result.ErrorMessage);\n return [];\n }\n } finally {\n this.loadingSubject.next(false);\n }\n }\n\n /**\n * Get all list categories\n */\n async getListCategories(forceRefresh: boolean = false): Promise<MJListCategoryEntity[]> {\n if (!forceRefresh && this.categoryCache && this.isCacheValid(this.categoryCache)) {\n return this.categoryCache.data;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJListCategoryEntity>({\n EntityName: 'MJ: List Categories',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.categoryCache = {\n data: result.Results || [],\n timestamp: new Date()\n };\n return this.categoryCache.data;\n }\n\n return [];\n }\n\n /**\n * Get membership information for a set of records\n * Returns a Map where key is listId and value is array of recordIds that are members\n */\n async getRecordMembership(\n entityId: string,\n recordIds: string[]\n ): Promise<Map<string, string[]>> {\n if (recordIds.length === 0) {\n return new Map();\n }\n\n const cacheKey = `${entityId}_${recordIds.sort().join(',')}`;\n\n // Check cache\n const cached = this.membershipCache.get(cacheKey);\n if (cached && this.isCacheValid(cached)) {\n return cached.data;\n }\n\n this.loadingSubject.next(true);\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get all list details for these records\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n const result = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `RecordID IN (${recordIdFilter})`,\n ResultType: 'entity_object'\n });\n\n const membership = new Map<string, string[]>();\n\n if (result.Success && result.Results) {\n for (const detail of result.Results) {\n const existingRecords = membership.get(detail.ListID) || [];\n if (!existingRecords.includes(detail.RecordID)) {\n existingRecords.push(detail.RecordID);\n }\n membership.set(detail.ListID, existingRecords);\n }\n }\n\n this.membershipCache.set(cacheKey, {\n data: membership,\n timestamp: new Date()\n });\n\n return membership;\n } finally {\n this.loadingSubject.next(false);\n }\n }\n\n /**\n * Get lists that contain a specific record\n */\n async getListsForRecord(\n entityId: string,\n recordId: string\n ): Promise<MJListEntity[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get list details for this record\n const detailsResult = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `RecordID = '${recordId}'`,\n ResultType: 'entity_object'\n });\n\n if (!detailsResult.Success || !detailsResult.Results || detailsResult.Results.length === 0) {\n return [];\n }\n\n const listIds = [...new Set(detailsResult.Results.map((d: MJListDetailEntity) => d.ListID))];\n\n // Get the lists filtered by entity\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const listsResult = await rv.RunView<MJListEntity>({\n EntityName: 'MJ: Lists',\n ExtraFilter: `ID IN (${listIdFilter}) AND EntityID = '${entityId}'`,\n ResultType: 'entity_object'\n });\n\n return listsResult.Success ? (listsResult.Results || []) : [];\n }\n\n /**\n * Get item count for a list\n */\n async getListItemCount(listId: string): Promise<number> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID = '${listId}'`,\n ResultType: 'count_only'\n });\n\n return result.Success ? result.TotalRowCount : 0;\n }\n\n /**\n * Build view models for lists with membership information\n */\n async buildListViewModels(\n lists: MJListEntity[],\n recordIds: string[],\n membership: Map<string, string[]>\n ): Promise<ListItemViewModel[]> {\n const viewModels: ListItemViewModel[] = [];\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get item counts for all lists in one batch query\n const listIds = lists.map(l => l.ID);\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n\n // Get counts grouped by list - using a regular query since we need aggregation\n const countsResult = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: listIds.length > 0 ? `ListID IN (${listIdFilter})` : '1=0',\n ResultType: 'entity_object'\n });\n\n // Build count map\n const countMap = new Map<string, number>();\n if (countsResult.Success && countsResult.Results) {\n for (const detail of countsResult.Results) {\n const current = countMap.get(detail.ListID) || 0;\n countMap.set(detail.ListID, current + 1);\n }\n }\n\n for (const list of lists) {\n const memberRecordIds = membership.get(list.ID) || [];\n const membershipCount = memberRecordIds.length;\n const totalSelected = recordIds.length;\n\n viewModels.push({\n list,\n itemCount: countMap.get(list.ID) || 0,\n membershipCount,\n totalSelectedRecords: totalSelected,\n isFullMember: membershipCount === totalSelected && totalSelected > 0,\n isPartialMember: membershipCount > 0 && membershipCount < totalSelected,\n isNotMember: membershipCount === 0,\n lastUpdated: list.Get('__mj_UpdatedAt') as Date || new Date(),\n category: undefined, // Can be populated separately if needed\n isSelectedForAdd: false,\n isSelectedForRemove: false\n });\n }\n\n return viewModels;\n }\n\n /**\n * Add records to one or more lists\n */\n async addRecordsToLists(\n listIds: string[],\n recordIds: string[],\n skipDuplicates: boolean = true\n ): Promise<BatchOperationResult> {\n const result: BatchOperationResult = {\n success: 0,\n failed: 0,\n skipped: 0,\n errors: []\n };\n\n const md = this.Provider;\n\n // Get existing membership to skip duplicates\n let existingMembership = new Map<string, Set<string>>();\n if (skipDuplicates) {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n\n const existing = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID IN (${listIdFilter}) AND RecordID IN (${recordIdFilter})`,\n ResultType: 'entity_object'\n }, md.CurrentUser);\n\n if (existing.Success && existing.Results) {\n for (const detail of existing.Results) {\n const recordSet = existingMembership.get(detail.ListID) || new Set();\n recordSet.add(detail.RecordID);\n existingMembership.set(detail.ListID, recordSet);\n }\n }\n }\n\n // Build list of records to add (excluding duplicates)\n const recordsToAdd: Array<{listId: string, recordId: string}> = [];\n for (const listId of listIds) {\n const existingRecords = existingMembership.get(listId) || new Set();\n for (const recordId of recordIds) {\n if (skipDuplicates && existingRecords.has(recordId)) {\n result.skipped++;\n } else {\n recordsToAdd.push({ listId, recordId });\n }\n }\n }\n\n if (recordsToAdd.length === 0) {\n return result;\n }\n\n // Use transaction group for bulk insert\n const tg = await md.CreateTransactionGroup();\n\n for (const { listId, recordId } of recordsToAdd) {\n try {\n const listDetail = await md.GetEntityObject<MJListDetailEntity>('MJ: List Details', md.CurrentUser);\n listDetail.ListID = listId;\n listDetail.RecordID = recordId;\n listDetail.TransactionGroup = tg;\n const saveResult = await listDetail.Save();\n if (!saveResult) {\n console.error(`[ListManagementService] Failed to queue record ${recordId} for list ${listId}:`, listDetail.LatestResult?.Message);\n result.errors.push(`Failed to add record ${recordId} to list ${listId}: ${listDetail.LatestResult?.Message || 'Unknown error'}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`[ListManagementService] Exception adding record:`, error);\n result.errors.push(`Error adding record ${recordId} to list ${listId}: ${errorMessage}`);\n }\n }\n\n // Submit the transaction\n const success = await tg.Submit();\n\n if (success) {\n result.success = recordsToAdd.length - result.errors.length;\n result.failed = result.errors.length;\n } else {\n result.failed = recordsToAdd.length;\n result.success = 0;\n result.errors.push('Transaction failed to submit');\n }\n\n // Invalidate membership cache\n this.membershipCache.clear();\n\n return result;\n }\n\n /**\n * Remove records from one or more lists\n */\n async removeRecordsFromLists(\n listIds: string[],\n recordIds: string[]\n ): Promise<BatchOperationResult> {\n const result: BatchOperationResult = {\n success: 0,\n failed: 0,\n skipped: 0,\n errors: []\n };\n\n const md = this.Provider;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Find existing list details to delete\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n\n const existingResult = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID IN (${listIdFilter}) AND RecordID IN (${recordIdFilter})`,\n ResultType: 'entity_object'\n });\n\n if (!existingResult.Success) {\n result.errors.push('Failed to query existing list details');\n return result;\n }\n\n // Delete each matching detail\n for (const detail of existingResult.Results || []) {\n try {\n const deleteResult = await detail.Delete();\n if (deleteResult) {\n result.success++;\n } else {\n result.failed++;\n result.errors.push(`Failed to remove record ${detail.RecordID} from list ${detail.ListID}`);\n }\n } catch (error) {\n result.failed++;\n const errorMessage = error instanceof Error ? error.message : String(error);\n result.errors.push(`Error removing record: ${errorMessage}`);\n }\n }\n\n // Invalidate caches\n this.membershipCache.clear();\n\n return result;\n }\n\n /**\n * Create a new list\n */\n async createList(config: CreateListConfig): Promise<MJListEntity | null> {\n const md = this.Provider;\n\n try {\n const list = await md.GetEntityObject<MJListEntity>('MJ: Lists', md.CurrentUser);\n list.NewRecord();\n list.Name = config.name;\n list.Description = config.description || '';\n list.EntityID = config.entityId;\n list.UserID = md.CurrentUser.ID;\n\n if (config.categoryId) {\n list.CategoryID = config.categoryId;\n }\n\n const saveResult = await list.Save();\n if (saveResult) {\n // Invalidate list cache\n this.invalidateListCache(config.entityId);\n return list;\n }\n\n return null;\n } catch (error) {\n console.error('Error creating list:', error);\n return null;\n }\n }\n\n /**\n * Check if a cache entry is still valid\n */\n private isCacheValid<T>(entry: CacheEntry<T>): boolean {\n const now = new Date().getTime();\n const entryTime = entry.timestamp.getTime();\n return (now - entryTime) < this.CACHE_TTL_MS;\n }\n\n /**\n * Invalidate cache for a specific entity or all caches\n */\n invalidateCache(entityId?: string): void {\n if (entityId) {\n this.invalidateListCache(entityId);\n } else {\n this.listCache.clear();\n this.categoryCache = null;\n this.membershipCache.clear();\n }\n }\n\n /**\n * Invalidate list cache for a specific entity\n */\n private invalidateListCache(entityId: string): void {\n // Remove all cache entries that start with this entityId\n for (const key of this.listCache.keys()) {\n if (key.startsWith(entityId)) {\n this.listCache.delete(key);\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"list-management.service.js","sourceRoot":"","sources":["../../../src/lib/services/list-management.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { IMetadataProvider, Metadata, RunView, UserInfo } from '@memberjunction/core';\nimport { MJListEntity, MJListDetailEntity, MJListCategoryEntity } from '@memberjunction/core-entities';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport {\n ListItemViewModel,\n BatchOperationResult,\n RecordMembershipInfo,\n CreateListConfig\n} from '../models/list-management.models';\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: Date;\n}\n\n/**\n * Service for managing list operations including data loading, caching,\n * and batch add/remove operations.\n *\n * Multi-provider note: callers under a non-default provider should set\n * `service.Provider = component.ProviderToUse` before invoking any methods.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ListManagementService {\n private readonly CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n // Cache storage\n private listCache = new Map<string, CacheEntry<MJListEntity[]>>();\n private categoryCache: CacheEntry<MJListCategoryEntity[]> | null = null;\n private membershipCache = new Map<string, CacheEntry<Map<string, string[]>>>();\n\n // Loading state subjects\n private loadingSubject = new BehaviorSubject<boolean>(false);\n public loading$: Observable<boolean> = this.loadingSubject.asObservable();\n\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 }\n\n constructor() {}\n\n /**\n * Get lists for a specific entity, with optional caching\n */\n async getListsForEntity(\n entityId: string,\n userId?: string,\n forceRefresh: boolean = false\n ): Promise<MJListEntity[]> {\n const cacheKey = `${entityId}_${userId || 'all'}`;\n\n // Check cache first\n if (!forceRefresh) {\n const cached = this.listCache.get(cacheKey);\n if (cached && this.isCacheValid(cached)) {\n return cached.data;\n }\n }\n\n this.loadingSubject.next(true);\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n let filter = `EntityID = '${entityId}'`;\n\n if (userId) {\n filter += ` AND UserID = '${userId}'`;\n }\n\n const result = await rv.RunView<MJListEntity>({\n EntityName: 'MJ: Lists',\n ExtraFilter: filter,\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n const lists = result.Results || [];\n this.listCache.set(cacheKey, {\n data: lists,\n timestamp: new Date()\n });\n return lists;\n } else {\n console.error('Failed to load lists:', result.ErrorMessage);\n return [];\n }\n } finally {\n this.loadingSubject.next(false);\n }\n }\n\n /**\n * Get all list categories\n */\n async getListCategories(forceRefresh: boolean = false): Promise<MJListCategoryEntity[]> {\n if (!forceRefresh && this.categoryCache && this.isCacheValid(this.categoryCache)) {\n return this.categoryCache.data;\n }\n\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView<MJListCategoryEntity>({\n EntityName: 'MJ: List Categories',\n OrderBy: 'Name',\n ResultType: 'entity_object'\n });\n\n if (result.Success) {\n this.categoryCache = {\n data: result.Results || [],\n timestamp: new Date()\n };\n return this.categoryCache.data;\n }\n\n return [];\n }\n\n /**\n * Get membership information for a set of records\n * Returns a Map where key is listId and value is array of recordIds that are members\n */\n async getRecordMembership(\n entityId: string,\n recordIds: string[]\n ): Promise<Map<string, string[]>> {\n if (recordIds.length === 0) {\n return new Map();\n }\n\n const cacheKey = `${entityId}_${recordIds.sort().join(',')}`;\n\n // Check cache\n const cached = this.membershipCache.get(cacheKey);\n if (cached && this.isCacheValid(cached)) {\n return cached.data;\n }\n\n this.loadingSubject.next(true);\n\n try {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get all list details for these records — read-only lookup, so\n // 'simple' with narrow Fields (no BaseEntity instantiation overhead)\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n const result = await rv.RunView<{ ListID: string; RecordID: string }>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `RecordID IN (${recordIdFilter})`,\n Fields: ['ListID', 'RecordID'],\n ResultType: 'simple'\n });\n\n const membership = new Map<string, string[]>();\n\n if (result.Success && result.Results) {\n for (const detail of result.Results) {\n const existingRecords = membership.get(detail.ListID) || [];\n if (!existingRecords.includes(detail.RecordID)) {\n existingRecords.push(detail.RecordID);\n }\n membership.set(detail.ListID, existingRecords);\n }\n }\n\n this.membershipCache.set(cacheKey, {\n data: membership,\n timestamp: new Date()\n });\n\n return membership;\n } finally {\n this.loadingSubject.next(false);\n }\n }\n\n /**\n * Get lists that contain a specific record\n */\n async getListsForRecord(\n entityId: string,\n recordId: string\n ): Promise<MJListEntity[]> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get list details for this record — read-only lookup\n const detailsResult = await rv.RunView<{ ListID: string }>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `RecordID = '${recordId}'`,\n Fields: ['ListID'],\n ResultType: 'simple'\n });\n\n if (!detailsResult.Success || !detailsResult.Results || detailsResult.Results.length === 0) {\n return [];\n }\n\n const listIds = [...new Set(detailsResult.Results.map(d => d.ListID))];\n\n // Get the lists filtered by entity\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const listsResult = await rv.RunView<MJListEntity>({\n EntityName: 'MJ: Lists',\n ExtraFilter: `ID IN (${listIdFilter}) AND EntityID = '${entityId}'`,\n ResultType: 'entity_object'\n });\n\n return listsResult.Success ? (listsResult.Results || []) : [];\n }\n\n /**\n * Get item count for a list\n */\n async getListItemCount(listId: string): Promise<number> {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const result = await rv.RunView({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID = '${listId}'`,\n ResultType: 'count_only'\n });\n\n return result.Success ? result.TotalRowCount : 0;\n }\n\n /**\n * Build view models for lists with membership information\n */\n async buildListViewModels(\n lists: MJListEntity[],\n recordIds: string[],\n membership: Map<string, string[]>\n ): Promise<ListItemViewModel[]> {\n const viewModels: ListItemViewModel[] = [];\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Get item counts for all lists in one batched round trip of count_only\n // queries — each an index-seek COUNT server-side. Never download the\n // membership rows just to count them.\n const countMap = new Map<string, number>();\n if (lists.length > 0) {\n const countResults = await rv.RunViews(lists.map(list => ({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID = '${list.ID}'`,\n ResultType: 'count_only' as const\n })));\n countResults.forEach((res, idx) => {\n countMap.set(lists[idx].ID, res.Success ? res.TotalRowCount : 0);\n });\n }\n\n for (const list of lists) {\n const memberRecordIds = membership.get(list.ID) || [];\n const membershipCount = memberRecordIds.length;\n const totalSelected = recordIds.length;\n\n viewModels.push({\n list,\n itemCount: countMap.get(list.ID) || 0,\n membershipCount,\n totalSelectedRecords: totalSelected,\n isFullMember: membershipCount === totalSelected && totalSelected > 0,\n isPartialMember: membershipCount > 0 && membershipCount < totalSelected,\n isNotMember: membershipCount === 0,\n lastUpdated: list.Get('__mj_UpdatedAt') as Date || new Date(),\n category: undefined, // Can be populated separately if needed\n isSelectedForAdd: false,\n isSelectedForRemove: false\n });\n }\n\n return viewModels;\n }\n\n /**\n * Add records to one or more lists\n */\n async addRecordsToLists(\n listIds: string[],\n recordIds: string[],\n skipDuplicates: boolean = true\n ): Promise<BatchOperationResult> {\n const result: BatchOperationResult = {\n success: 0,\n failed: 0,\n skipped: 0,\n errors: []\n };\n\n const md = this.Provider;\n\n // Get existing membership to skip duplicates\n let existingMembership = new Map<string, Set<string>>();\n if (skipDuplicates) {\n const rv = RunView.FromMetadataProvider(this.Provider);\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n\n const existing = await rv.RunView<{ ListID: string; RecordID: string }>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID IN (${listIdFilter}) AND RecordID IN (${recordIdFilter})`,\n Fields: ['ListID', 'RecordID'],\n ResultType: 'simple'\n }, md.CurrentUser);\n\n if (existing.Success && existing.Results) {\n for (const detail of existing.Results) {\n const recordSet = existingMembership.get(detail.ListID) || new Set();\n recordSet.add(detail.RecordID);\n existingMembership.set(detail.ListID, recordSet);\n }\n }\n }\n\n // Build list of records to add (excluding duplicates)\n const recordsToAdd: Array<{listId: string, recordId: string}> = [];\n for (const listId of listIds) {\n const existingRecords = existingMembership.get(listId) || new Set();\n for (const recordId of recordIds) {\n if (skipDuplicates && existingRecords.has(recordId)) {\n result.skipped++;\n } else {\n recordsToAdd.push({ listId, recordId });\n }\n }\n }\n\n if (recordsToAdd.length === 0) {\n return result;\n }\n\n // Use transaction group for bulk insert\n const tg = await md.CreateTransactionGroup();\n\n for (const { listId, recordId } of recordsToAdd) {\n try {\n const listDetail = await md.GetEntityObject<MJListDetailEntity>('MJ: List Details', md.CurrentUser);\n listDetail.ListID = listId;\n listDetail.RecordID = recordId;\n listDetail.TransactionGroup = tg;\n const saveResult = await listDetail.Save();\n if (!saveResult) {\n console.error(`[ListManagementService] Failed to queue record ${recordId} for list ${listId}:`, listDetail.LatestResult?.Message);\n result.errors.push(`Failed to add record ${recordId} to list ${listId}: ${listDetail.LatestResult?.Message || 'Unknown error'}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`[ListManagementService] Exception adding record:`, error);\n result.errors.push(`Error adding record ${recordId} to list ${listId}: ${errorMessage}`);\n }\n }\n\n // Submit the transaction\n const success = await tg.Submit();\n\n if (success) {\n result.success = recordsToAdd.length - result.errors.length;\n result.failed = result.errors.length;\n } else {\n result.failed = recordsToAdd.length;\n result.success = 0;\n result.errors.push('Transaction failed to submit');\n }\n\n // Invalidate membership cache\n this.membershipCache.clear();\n\n return result;\n }\n\n /**\n * Remove records from one or more lists\n */\n async removeRecordsFromLists(\n listIds: string[],\n recordIds: string[]\n ): Promise<BatchOperationResult> {\n const result: BatchOperationResult = {\n success: 0,\n failed: 0,\n skipped: 0,\n errors: []\n };\n\n const md = this.Provider;\n const rv = RunView.FromMetadataProvider(this.Provider);\n\n // Find existing list details to delete\n const listIdFilter = listIds.map(id => `'${id}'`).join(',');\n const recordIdFilter = recordIds.map(id => `'${id}'`).join(',');\n\n const existingResult = await rv.RunView<MJListDetailEntity>({\n EntityName: 'MJ: List Details',\n ExtraFilter: `ListID IN (${listIdFilter}) AND RecordID IN (${recordIdFilter})`,\n ResultType: 'entity_object'\n });\n\n if (!existingResult.Success) {\n result.errors.push('Failed to query existing list details');\n return result;\n }\n\n const toDelete = existingResult.Results || [];\n if (toDelete.length === 0) {\n return result;\n }\n\n // Queue all deletes in one TransactionGroup — a single round trip\n // instead of one per removed membership row. Deliberately atomic (unlike\n // the server-side bulk paths, which trade atomicity for per-record error\n // isolation): if Submit() fails, the transaction rolled back and no rows\n // were removed.\n const tg = await md.CreateTransactionGroup();\n let queued = 0;\n for (const detail of toDelete) {\n try {\n detail.TransactionGroup = tg;\n // With a TransactionGroup set, Delete() returns true once enqueued;\n // false means a pre-enqueue failure (validation/permission) and the\n // row never joined the transaction.\n if (await detail.Delete()) {\n queued++;\n } else {\n result.failed++;\n result.errors.push(`Failed to queue removal of record ${detail.RecordID} from list ${detail.ListID}: ${detail.LatestResult?.CompleteMessage ?? 'unknown error'}`);\n }\n } catch (error) {\n result.failed++;\n const errorMessage = error instanceof Error ? error.message : String(error);\n result.errors.push(`Error removing record: ${errorMessage}`);\n }\n }\n\n const submitted = queued === 0 || await tg.Submit();\n if (submitted) {\n result.success = queued;\n } else {\n result.failed += queued;\n result.errors.push('Transaction failed to submit');\n }\n\n // Invalidate caches\n this.membershipCache.clear();\n\n return result;\n }\n\n /**\n * Create a new list\n */\n async createList(config: CreateListConfig): Promise<MJListEntity | null> {\n const md = this.Provider;\n\n try {\n const list = await md.GetEntityObject<MJListEntity>('MJ: Lists', md.CurrentUser);\n list.NewRecord();\n list.Name = config.name;\n list.Description = config.description || '';\n list.EntityID = config.entityId;\n list.UserID = md.CurrentUser.ID;\n\n if (config.categoryId) {\n list.CategoryID = config.categoryId;\n }\n\n const saveResult = await list.Save();\n if (saveResult) {\n // Invalidate list cache\n this.invalidateListCache(config.entityId);\n return list;\n }\n\n return null;\n } catch (error) {\n console.error('Error creating list:', error);\n return null;\n }\n }\n\n /**\n * Check if a cache entry is still valid\n */\n private isCacheValid<T>(entry: CacheEntry<T>): boolean {\n const now = new Date().getTime();\n const entryTime = entry.timestamp.getTime();\n return (now - entryTime) < this.CACHE_TTL_MS;\n }\n\n /**\n * Invalidate cache for a specific entity or all caches\n */\n invalidateCache(entityId?: string): void {\n if (entityId) {\n this.invalidateListCache(entityId);\n } else {\n this.listCache.clear();\n this.categoryCache = null;\n this.membershipCache.clear();\n }\n }\n\n /**\n * Invalidate list cache for a specific entity\n */\n private invalidateListCache(entityId: string): void {\n // Remove all cache entries that start with this entityId\n for (const key of this.listCache.keys()) {\n if (key.startsWith(entityId)) {\n this.listCache.delete(key);\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for choosing which field to display (and search on) when
|
|
3
|
+
* showing an entity's records in list-membership UIs — the Add Records
|
|
4
|
+
* dialogs and the List form's Items grid.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order:
|
|
7
|
+
* 1. The entity's NameField, when one is defined (display the value alone).
|
|
8
|
+
* 2. Otherwise the first field that is not a primary key, not a foreign
|
|
9
|
+
* key, and not an MJ system column (`__mj_*`) — displayed as
|
|
10
|
+
* "<ID> — <value>" so the record stays identifiable.
|
|
11
|
+
* 3. Otherwise the first non-primary-key field, whatever it is.
|
|
12
|
+
* 4. Entities with only primary-key fields return null — callers display
|
|
13
|
+
* the record ID alone.
|
|
14
|
+
*/
|
|
15
|
+
import { EntityFieldInfo, EntityInfo } from '@memberjunction/core';
|
|
16
|
+
/** The display-field choice for an entity's records in list UIs. */
|
|
17
|
+
export interface RecordDisplayFieldInfo {
|
|
18
|
+
/** The field whose value should be shown; null when only the ID is displayable. */
|
|
19
|
+
Field: EntityFieldInfo | null;
|
|
20
|
+
/** True when Field is the entity's real NameField (display value alone, no ID prefix). */
|
|
21
|
+
IsNameField: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Picks the field to display for an entity's records per the resolution
|
|
25
|
+
* order documented at the top of this file.
|
|
26
|
+
*/
|
|
27
|
+
export declare function GetRecordDisplayField(entityInfo: EntityInfo): RecordDisplayFieldInfo;
|
|
28
|
+
/** True when the field's SQL type supports a LIKE-based contains search. */
|
|
29
|
+
export declare function IsTextSearchableField(field: EntityFieldInfo | null): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Formats a record's display label from its ID and the chosen display
|
|
32
|
+
* field's value: NameField → the value alone; fallback field →
|
|
33
|
+
* "<id> — <value>"; no field / empty value → the id.
|
|
34
|
+
*/
|
|
35
|
+
export declare function FormatRecordDisplayValue(recordId: string, fieldValue: unknown, displayField: RecordDisplayFieldInfo): string;
|
|
36
|
+
//# sourceMappingURL=record-display-field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-display-field.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/record-display-field.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEnE,oEAAoE;AACpE,MAAM,WAAW,sBAAsB;IACnC,mFAAmF;IACnF,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,0FAA0F;IAC1F,WAAW,EAAE,OAAO,CAAC;CACxB;AAKD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,UAAU,GAAG,sBAAsB,CAcpF;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,OAAO,CAI5E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,EACnB,YAAY,EAAE,sBAAsB,GACrC,MAAM,CAMR"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** SQL types safe to use in a `LIKE '%…%'` search filter. */
|
|
2
|
+
const TEXT_SEARCHABLE_TYPES = new Set(['nvarchar', 'varchar', 'nchar', 'char', 'text', 'ntext']);
|
|
3
|
+
/**
|
|
4
|
+
* Picks the field to display for an entity's records per the resolution
|
|
5
|
+
* order documented at the top of this file.
|
|
6
|
+
*/
|
|
7
|
+
export function GetRecordDisplayField(entityInfo) {
|
|
8
|
+
if (entityInfo.NameField) {
|
|
9
|
+
return { Field: entityInfo.NameField, IsNameField: true };
|
|
10
|
+
}
|
|
11
|
+
const preferred = entityInfo.Fields.find((f) => !f.IsPrimaryKey && !f.RelatedEntityID && !f.Name.startsWith('__mj_'));
|
|
12
|
+
if (preferred) {
|
|
13
|
+
return { Field: preferred, IsNameField: false };
|
|
14
|
+
}
|
|
15
|
+
const anyNonPk = entityInfo.Fields.find((f) => !f.IsPrimaryKey) ?? null;
|
|
16
|
+
return { Field: anyNonPk, IsNameField: false };
|
|
17
|
+
}
|
|
18
|
+
/** True when the field's SQL type supports a LIKE-based contains search. */
|
|
19
|
+
export function IsTextSearchableField(field) {
|
|
20
|
+
if (!field)
|
|
21
|
+
return false;
|
|
22
|
+
const normalized = (field.Type || '').replace(/\s*\([^)]*\)\s*$/, '').trim().toLowerCase();
|
|
23
|
+
return TEXT_SEARCHABLE_TYPES.has(normalized);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Formats a record's display label from its ID and the chosen display
|
|
27
|
+
* field's value: NameField → the value alone; fallback field →
|
|
28
|
+
* "<id> — <value>"; no field / empty value → the id.
|
|
29
|
+
*/
|
|
30
|
+
export function FormatRecordDisplayValue(recordId, fieldValue, displayField) {
|
|
31
|
+
const value = fieldValue == null ? '' : String(fieldValue).trim();
|
|
32
|
+
if (displayField.IsNameField) {
|
|
33
|
+
return value || recordId;
|
|
34
|
+
}
|
|
35
|
+
return value ? `${recordId} — ${value}` : recordId;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=record-display-field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-display-field.js","sourceRoot":"","sources":["../../../src/lib/utils/record-display-field.ts"],"names":[],"mappings":"AAwBA,6DAA6D;AAC7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEjG;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAsB;IACxD,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAC9E,CAAC;IACF,IAAI,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC;IACxE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,qBAAqB,CAAC,KAA6B;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3F,OAAO,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACpC,QAAgB,EAChB,UAAmB,EACnB,YAAoC;IAEpC,MAAM,KAAK,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IAClE,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;QAC3B,OAAO,KAAK,IAAI,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvD,CAAC","sourcesContent":["/**\n * Shared helper for choosing which field to display (and search on) when\n * showing an entity's records in list-membership UIs — the Add Records\n * dialogs and the List form's Items grid.\n *\n * Resolution order:\n * 1. The entity's NameField, when one is defined (display the value alone).\n * 2. Otherwise the first field that is not a primary key, not a foreign\n * key, and not an MJ system column (`__mj_*`) — displayed as\n * \"<ID> — <value>\" so the record stays identifiable.\n * 3. Otherwise the first non-primary-key field, whatever it is.\n * 4. Entities with only primary-key fields return null — callers display\n * the record ID alone.\n */\nimport { EntityFieldInfo, EntityInfo } from '@memberjunction/core';\n\n/** The display-field choice for an entity's records in list UIs. */\nexport interface RecordDisplayFieldInfo {\n /** The field whose value should be shown; null when only the ID is displayable. */\n Field: EntityFieldInfo | null;\n /** True when Field is the entity's real NameField (display value alone, no ID prefix). */\n IsNameField: boolean;\n}\n\n/** SQL types safe to use in a `LIKE '%…%'` search filter. */\nconst TEXT_SEARCHABLE_TYPES = new Set(['nvarchar', 'varchar', 'nchar', 'char', 'text', 'ntext']);\n\n/**\n * Picks the field to display for an entity's records per the resolution\n * order documented at the top of this file.\n */\nexport function GetRecordDisplayField(entityInfo: EntityInfo): RecordDisplayFieldInfo {\n if (entityInfo.NameField) {\n return { Field: entityInfo.NameField, IsNameField: true };\n }\n\n const preferred = entityInfo.Fields.find(\n (f) => !f.IsPrimaryKey && !f.RelatedEntityID && !f.Name.startsWith('__mj_'),\n );\n if (preferred) {\n return { Field: preferred, IsNameField: false };\n }\n\n const anyNonPk = entityInfo.Fields.find((f) => !f.IsPrimaryKey) ?? null;\n return { Field: anyNonPk, IsNameField: false };\n}\n\n/** True when the field's SQL type supports a LIKE-based contains search. */\nexport function IsTextSearchableField(field: EntityFieldInfo | null): boolean {\n if (!field) return false;\n const normalized = (field.Type || '').replace(/\\s*\\([^)]*\\)\\s*$/, '').trim().toLowerCase();\n return TEXT_SEARCHABLE_TYPES.has(normalized);\n}\n\n/**\n * Formats a record's display label from its ID and the chosen display\n * field's value: NameField → the value alone; fallback field →\n * \"<id> — <value>\"; no field / empty value → the id.\n */\nexport function FormatRecordDisplayValue(\n recordId: string,\n fieldValue: unknown,\n displayField: RecordDisplayFieldInfo,\n): string {\n const value = fieldValue == null ? '' : String(fieldValue).trim();\n if (displayField.IsNameField) {\n return value || recordId;\n }\n return value ? `${recordId} — ${value}` : recordId;\n}\n"]}
|
package/dist/public-api.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export * from './lib/services/list-management.service';
|
|
|
14
14
|
export * from './lib/services/list-sharing.service';
|
|
15
15
|
export * from './lib/models/list-management.models';
|
|
16
16
|
export * from './lib/models/list-sharing.models';
|
|
17
|
+
export * from './lib/utils/record-display-field';
|
|
17
18
|
//# sourceMappingURL=public-api.d.ts.map
|
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,cAAc,CAAC;AAG7B,cAAc,0EAA0E,CAAC;AACzF,cAAc,4EAA4E,CAAC;AAC3F,cAAc,0DAA0D,CAAC;AACzE,cAAc,kEAAkE,CAAC;AACjF,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0EAA0E,CAAC;AACzF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kDAAkD,CAAC;AACjE,cAAc,0DAA0D,CAAC;AACzE,cAAc,gDAAgD,CAAC;AAG/D,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AAGpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAKA,cAAc,cAAc,CAAC;AAG7B,cAAc,0EAA0E,CAAC;AACzF,cAAc,4EAA4E,CAAC;AAC3F,cAAc,0DAA0D,CAAC;AACzE,cAAc,kEAAkE,CAAC;AACjF,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0EAA0E,CAAC;AACzF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kDAAkD,CAAC;AACjE,cAAc,0DAA0D,CAAC;AACzE,cAAc,gDAAgD,CAAC;AAG/D,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AAGpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,kCAAkC,CAAC;AAGjD,cAAc,kCAAkC,CAAC"}
|
package/dist/public-api.js
CHANGED
|
@@ -21,4 +21,6 @@ export * from './lib/services/list-sharing.service';
|
|
|
21
21
|
// Models
|
|
22
22
|
export * from './lib/models/list-management.models';
|
|
23
23
|
export * from './lib/models/list-sharing.models';
|
|
24
|
+
// Utils
|
|
25
|
+
export * from './lib/utils/record-display-field';
|
|
24
26
|
//# sourceMappingURL=public-api.js.map
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,cAAc,CAAC;AAE7B,aAAa;AACb,cAAc,0EAA0E,CAAC;AACzF,cAAc,4EAA4E,CAAC;AAC3F,cAAc,0DAA0D,CAAC;AACzE,cAAc,kEAAkE,CAAC;AACjF,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0EAA0E,CAAC;AACzF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kDAAkD,CAAC;AACjE,cAAc,0DAA0D,CAAC;AACzE,cAAc,gDAAgD,CAAC;AAE/D,WAAW;AACX,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AAEpD,SAAS;AACT,cAAc,qCAAqC,CAAC;AACpD,cAAc,kCAAkC,CAAC","sourcesContent":["/*\n * Public API Surface for @memberjunction/ng-list-management\n */\n\n// Module\nexport * from './lib/module';\n\n// Components\nexport * from './lib/components/audience-source-picker/audience-source-picker.component';\nexport * from './lib/components/audience-source-summary/audience-source-summary.component';\nexport * from './lib/components/list-audit-log/list-audit-log.component';\nexport * from './lib/components/list-delta-confirm/list-delta-confirm.component';\nexport * from './lib/components/list-invitations/list-invitations.component';\nexport * from './lib/components/list-management-dialog/list-management-dialog.component';\nexport * from './lib/components/list-share-dialog/list-share-dialog.component';\nexport * from './lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component';\nexport * from './lib/components/list-stats/list-stats.component';\nexport * from './lib/components/shared-with-me/shared-with-me.component';\nexport * from './lib/components/tag-chips/tag-chips.component';\n\n// Services\nexport * from './lib/services/list-management.service';\nexport * from './lib/services/list-sharing.service';\n\n// Models\nexport * from './lib/models/list-management.models';\nexport * from './lib/models/list-sharing.models';\n"]}
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,SAAS;AACT,cAAc,cAAc,CAAC;AAE7B,aAAa;AACb,cAAc,0EAA0E,CAAC;AACzF,cAAc,4EAA4E,CAAC;AAC3F,cAAc,0DAA0D,CAAC;AACzE,cAAc,kEAAkE,CAAC;AACjF,cAAc,8DAA8D,CAAC;AAC7E,cAAc,0EAA0E,CAAC;AACzF,cAAc,gEAAgE,CAAC;AAC/E,cAAc,8EAA8E,CAAC;AAC7F,cAAc,kDAAkD,CAAC;AACjE,cAAc,0DAA0D,CAAC;AACzE,cAAc,gDAAgD,CAAC;AAE/D,WAAW;AACX,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AAEpD,SAAS;AACT,cAAc,qCAAqC,CAAC;AACpD,cAAc,kCAAkC,CAAC;AAEjD,QAAQ;AACR,cAAc,kCAAkC,CAAC","sourcesContent":["/*\n * Public API Surface for @memberjunction/ng-list-management\n */\n\n// Module\nexport * from './lib/module';\n\n// Components\nexport * from './lib/components/audience-source-picker/audience-source-picker.component';\nexport * from './lib/components/audience-source-summary/audience-source-summary.component';\nexport * from './lib/components/list-audit-log/list-audit-log.component';\nexport * from './lib/components/list-delta-confirm/list-delta-confirm.component';\nexport * from './lib/components/list-invitations/list-invitations.component';\nexport * from './lib/components/list-management-dialog/list-management-dialog.component';\nexport * from './lib/components/list-share-dialog/list-share-dialog.component';\nexport * from './lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component';\nexport * from './lib/components/list-stats/list-stats.component';\nexport * from './lib/components/shared-with-me/shared-with-me.component';\nexport * from './lib/components/tag-chips/tag-chips.component';\n\n// Services\nexport * from './lib/services/list-management.service';\nexport * from './lib/services/list-sharing.service';\n\n// Models\nexport * from './lib/models/list-management.models';\nexport * from './lib/models/list-sharing.models';\n\n// Utils\nexport * from './lib/utils/record-display-field';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-list-management",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.48.0",
|
|
4
4
|
"description": "MemberJunction: Angular Components for managing entity list membership with beautiful, responsive UI",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@angular/compiler": "21.1.3",
|
|
25
25
|
"@angular/compiler-cli": "21.1.3",
|
|
26
|
-
"@memberjunction/ng-test-utils": "5.
|
|
26
|
+
"@memberjunction/ng-test-utils": "5.48.0",
|
|
27
27
|
"vitest": "^4.0.18"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -34,16 +34,16 @@
|
|
|
34
34
|
"rxjs": "^7.8.2"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@memberjunction/core": "5.
|
|
38
|
-
"@memberjunction/core-entities": "5.
|
|
39
|
-
"@memberjunction/global": "5.
|
|
40
|
-
"@memberjunction/graphql-dataprovider": "5.
|
|
41
|
-
"@memberjunction/lists-base": "5.
|
|
42
|
-
"@memberjunction/ng-base-types": "5.
|
|
43
|
-
"@memberjunction/ng-container-directives": "5.
|
|
44
|
-
"@memberjunction/ng-shared": "5.
|
|
45
|
-
"@memberjunction/ng-shared-generic": "5.
|
|
46
|
-
"@memberjunction/ng-ui-components": "5.
|
|
37
|
+
"@memberjunction/core": "5.48.0",
|
|
38
|
+
"@memberjunction/core-entities": "5.48.0",
|
|
39
|
+
"@memberjunction/global": "5.48.0",
|
|
40
|
+
"@memberjunction/graphql-dataprovider": "5.48.0",
|
|
41
|
+
"@memberjunction/lists-base": "5.48.0",
|
|
42
|
+
"@memberjunction/ng-base-types": "5.48.0",
|
|
43
|
+
"@memberjunction/ng-container-directives": "5.48.0",
|
|
44
|
+
"@memberjunction/ng-shared": "5.48.0",
|
|
45
|
+
"@memberjunction/ng-shared-generic": "5.48.0",
|
|
46
|
+
"@memberjunction/ng-ui-components": "5.48.0",
|
|
47
47
|
"tslib": "^2.8.1"
|
|
48
48
|
},
|
|
49
49
|
"sideEffects": false,
|