@memberjunction/ng-list-management 6.1.4 → 6.2.0-edge.1
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/audience-source-picker/audience-source-picker.component.d.ts +74 -14
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.d.ts.map +1 -1
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.js +177 -57
- package/dist/lib/components/audience-source-picker/audience-source-picker.component.js.map +1 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.d.ts +7 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.d.ts.map +1 -1
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.js +17 -5
- package/dist/lib/components/audience-source-summary/audience-source-summary.component.js.map +1 -1
- package/dist/lib/components/list-audit-log/list-audit-log.component.d.ts +30 -4
- package/dist/lib/components/list-audit-log/list-audit-log.component.d.ts.map +1 -1
- package/dist/lib/components/list-audit-log/list-audit-log.component.js +54 -14
- package/dist/lib/components/list-audit-log/list-audit-log.component.js.map +1 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.d.ts +17 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.d.ts.map +1 -1
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.js +45 -13
- package/dist/lib/components/list-delta-confirm/list-delta-confirm.component.js.map +1 -1
- package/dist/lib/components/list-invitations/list-invitations.component.d.ts +48 -8
- package/dist/lib/components/list-invitations/list-invitations.component.d.ts.map +1 -1
- package/dist/lib/components/list-invitations/list-invitations.component.js +108 -28
- package/dist/lib/components/list-invitations/list-invitations.component.js.map +1 -1
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.d.ts +123 -15
- 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 +312 -100
- package/dist/lib/components/list-management-dialog/list-management-dialog.component.js.map +1 -1
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.d.ts +128 -14
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.js +288 -92
- package/dist/lib/components/list-share-dialog/list-share-dialog.component.js.map +1 -1
- package/dist/lib/components/list-stats/list-stats.component.d.ts +32 -6
- package/dist/lib/components/list-stats/list-stats.component.d.ts.map +1 -1
- package/dist/lib/components/list-stats/list-stats.component.js +67 -15
- package/dist/lib/components/list-stats/list-stats.component.js.map +1 -1
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.d.ts +44 -8
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.js +100 -28
- package/dist/lib/components/save-view-as-list-dialog/save-view-as-list-dialog.component.js.map +1 -1
- package/dist/lib/components/shared-with-me/shared-with-me.component.d.ts +18 -2
- package/dist/lib/components/shared-with-me/shared-with-me.component.d.ts.map +1 -1
- package/dist/lib/components/shared-with-me/shared-with-me.component.js +41 -9
- package/dist/lib/components/shared-with-me/shared-with-me.component.js.map +1 -1
- package/dist/lib/components/tag-chips/tag-chips.component.d.ts +30 -6
- package/dist/lib/components/tag-chips/tag-chips.component.d.ts.map +1 -1
- package/dist/lib/components/tag-chips/tag-chips.component.js +76 -28
- package/dist/lib/components/tag-chips/tag-chips.component.js.map +1 -1
- package/dist/lib/services/list-management.service.d.ts +25 -1
- package/dist/lib/services/list-management.service.d.ts.map +1 -1
- package/dist/lib/services/list-management.service.js +59 -11
- package/dist/lib/services/list-management.service.js.map +1 -1
- package/dist/lib/services/list-sharing.service.d.ts +42 -1
- package/dist/lib/services/list-sharing.service.d.ts.map +1 -1
- package/dist/lib/services/list-sharing.service.js +85 -17
- package/dist/lib/services/list-sharing.service.js.map +1 -1
- package/package.json +11 -11
|
@@ -124,13 +124,53 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
124
124
|
/** Emitted after add/remove so parents can refresh dependent data. */
|
|
125
125
|
TagsChanged = new EventEmitter();
|
|
126
126
|
tags = [];
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
Loading = false;
|
|
128
|
+
/** @deprecated Use {@link Loading}. */
|
|
129
|
+
get loading() {
|
|
130
|
+
return this.Loading;
|
|
131
|
+
}
|
|
132
|
+
/** @deprecated Use {@link Loading}. */
|
|
133
|
+
set loading(value) {
|
|
134
|
+
this.Loading = value;
|
|
135
|
+
}
|
|
136
|
+
AddInput = '';
|
|
137
|
+
/** @deprecated Use {@link AddInput}. */
|
|
138
|
+
get addInput() {
|
|
139
|
+
return this.AddInput;
|
|
140
|
+
}
|
|
141
|
+
/** @deprecated Use {@link AddInput}. */
|
|
142
|
+
set addInput(value) {
|
|
143
|
+
this.AddInput = value;
|
|
144
|
+
}
|
|
145
|
+
Suggestions = [];
|
|
146
|
+
/** @deprecated Use {@link Suggestions}. */
|
|
147
|
+
get suggestions() {
|
|
148
|
+
return this.Suggestions;
|
|
149
|
+
}
|
|
150
|
+
/** @deprecated Use {@link Suggestions}. */
|
|
151
|
+
set suggestions(value) {
|
|
152
|
+
this.Suggestions = value;
|
|
153
|
+
}
|
|
154
|
+
ShowSuggestions = false;
|
|
155
|
+
/** @deprecated Use {@link ShowSuggestions}. */
|
|
156
|
+
get showSuggestions() {
|
|
157
|
+
return this.ShowSuggestions;
|
|
158
|
+
}
|
|
159
|
+
/** @deprecated Use {@link ShowSuggestions}. */
|
|
160
|
+
set showSuggestions(value) {
|
|
161
|
+
this.ShowSuggestions = value;
|
|
162
|
+
}
|
|
131
163
|
/** True when the trimmed input doesn't exactly match any existing tag —
|
|
132
164
|
* drives the "Create '<term>'" affordance at the top of the dropdown. */
|
|
133
|
-
|
|
165
|
+
CanCreateNew = false;
|
|
166
|
+
/** @deprecated Use {@link CanCreateNew}. */
|
|
167
|
+
get canCreateNew() {
|
|
168
|
+
return this.CanCreateNew;
|
|
169
|
+
}
|
|
170
|
+
/** @deprecated Use {@link CanCreateNew}. */
|
|
171
|
+
set canCreateNew(value) {
|
|
172
|
+
this.CanCreateNew = value;
|
|
173
|
+
}
|
|
134
174
|
initialized = false;
|
|
135
175
|
entityID = null;
|
|
136
176
|
async ngOnInit() {
|
|
@@ -138,12 +178,20 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
138
178
|
if (this._entityName && this._recordId)
|
|
139
179
|
await this.loadTags();
|
|
140
180
|
}
|
|
141
|
-
get
|
|
181
|
+
get DisplayedTags() {
|
|
142
182
|
return this.tags.slice(0, this.MaxDisplay);
|
|
143
183
|
}
|
|
144
|
-
|
|
184
|
+
/** @deprecated Use {@link DisplayedTags}. */
|
|
185
|
+
get displayedTags() {
|
|
186
|
+
return this.DisplayedTags;
|
|
187
|
+
}
|
|
188
|
+
get ExtraTagCount() {
|
|
145
189
|
return Math.max(0, this.tags.length - this.MaxDisplay);
|
|
146
190
|
}
|
|
191
|
+
/** @deprecated Use {@link ExtraTagCount}. */
|
|
192
|
+
get extraTagCount() {
|
|
193
|
+
return this.ExtraTagCount;
|
|
194
|
+
}
|
|
147
195
|
OnTagClick(tag) {
|
|
148
196
|
this.TagClicked.emit({ TagID: tag.TagID, Name: tag.Name });
|
|
149
197
|
}
|
|
@@ -169,12 +217,12 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
169
217
|
}
|
|
170
218
|
}
|
|
171
219
|
async OnAddInputChange(value) {
|
|
172
|
-
this.
|
|
220
|
+
this.AddInput = value;
|
|
173
221
|
const term = value.trim();
|
|
174
222
|
if (term.length < 1) {
|
|
175
|
-
this.
|
|
176
|
-
this.
|
|
177
|
-
this.
|
|
223
|
+
this.Suggestions = [];
|
|
224
|
+
this.CanCreateNew = false;
|
|
225
|
+
this.ShowSuggestions = false;
|
|
178
226
|
this.cdr.markForCheck();
|
|
179
227
|
return;
|
|
180
228
|
}
|
|
@@ -189,14 +237,14 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
189
237
|
ResultType: 'entity_object',
|
|
190
238
|
});
|
|
191
239
|
const alreadyApplied = new Set(this.tags.map((t) => t.TagID));
|
|
192
|
-
this.
|
|
240
|
+
this.Suggestions = (result.Results ?? []).filter((t) => !alreadyApplied.has(t.ID));
|
|
193
241
|
// Offer "Create '<term>'" when the typed text doesn't exactly
|
|
194
242
|
// match any existing tag (case-insensitive). Without this, typing
|
|
195
243
|
// a brand-new tag name and hitting Enter does nothing — there's
|
|
196
244
|
// no suggestion to click.
|
|
197
245
|
const lowerTerm = term.toLowerCase();
|
|
198
|
-
this.
|
|
199
|
-
this.
|
|
246
|
+
this.CanCreateNew = !this.Suggestions.some((s) => s.Name.toLowerCase() === lowerTerm);
|
|
247
|
+
this.ShowSuggestions = true;
|
|
200
248
|
}
|
|
201
249
|
catch (e) {
|
|
202
250
|
LogError(`tag-chips: suggestion lookup failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -213,17 +261,17 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
213
261
|
*/
|
|
214
262
|
async OnAddInputSubmit(event) {
|
|
215
263
|
event?.preventDefault();
|
|
216
|
-
const term = this.
|
|
264
|
+
const term = this.AddInput.trim();
|
|
217
265
|
if (term.length === 0)
|
|
218
266
|
return;
|
|
219
267
|
// Existing tag in suggestions takes priority — Enter selects the
|
|
220
268
|
// first match (matching most autocomplete UIs).
|
|
221
|
-
if (this.
|
|
222
|
-
await this.OnAddTag(this.
|
|
269
|
+
if (this.Suggestions.length > 0) {
|
|
270
|
+
await this.OnAddTag(this.Suggestions[0]);
|
|
223
271
|
return;
|
|
224
272
|
}
|
|
225
|
-
if (this.
|
|
226
|
-
await this.
|
|
273
|
+
if (this.CanCreateNew) {
|
|
274
|
+
await this.createAndAddTag(term);
|
|
227
275
|
}
|
|
228
276
|
}
|
|
229
277
|
async OnAddTag(tag) {
|
|
@@ -234,12 +282,12 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
234
282
|
/** Click handler for the "Create '<term>'" affordance. Creates the
|
|
235
283
|
* `MJ: Tags` row then attaches it via the standard apply path. */
|
|
236
284
|
async OnCreateNew() {
|
|
237
|
-
const term = this.
|
|
285
|
+
const term = this.AddInput.trim();
|
|
238
286
|
if (term.length === 0)
|
|
239
287
|
return;
|
|
240
|
-
await this.
|
|
288
|
+
await this.createAndAddTag(term);
|
|
241
289
|
}
|
|
242
|
-
async
|
|
290
|
+
async createAndAddTag(name) {
|
|
243
291
|
if (!this._entityName || !this._recordId)
|
|
244
292
|
return;
|
|
245
293
|
try {
|
|
@@ -281,10 +329,10 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
281
329
|
return;
|
|
282
330
|
}
|
|
283
331
|
this.tags = [...this.tags, { TaggedItemID: entity.ID, TagID: tagId, Name: tagName }];
|
|
284
|
-
this.
|
|
285
|
-
this.
|
|
286
|
-
this.
|
|
287
|
-
this.
|
|
332
|
+
this.AddInput = '';
|
|
333
|
+
this.Suggestions = [];
|
|
334
|
+
this.CanCreateNew = false;
|
|
335
|
+
this.ShowSuggestions = false;
|
|
288
336
|
this.TagsChanged.emit();
|
|
289
337
|
this.cdr.markForCheck();
|
|
290
338
|
}
|
|
@@ -302,7 +350,7 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
302
350
|
this.tags = [];
|
|
303
351
|
return;
|
|
304
352
|
}
|
|
305
|
-
this.
|
|
353
|
+
this.Loading = true;
|
|
306
354
|
this.cdr.markForCheck();
|
|
307
355
|
try {
|
|
308
356
|
const md = this.metadata();
|
|
@@ -348,7 +396,7 @@ export class TagChipsComponent extends BaseAngularComponent {
|
|
|
348
396
|
.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
349
397
|
}
|
|
350
398
|
finally {
|
|
351
|
-
this.
|
|
399
|
+
this.Loading = false;
|
|
352
400
|
this.cdr.markForCheck();
|
|
353
401
|
}
|
|
354
402
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-chips.component.js","sourceRoot":"","sources":["../../../../src/lib/components/tag-chips/tag-chips.component.ts","../../../../src/lib/components/tag-chips/tag-chips.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { LogError, Metadata, RunView } from '@memberjunction/core';\nimport type { MJTagEntity, MJTaggedItemEntity } from '@memberjunction/core-entities';\n\n/**\n * Compact tag chips for a single record (mockup 22). Loads tags by\n * querying `MJ: Tagged Items` filtered to `(EntityID, RecordID)`, then\n * resolves names from `MJ: Tags` in a single batch. Render-only by\n * default; pass `Editable=true` to surface an inline add field and\n * per-chip remove buttons.\n *\n * Intentionally lightweight — not a tag manager. For richer tag tooling\n * (cloud view, related records, etc.) use `mj-record-tags` from\n * `@memberjunction/ng-record-tags`.\n */\n\ninterface DisplayTag {\n /** TaggedItem row ID — used for removal. */\n TaggedItemID: string;\n /** Tag.ID — useful for downstream filtering / lookups. */\n TagID: string;\n /** Tag display name. */\n Name: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-tag-chips',\n templateUrl: './tag-chips.component.html',\n styleUrls: ['./tag-chips.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TagChipsComponent extends BaseAngularComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n /** Entity name (e.g. 'MJ: Lists'). Required. */\n @Input()\n set EntityName(value: string | null) {\n if (this._entityName !== value) {\n this._entityName = value;\n if (this.initialized && value && this._recordId) void this.loadTags();\n }\n }\n get EntityName(): string | null {\n return this._entityName;\n }\n private _entityName: string | null = null;\n\n /** Record ID (the row's primary key, serialized). Required. */\n @Input()\n set RecordID(value: string | null) {\n if (this._recordId !== value) {\n this._recordId = value;\n if (this.initialized && value && this._entityName) void this.loadTags();\n }\n }\n get RecordID(): string | null {\n return this._recordId;\n }\n private _recordId: string | null = null;\n\n /** When true, shows add input + remove buttons on chips. */\n @Input() Editable = false;\n\n /** Cap visible chips and surface \"+N more\". Defaults to 6 for cards. */\n @Input() MaxDisplay = 6;\n\n /** Emitted when a chip is clicked. Lets the parent drive filter-by-tag. */\n @Output() TagClicked = new EventEmitter<{ TagID: string; Name: string }>();\n\n /** Emitted after add/remove so parents can refresh dependent data. */\n @Output() TagsChanged = new EventEmitter<void>();\n\n public tags: DisplayTag[] = [];\n public loading = false;\n public addInput = '';\n public suggestions: MJTagEntity[] = [];\n public showSuggestions = false;\n /** True when the trimmed input doesn't exactly match any existing tag —\n * drives the \"Create '<term>'\" affordance at the top of the dropdown. */\n public canCreateNew = false;\n\n private initialized = false;\n private entityID: string | null = null;\n\n async ngOnInit(): Promise<void> {\n this.initialized = true;\n if (this._entityName && this._recordId) await this.loadTags();\n }\n\n public get displayedTags(): DisplayTag[] {\n return this.tags.slice(0, this.MaxDisplay);\n }\n\n public get extraTagCount(): number {\n return Math.max(0, this.tags.length - this.MaxDisplay);\n }\n\n public OnTagClick(tag: DisplayTag): void {\n this.TagClicked.emit({ TagID: tag.TagID, Name: tag.Name });\n }\n\n public async OnRemove(tag: DisplayTag, event: Event): Promise<void> {\n event.stopPropagation();\n if (!this.Editable) return;\n try {\n const md = this.metadata();\n const entity = await md.GetEntityObject<MJTaggedItemEntity>('MJ: Tagged Items', this.ProviderToUse.CurrentUser ?? undefined);\n const loaded = await entity.Load(tag.TaggedItemID);\n if (!loaded) return;\n const ok = await entity.Delete();\n if (ok) {\n this.tags = this.tags.filter((t) => t.TaggedItemID !== tag.TaggedItemID);\n this.TagsChanged.emit();\n this.cdr.markForCheck();\n }\n } catch (e) {\n LogError(`tag-chips: remove failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n public async OnAddInputChange(value: string): Promise<void> {\n this.addInput = value;\n const term = value.trim();\n if (term.length < 1) {\n this.suggestions = [];\n this.canCreateNew = false;\n this.showSuggestions = false;\n this.cdr.markForCheck();\n return;\n }\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const escaped = term.replace(/'/g, \"''\");\n const result = await rv.RunView<MJTagEntity>({\n EntityName: 'MJ: Tags',\n ExtraFilter: `Name LIKE '%${escaped}%'`,\n OrderBy: 'Name',\n MaxRows: 8,\n ResultType: 'entity_object',\n });\n const alreadyApplied = new Set(this.tags.map((t) => t.TagID));\n this.suggestions = (result.Results ?? []).filter((t) => !alreadyApplied.has(t.ID));\n // Offer \"Create '<term>'\" when the typed text doesn't exactly\n // match any existing tag (case-insensitive). Without this, typing\n // a brand-new tag name and hitting Enter does nothing — there's\n // no suggestion to click.\n const lowerTerm = term.toLowerCase();\n this.canCreateNew = !this.suggestions.some(\n (s) => s.Name.toLowerCase() === lowerTerm,\n );\n this.showSuggestions = true;\n } catch (e) {\n LogError(`tag-chips: suggestion lookup failed: ${e instanceof Error ? e.message : String(e)}`);\n } finally {\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Enter-key handler on the input. If suggestions are showing,\n * picks the first one (existing tag); otherwise creates a new tag\n * from the typed text and applies it. Closes the suggestion menu\n * on either path.\n */\n public async OnAddInputSubmit(event?: Event): Promise<void> {\n event?.preventDefault();\n const term = this.addInput.trim();\n if (term.length === 0) return;\n // Existing tag in suggestions takes priority — Enter selects the\n // first match (matching most autocomplete UIs).\n if (this.suggestions.length > 0) {\n await this.OnAddTag(this.suggestions[0]);\n return;\n }\n if (this.canCreateNew) {\n await this.CreateAndAddTag(term);\n }\n }\n\n public async OnAddTag(tag: MJTagEntity): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n await this.applyTagToRecord(tag.ID, tag.Name);\n }\n\n /** Click handler for the \"Create '<term>'\" affordance. Creates the\n * `MJ: Tags` row then attaches it via the standard apply path. */\n public async OnCreateNew(): Promise<void> {\n const term = this.addInput.trim();\n if (term.length === 0) return;\n await this.CreateAndAddTag(term);\n }\n\n private async CreateAndAddTag(name: string): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n try {\n const md = this.metadata();\n const tag = await md.GetEntityObject<MJTagEntity>('MJ: Tags', this.ProviderToUse.CurrentUser ?? undefined);\n tag.NewRecord();\n tag.Name = name;\n // MJ: Tags requires both Name (canonical) and DisplayName (UI).\n // Default DisplayName to the same text the user typed — they can\n // refine it later via the Tags entity editor if needed.\n tag.DisplayName = name;\n const ok = await tag.Save();\n if (!ok) {\n LogError(`tag-chips: create-tag save failed: ${tag.LatestResult?.CompleteMessage ?? 'unknown'}`);\n return;\n }\n await this.applyTagToRecord(tag.ID, tag.Name);\n } catch (e) {\n LogError(`tag-chips: create-and-add failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n private async applyTagToRecord(tagId: string, tagName: string): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n try {\n const md = this.metadata();\n const entity = await md.GetEntityObject<MJTaggedItemEntity>('MJ: Tagged Items', this.ProviderToUse.CurrentUser ?? undefined);\n entity.NewRecord();\n entity.TagID = tagId;\n entity.RecordID = this._recordId;\n const entityInfo = md.EntityByName(this._entityName);\n if (entityInfo) entity.EntityID = entityInfo.ID;\n entity.Weight = 1.0;\n const ok = await entity.Save();\n if (!ok) {\n LogError(`tag-chips: attach-tag save failed: ${entity.LatestResult?.CompleteMessage ?? 'unknown'}`);\n return;\n }\n this.tags = [...this.tags, { TaggedItemID: entity.ID, TagID: tagId, Name: tagName }];\n this.addInput = '';\n this.suggestions = [];\n this.canCreateNew = false;\n this.showSuggestions = false;\n this.TagsChanged.emit();\n this.cdr.markForCheck();\n } catch (e) {\n LogError(`tag-chips: apply failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n /**\n * Bulk-load tags + their names in two RunViews — one for the join\n * rows and one to resolve display names. Cheap; this typically returns\n * fewer than 10 rows.\n */\n private async loadTags(): Promise<void> {\n if (!this._entityName || !this._recordId) {\n this.tags = [];\n return;\n }\n this.loading = true;\n this.cdr.markForCheck();\n try {\n const md = this.metadata();\n const entityInfo = md.EntityByName(this._entityName);\n if (!entityInfo) {\n this.tags = [];\n return;\n }\n this.entityID = entityInfo.ID;\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const recordIdEscaped = this._recordId.replace(/'/g, \"''\");\n const joinResult = await rv.RunView<{ ID: string; TagID: string }>({\n EntityName: 'MJ: Tagged Items',\n ExtraFilter: `EntityID='${entityInfo.ID}' AND RecordID='${recordIdEscaped}'`,\n Fields: ['ID', 'TagID'],\n ResultType: 'simple',\n });\n if (!joinResult.Success) {\n this.tags = [];\n return;\n }\n const rows = joinResult.Results ?? [];\n if (rows.length === 0) {\n this.tags = [];\n return;\n }\n const tagIds = Array.from(new Set(rows.map((r) => String(r.TagID))));\n const tagsResult = await rv.RunView<{ ID: string; Name: string }>({\n EntityName: 'MJ: Tags',\n ExtraFilter: `ID IN (${tagIds.map((id) => `'${id}'`).join(',')})`,\n Fields: ['ID', 'Name'],\n ResultType: 'simple',\n });\n const nameById = new Map<string, string>();\n for (const t of tagsResult.Results ?? []) nameById.set(String(t.ID), String(t.Name));\n this.tags = rows\n .map((r) => ({\n TaggedItemID: String(r.ID),\n TagID: String(r.TagID),\n Name: nameById.get(String(r.TagID)) ?? '(unknown tag)',\n }))\n .sort((a, b) => a.Name.localeCompare(b.Name));\n } finally {\n this.loading = false;\n this.cdr.markForCheck();\n }\n }\n\n private metadata(): Metadata {\n // ProviderToUse always resolves (it falls back to the global default itself), so a\n // `?? new Metadata()` arm here was dead code that would have defeated an injected provider.\n return this.ProviderToUse as unknown as Metadata;\n }\n}\n","<div class=\"tag-chips\" [class.tag-chips--loading]=\"loading\">\n @for (tag of displayedTags; track tag.TaggedItemID) {\n <span class=\"tag-chip\" (click)=\"OnTagClick(tag)\">\n <i class=\"fa-solid fa-tag\"></i>\n <span class=\"tag-chip__name\">{{ tag.Name }}</span>\n @if (Editable) {\n <i\n class=\"fa-solid fa-xmark tag-chip__remove\"\n title=\"Remove tag\"\n (click)=\"OnRemove(tag, $event)\"></i>\n }\n </span>\n }\n\n @if (extraTagCount > 0) {\n <span class=\"tag-chip tag-chip--more\">+{{ extraTagCount }} more</span>\n }\n\n @if (Editable) {\n <div class=\"tag-chip-add\">\n <input\n type=\"text\"\n class=\"tag-chip-add__input\"\n [(ngModel)]=\"addInput\"\n (ngModelChange)=\"OnAddInputChange($event)\"\n (keydown.enter)=\"OnAddInputSubmit($event)\"\n placeholder=\"Add tag…\" />\n @if (showSuggestions && (suggestions.length > 0 || canCreateNew)) {\n <div class=\"tag-chip-add__suggestions\">\n @for (s of suggestions; track s.ID) {\n <button class=\"tag-chip-add__suggestion\" (click)=\"OnAddTag(s)\" type=\"button\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ s.Name }}\n </button>\n }\n @if (canCreateNew) {\n <button\n class=\"tag-chip-add__suggestion tag-chip-add__suggestion--create\"\n (click)=\"OnCreateNew()\"\n type=\"button\"\n title=\"Create a new tag with this name\">\n <i class=\"fa-solid fa-plus\"></i>\n Create \"{{ addInput.trim() }}\"\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"tag-chips.component.js","sourceRoot":"","sources":["../../../../src/lib/components/tag-chips/tag-chips.component.ts","../../../../src/lib/components/tag-chips/tag-chips.component.html"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';\n\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { LogError, Metadata, RunView } from '@memberjunction/core';\nimport type { MJTagEntity, MJTaggedItemEntity } from '@memberjunction/core-entities';\n\n/**\n * Compact tag chips for a single record (mockup 22). Loads tags by\n * querying `MJ: Tagged Items` filtered to `(EntityID, RecordID)`, then\n * resolves names from `MJ: Tags` in a single batch. Render-only by\n * default; pass `Editable=true` to surface an inline add field and\n * per-chip remove buttons.\n *\n * Intentionally lightweight — not a tag manager. For richer tag tooling\n * (cloud view, related records, etc.) use `mj-record-tags` from\n * `@memberjunction/ng-record-tags`.\n */\n\ninterface DisplayTag {\n /** TaggedItem row ID — used for removal. */\n TaggedItemID: string;\n /** Tag.ID — useful for downstream filtering / lookups. */\n TagID: string;\n /** Tag display name. */\n Name: string;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-tag-chips',\n templateUrl: './tag-chips.component.html',\n styleUrls: ['./tag-chips.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TagChipsComponent extends BaseAngularComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n /** Entity name (e.g. 'MJ: Lists'). Required. */\n @Input()\n set EntityName(value: string | null) {\n if (this._entityName !== value) {\n this._entityName = value;\n if (this.initialized && value && this._recordId) void this.loadTags();\n }\n }\n get EntityName(): string | null {\n return this._entityName;\n }\n private _entityName: string | null = null;\n\n /** Record ID (the row's primary key, serialized). Required. */\n @Input()\n set RecordID(value: string | null) {\n if (this._recordId !== value) {\n this._recordId = value;\n if (this.initialized && value && this._entityName) void this.loadTags();\n }\n }\n get RecordID(): string | null {\n return this._recordId;\n }\n private _recordId: string | null = null;\n\n /** When true, shows add input + remove buttons on chips. */\n @Input() Editable = false;\n\n /** Cap visible chips and surface \"+N more\". Defaults to 6 for cards. */\n @Input() MaxDisplay = 6;\n\n /** Emitted when a chip is clicked. Lets the parent drive filter-by-tag. */\n @Output() TagClicked = new EventEmitter<{ TagID: string; Name: string }>();\n\n /** Emitted after add/remove so parents can refresh dependent data. */\n @Output() TagsChanged = new EventEmitter<void>();\n\n public tags: DisplayTag[] = [];\n public Loading = false;\n\n /** @deprecated Use {@link Loading}. */\n public get loading() {\n return this.Loading;\n }\n /** @deprecated Use {@link Loading}. */\n public set loading(value) {\n this.Loading = value;\n }\n public AddInput = '';\n\n /** @deprecated Use {@link AddInput}. */\n public get addInput() {\n return this.AddInput;\n }\n /** @deprecated Use {@link AddInput}. */\n public set addInput(value) {\n this.AddInput = value;\n }\n public Suggestions: MJTagEntity[] = [];\n\n /** @deprecated Use {@link Suggestions}. */\n public get suggestions(): MJTagEntity[] {\n return this.Suggestions;\n }\n /** @deprecated Use {@link Suggestions}. */\n public set suggestions(value: MJTagEntity[]) {\n this.Suggestions = value;\n }\n public ShowSuggestions = false;\n\n /** @deprecated Use {@link ShowSuggestions}. */\n public get showSuggestions() {\n return this.ShowSuggestions;\n }\n /** @deprecated Use {@link ShowSuggestions}. */\n public set showSuggestions(value) {\n this.ShowSuggestions = value;\n }\n /** True when the trimmed input doesn't exactly match any existing tag —\n * drives the \"Create '<term>'\" affordance at the top of the dropdown. */\n public CanCreateNew = false;\n\n /** @deprecated Use {@link CanCreateNew}. */\n public get canCreateNew() {\n return this.CanCreateNew;\n }\n /** @deprecated Use {@link CanCreateNew}. */\n public set canCreateNew(value) {\n this.CanCreateNew = value;\n }\n\n private initialized = false;\n private entityID: string | null = null;\n\n async ngOnInit(): Promise<void> {\n this.initialized = true;\n if (this._entityName && this._recordId) await this.loadTags();\n }\n\n public get DisplayedTags(): DisplayTag[] {\n return this.tags.slice(0, this.MaxDisplay);\n }\n\n /** @deprecated Use {@link DisplayedTags}. */\n public get displayedTags(): DisplayTag[] {\n return this.DisplayedTags;\n }\n\n public get ExtraTagCount(): number {\n return Math.max(0, this.tags.length - this.MaxDisplay);\n }\n\n /** @deprecated Use {@link ExtraTagCount}. */\n public get extraTagCount(): number {\n return this.ExtraTagCount;\n }\n\n public OnTagClick(tag: DisplayTag): void {\n this.TagClicked.emit({ TagID: tag.TagID, Name: tag.Name });\n }\n\n public async OnRemove(tag: DisplayTag, event: Event): Promise<void> {\n event.stopPropagation();\n if (!this.Editable) return;\n try {\n const md = this.metadata();\n const entity = await md.GetEntityObject<MJTaggedItemEntity>('MJ: Tagged Items', this.ProviderToUse.CurrentUser ?? undefined);\n const loaded = await entity.Load(tag.TaggedItemID);\n if (!loaded) return;\n const ok = await entity.Delete();\n if (ok) {\n this.tags = this.tags.filter((t) => t.TaggedItemID !== tag.TaggedItemID);\n this.TagsChanged.emit();\n this.cdr.markForCheck();\n }\n } catch (e) {\n LogError(`tag-chips: remove failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n public async OnAddInputChange(value: string): Promise<void> {\n this.AddInput = value;\n const term = value.trim();\n if (term.length < 1) {\n this.Suggestions = [];\n this.CanCreateNew = false;\n this.ShowSuggestions = false;\n this.cdr.markForCheck();\n return;\n }\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const escaped = term.replace(/'/g, \"''\");\n const result = await rv.RunView<MJTagEntity>({\n EntityName: 'MJ: Tags',\n ExtraFilter: `Name LIKE '%${escaped}%'`,\n OrderBy: 'Name',\n MaxRows: 8,\n ResultType: 'entity_object',\n });\n const alreadyApplied = new Set(this.tags.map((t) => t.TagID));\n this.Suggestions = (result.Results ?? []).filter((t) => !alreadyApplied.has(t.ID));\n // Offer \"Create '<term>'\" when the typed text doesn't exactly\n // match any existing tag (case-insensitive). Without this, typing\n // a brand-new tag name and hitting Enter does nothing — there's\n // no suggestion to click.\n const lowerTerm = term.toLowerCase();\n this.CanCreateNew = !this.Suggestions.some(\n (s) => s.Name.toLowerCase() === lowerTerm,\n );\n this.ShowSuggestions = true;\n } catch (e) {\n LogError(`tag-chips: suggestion lookup failed: ${e instanceof Error ? e.message : String(e)}`);\n } finally {\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Enter-key handler on the input. If suggestions are showing,\n * picks the first one (existing tag); otherwise creates a new tag\n * from the typed text and applies it. Closes the suggestion menu\n * on either path.\n */\n public async OnAddInputSubmit(event?: Event): Promise<void> {\n event?.preventDefault();\n const term = this.AddInput.trim();\n if (term.length === 0) return;\n // Existing tag in suggestions takes priority — Enter selects the\n // first match (matching most autocomplete UIs).\n if (this.Suggestions.length > 0) {\n await this.OnAddTag(this.Suggestions[0]);\n return;\n }\n if (this.CanCreateNew) {\n await this.createAndAddTag(term);\n }\n }\n\n public async OnAddTag(tag: MJTagEntity): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n await this.applyTagToRecord(tag.ID, tag.Name);\n }\n\n /** Click handler for the \"Create '<term>'\" affordance. Creates the\n * `MJ: Tags` row then attaches it via the standard apply path. */\n public async OnCreateNew(): Promise<void> {\n const term = this.AddInput.trim();\n if (term.length === 0) return;\n await this.createAndAddTag(term);\n }\n\n private async createAndAddTag(name: string): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n try {\n const md = this.metadata();\n const tag = await md.GetEntityObject<MJTagEntity>('MJ: Tags', this.ProviderToUse.CurrentUser ?? undefined);\n tag.NewRecord();\n tag.Name = name;\n // MJ: Tags requires both Name (canonical) and DisplayName (UI).\n // Default DisplayName to the same text the user typed — they can\n // refine it later via the Tags entity editor if needed.\n tag.DisplayName = name;\n const ok = await tag.Save();\n if (!ok) {\n LogError(`tag-chips: create-tag save failed: ${tag.LatestResult?.CompleteMessage ?? 'unknown'}`);\n return;\n }\n await this.applyTagToRecord(tag.ID, tag.Name);\n } catch (e) {\n LogError(`tag-chips: create-and-add failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n private async applyTagToRecord(tagId: string, tagName: string): Promise<void> {\n if (!this._entityName || !this._recordId) return;\n try {\n const md = this.metadata();\n const entity = await md.GetEntityObject<MJTaggedItemEntity>('MJ: Tagged Items', this.ProviderToUse.CurrentUser ?? undefined);\n entity.NewRecord();\n entity.TagID = tagId;\n entity.RecordID = this._recordId;\n const entityInfo = md.EntityByName(this._entityName);\n if (entityInfo) entity.EntityID = entityInfo.ID;\n entity.Weight = 1.0;\n const ok = await entity.Save();\n if (!ok) {\n LogError(`tag-chips: attach-tag save failed: ${entity.LatestResult?.CompleteMessage ?? 'unknown'}`);\n return;\n }\n this.tags = [...this.tags, { TaggedItemID: entity.ID, TagID: tagId, Name: tagName }];\n this.AddInput = '';\n this.Suggestions = [];\n this.CanCreateNew = false;\n this.ShowSuggestions = false;\n this.TagsChanged.emit();\n this.cdr.markForCheck();\n } catch (e) {\n LogError(`tag-chips: apply failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n /**\n * Bulk-load tags + their names in two RunViews — one for the join\n * rows and one to resolve display names. Cheap; this typically returns\n * fewer than 10 rows.\n */\n private async loadTags(): Promise<void> {\n if (!this._entityName || !this._recordId) {\n this.tags = [];\n return;\n }\n this.Loading = true;\n this.cdr.markForCheck();\n try {\n const md = this.metadata();\n const entityInfo = md.EntityByName(this._entityName);\n if (!entityInfo) {\n this.tags = [];\n return;\n }\n this.entityID = entityInfo.ID;\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const recordIdEscaped = this._recordId.replace(/'/g, \"''\");\n const joinResult = await rv.RunView<{ ID: string; TagID: string }>({\n EntityName: 'MJ: Tagged Items',\n ExtraFilter: `EntityID='${entityInfo.ID}' AND RecordID='${recordIdEscaped}'`,\n Fields: ['ID', 'TagID'],\n ResultType: 'simple',\n });\n if (!joinResult.Success) {\n this.tags = [];\n return;\n }\n const rows = joinResult.Results ?? [];\n if (rows.length === 0) {\n this.tags = [];\n return;\n }\n const tagIds = Array.from(new Set(rows.map((r) => String(r.TagID))));\n const tagsResult = await rv.RunView<{ ID: string; Name: string }>({\n EntityName: 'MJ: Tags',\n ExtraFilter: `ID IN (${tagIds.map((id) => `'${id}'`).join(',')})`,\n Fields: ['ID', 'Name'],\n ResultType: 'simple',\n });\n const nameById = new Map<string, string>();\n for (const t of tagsResult.Results ?? []) nameById.set(String(t.ID), String(t.Name));\n this.tags = rows\n .map((r) => ({\n TaggedItemID: String(r.ID),\n TagID: String(r.TagID),\n Name: nameById.get(String(r.TagID)) ?? '(unknown tag)',\n }))\n .sort((a, b) => a.Name.localeCompare(b.Name));\n } finally {\n this.Loading = false;\n this.cdr.markForCheck();\n }\n }\n\n private metadata(): Metadata {\n // ProviderToUse always resolves (it falls back to the global default itself), so a\n // `?? new Metadata()` arm here was dead code that would have defeated an injected provider.\n return this.ProviderToUse as unknown as Metadata;\n }\n}\n","<div class=\"tag-chips\" [class.tag-chips--loading]=\"loading\">\n @for (tag of displayedTags; track tag.TaggedItemID) {\n <span class=\"tag-chip\" (click)=\"OnTagClick(tag)\">\n <i class=\"fa-solid fa-tag\"></i>\n <span class=\"tag-chip__name\">{{ tag.Name }}</span>\n @if (Editable) {\n <i\n class=\"fa-solid fa-xmark tag-chip__remove\"\n title=\"Remove tag\"\n (click)=\"OnRemove(tag, $event)\"></i>\n }\n </span>\n }\n\n @if (extraTagCount > 0) {\n <span class=\"tag-chip tag-chip--more\">+{{ extraTagCount }} more</span>\n }\n\n @if (Editable) {\n <div class=\"tag-chip-add\">\n <input\n type=\"text\"\n class=\"tag-chip-add__input\"\n [(ngModel)]=\"addInput\"\n (ngModelChange)=\"OnAddInputChange($event)\"\n (keydown.enter)=\"OnAddInputSubmit($event)\"\n placeholder=\"Add tag…\" />\n @if (showSuggestions && (suggestions.length > 0 || canCreateNew)) {\n <div class=\"tag-chip-add__suggestions\">\n @for (s of suggestions; track s.ID) {\n <button class=\"tag-chip-add__suggestion\" (click)=\"OnAddTag(s)\" type=\"button\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ s.Name }}\n </button>\n }\n @if (canCreateNew) {\n <button\n class=\"tag-chip-add__suggestion tag-chip-add__suggestion--create\"\n (click)=\"OnCreateNew()\"\n type=\"button\"\n title=\"Create a new tag with this name\">\n <i class=\"fa-solid fa-plus\"></i>\n Create \"{{ addInput.trim() }}\"\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n"]}
|
|
@@ -16,7 +16,11 @@ export declare class ListManagementService {
|
|
|
16
16
|
private categoryCache;
|
|
17
17
|
private membershipCache;
|
|
18
18
|
private loadingSubject;
|
|
19
|
-
|
|
19
|
+
Loading$: Observable<boolean>;
|
|
20
|
+
/** @deprecated Use {@link Loading$}. */
|
|
21
|
+
get loading$(): Observable<boolean>;
|
|
22
|
+
/** @deprecated Use {@link Loading$}. */
|
|
23
|
+
set loading$(value: Observable<boolean>);
|
|
20
24
|
private _provider;
|
|
21
25
|
get Provider(): IMetadataProvider;
|
|
22
26
|
set Provider(value: IMetadataProvider | null);
|
|
@@ -24,39 +28,57 @@ export declare class ListManagementService {
|
|
|
24
28
|
/**
|
|
25
29
|
* Get lists for a specific entity, with optional caching
|
|
26
30
|
*/
|
|
31
|
+
GetListsForEntity(entityId: string, userId?: string, forceRefresh?: boolean): Promise<MJListEntity[]>;
|
|
32
|
+
/** @deprecated Use {@link GetListsForEntity}. */
|
|
27
33
|
getListsForEntity(entityId: string, userId?: string, forceRefresh?: boolean): Promise<MJListEntity[]>;
|
|
28
34
|
/**
|
|
29
35
|
* Get all list categories
|
|
30
36
|
*/
|
|
37
|
+
GetListCategories(forceRefresh?: boolean): Promise<MJListCategoryEntity[]>;
|
|
38
|
+
/** @deprecated Use {@link GetListCategories}. */
|
|
31
39
|
getListCategories(forceRefresh?: boolean): Promise<MJListCategoryEntity[]>;
|
|
32
40
|
/**
|
|
33
41
|
* Get membership information for a set of records
|
|
34
42
|
* Returns a Map where key is listId and value is array of recordIds that are members
|
|
35
43
|
*/
|
|
44
|
+
GetRecordMembership(entityId: string, recordIds: string[]): Promise<Map<string, string[]>>;
|
|
45
|
+
/** @deprecated Use {@link GetRecordMembership}. */
|
|
36
46
|
getRecordMembership(entityId: string, recordIds: string[]): Promise<Map<string, string[]>>;
|
|
37
47
|
/**
|
|
38
48
|
* Get lists that contain a specific record
|
|
39
49
|
*/
|
|
50
|
+
GetListsForRecord(entityId: string, recordId: string): Promise<MJListEntity[]>;
|
|
51
|
+
/** @deprecated Use {@link GetListsForRecord}. */
|
|
40
52
|
getListsForRecord(entityId: string, recordId: string): Promise<MJListEntity[]>;
|
|
41
53
|
/**
|
|
42
54
|
* Get item count for a list
|
|
43
55
|
*/
|
|
56
|
+
GetListItemCount(listId: string): Promise<number>;
|
|
57
|
+
/** @deprecated Use {@link GetListItemCount}. */
|
|
44
58
|
getListItemCount(listId: string): Promise<number>;
|
|
45
59
|
/**
|
|
46
60
|
* Build view models for lists with membership information
|
|
47
61
|
*/
|
|
62
|
+
BuildListViewModels(lists: MJListEntity[], recordIds: string[], membership: Map<string, string[]>): Promise<ListItemViewModel[]>;
|
|
63
|
+
/** @deprecated Use {@link BuildListViewModels}. */
|
|
48
64
|
buildListViewModels(lists: MJListEntity[], recordIds: string[], membership: Map<string, string[]>): Promise<ListItemViewModel[]>;
|
|
49
65
|
/**
|
|
50
66
|
* Add records to one or more lists
|
|
51
67
|
*/
|
|
68
|
+
AddRecordsToLists(listIds: string[], recordIds: string[], skipDuplicates?: boolean): Promise<BatchOperationResult>;
|
|
69
|
+
/** @deprecated Use {@link AddRecordsToLists}. */
|
|
52
70
|
addRecordsToLists(listIds: string[], recordIds: string[], skipDuplicates?: boolean): Promise<BatchOperationResult>;
|
|
53
71
|
/**
|
|
54
72
|
* Remove records from one or more lists
|
|
55
73
|
*/
|
|
74
|
+
RemoveRecordsFromLists(listIds: string[], recordIds: string[]): Promise<BatchOperationResult>;
|
|
75
|
+
/** @deprecated Use {@link RemoveRecordsFromLists}. */
|
|
56
76
|
removeRecordsFromLists(listIds: string[], recordIds: string[]): Promise<BatchOperationResult>;
|
|
57
77
|
/**
|
|
58
78
|
* Create a new list
|
|
59
79
|
*/
|
|
80
|
+
CreateList(config: CreateListConfig): Promise<MJListEntity | null>;
|
|
81
|
+
/** @deprecated Use {@link CreateList}. */
|
|
60
82
|
createList(config: CreateListConfig): Promise<MJListEntity | null>;
|
|
61
83
|
/**
|
|
62
84
|
* Check if a cache entry is still valid
|
|
@@ -65,6 +87,8 @@ export declare class ListManagementService {
|
|
|
65
87
|
/**
|
|
66
88
|
* Invalidate cache for a specific entity or all caches
|
|
67
89
|
*/
|
|
90
|
+
InvalidateCache(entityId?: string): void;
|
|
91
|
+
/** @deprecated Use {@link InvalidateCache}. */
|
|
68
92
|
invalidateCache(entityId?: string): void;
|
|
69
93
|
/**
|
|
70
94
|
* Invalidate list cache for a specific entity
|
|
@@ -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;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;
|
|
1
|
+
{"version":3,"file":"list-management.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/list-management.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,15 @@ export class ListManagementService {
|
|
|
17
17
|
membershipCache = new Map();
|
|
18
18
|
// Loading state subjects
|
|
19
19
|
loadingSubject = new BehaviorSubject(false);
|
|
20
|
-
|
|
20
|
+
Loading$ = this.loadingSubject.asObservable();
|
|
21
|
+
/** @deprecated Use {@link Loading$}. */
|
|
22
|
+
get loading$() {
|
|
23
|
+
return this.Loading$;
|
|
24
|
+
}
|
|
25
|
+
/** @deprecated Use {@link Loading$}. */
|
|
26
|
+
set loading$(value) {
|
|
27
|
+
this.Loading$ = value;
|
|
28
|
+
}
|
|
21
29
|
_provider = null;
|
|
22
30
|
get Provider() {
|
|
23
31
|
return this._provider ?? Metadata.Provider;
|
|
@@ -29,7 +37,7 @@ export class ListManagementService {
|
|
|
29
37
|
/**
|
|
30
38
|
* Get lists for a specific entity, with optional caching
|
|
31
39
|
*/
|
|
32
|
-
async
|
|
40
|
+
async GetListsForEntity(entityId, userId, forceRefresh = false) {
|
|
33
41
|
const cacheKey = `${entityId}_${userId || 'all'}`;
|
|
34
42
|
// Check cache first
|
|
35
43
|
if (!forceRefresh) {
|
|
@@ -68,10 +76,14 @@ export class ListManagementService {
|
|
|
68
76
|
this.loadingSubject.next(false);
|
|
69
77
|
}
|
|
70
78
|
}
|
|
79
|
+
/** @deprecated Use {@link GetListsForEntity}. */
|
|
80
|
+
async getListsForEntity(entityId, userId, forceRefresh = false) {
|
|
81
|
+
return this.GetListsForEntity(entityId, userId, forceRefresh);
|
|
82
|
+
}
|
|
71
83
|
/**
|
|
72
84
|
* Get all list categories
|
|
73
85
|
*/
|
|
74
|
-
async
|
|
86
|
+
async GetListCategories(forceRefresh = false) {
|
|
75
87
|
if (!forceRefresh && this.categoryCache && this.isCacheValid(this.categoryCache)) {
|
|
76
88
|
return this.categoryCache.data;
|
|
77
89
|
}
|
|
@@ -90,11 +102,15 @@ export class ListManagementService {
|
|
|
90
102
|
}
|
|
91
103
|
return [];
|
|
92
104
|
}
|
|
105
|
+
/** @deprecated Use {@link GetListCategories}. */
|
|
106
|
+
async getListCategories(forceRefresh = false) {
|
|
107
|
+
return this.GetListCategories(forceRefresh);
|
|
108
|
+
}
|
|
93
109
|
/**
|
|
94
110
|
* Get membership information for a set of records
|
|
95
111
|
* Returns a Map where key is listId and value is array of recordIds that are members
|
|
96
112
|
*/
|
|
97
|
-
async
|
|
113
|
+
async GetRecordMembership(entityId, recordIds) {
|
|
98
114
|
if (recordIds.length === 0) {
|
|
99
115
|
return new Map();
|
|
100
116
|
}
|
|
@@ -136,10 +152,14 @@ export class ListManagementService {
|
|
|
136
152
|
this.loadingSubject.next(false);
|
|
137
153
|
}
|
|
138
154
|
}
|
|
155
|
+
/** @deprecated Use {@link GetRecordMembership}. */
|
|
156
|
+
async getRecordMembership(entityId, recordIds) {
|
|
157
|
+
return this.GetRecordMembership(entityId, recordIds);
|
|
158
|
+
}
|
|
139
159
|
/**
|
|
140
160
|
* Get lists that contain a specific record
|
|
141
161
|
*/
|
|
142
|
-
async
|
|
162
|
+
async GetListsForRecord(entityId, recordId) {
|
|
143
163
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
144
164
|
// Get list details for this record — read-only lookup
|
|
145
165
|
const detailsResult = await rv.RunView({
|
|
@@ -161,10 +181,14 @@ export class ListManagementService {
|
|
|
161
181
|
});
|
|
162
182
|
return listsResult.Success ? (listsResult.Results || []) : [];
|
|
163
183
|
}
|
|
184
|
+
/** @deprecated Use {@link GetListsForRecord}. */
|
|
185
|
+
async getListsForRecord(entityId, recordId) {
|
|
186
|
+
return this.GetListsForRecord(entityId, recordId);
|
|
187
|
+
}
|
|
164
188
|
/**
|
|
165
189
|
* Get item count for a list
|
|
166
190
|
*/
|
|
167
|
-
async
|
|
191
|
+
async GetListItemCount(listId) {
|
|
168
192
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
169
193
|
const result = await rv.RunView({
|
|
170
194
|
EntityName: 'MJ: List Details',
|
|
@@ -173,10 +197,14 @@ export class ListManagementService {
|
|
|
173
197
|
});
|
|
174
198
|
return result.Success ? result.TotalRowCount : 0;
|
|
175
199
|
}
|
|
200
|
+
/** @deprecated Use {@link GetListItemCount}. */
|
|
201
|
+
async getListItemCount(listId) {
|
|
202
|
+
return this.GetListItemCount(listId);
|
|
203
|
+
}
|
|
176
204
|
/**
|
|
177
205
|
* Build view models for lists with membership information
|
|
178
206
|
*/
|
|
179
|
-
async
|
|
207
|
+
async BuildListViewModels(lists, recordIds, membership) {
|
|
180
208
|
const viewModels = [];
|
|
181
209
|
const rv = RunView.FromMetadataProvider(this.Provider);
|
|
182
210
|
// Get item counts for all lists in one batched round trip of count_only
|
|
@@ -213,10 +241,14 @@ export class ListManagementService {
|
|
|
213
241
|
}
|
|
214
242
|
return viewModels;
|
|
215
243
|
}
|
|
244
|
+
/** @deprecated Use {@link BuildListViewModels}. */
|
|
245
|
+
async buildListViewModels(lists, recordIds, membership) {
|
|
246
|
+
return this.BuildListViewModels(lists, recordIds, membership);
|
|
247
|
+
}
|
|
216
248
|
/**
|
|
217
249
|
* Add records to one or more lists
|
|
218
250
|
*/
|
|
219
|
-
async
|
|
251
|
+
async AddRecordsToLists(listIds, recordIds, skipDuplicates = true) {
|
|
220
252
|
const result = {
|
|
221
253
|
success: 0,
|
|
222
254
|
failed: 0,
|
|
@@ -295,10 +327,14 @@ export class ListManagementService {
|
|
|
295
327
|
this.membershipCache.clear();
|
|
296
328
|
return result;
|
|
297
329
|
}
|
|
330
|
+
/** @deprecated Use {@link AddRecordsToLists}. */
|
|
331
|
+
async addRecordsToLists(listIds, recordIds, skipDuplicates = true) {
|
|
332
|
+
return this.AddRecordsToLists(listIds, recordIds, skipDuplicates);
|
|
333
|
+
}
|
|
298
334
|
/**
|
|
299
335
|
* Remove records from one or more lists
|
|
300
336
|
*/
|
|
301
|
-
async
|
|
337
|
+
async RemoveRecordsFromLists(listIds, recordIds) {
|
|
302
338
|
const result = {
|
|
303
339
|
success: 0,
|
|
304
340
|
failed: 0,
|
|
@@ -362,10 +398,14 @@ export class ListManagementService {
|
|
|
362
398
|
this.membershipCache.clear();
|
|
363
399
|
return result;
|
|
364
400
|
}
|
|
401
|
+
/** @deprecated Use {@link RemoveRecordsFromLists}. */
|
|
402
|
+
async removeRecordsFromLists(listIds, recordIds) {
|
|
403
|
+
return this.RemoveRecordsFromLists(listIds, recordIds);
|
|
404
|
+
}
|
|
365
405
|
/**
|
|
366
406
|
* Create a new list
|
|
367
407
|
*/
|
|
368
|
-
async
|
|
408
|
+
async CreateList(config) {
|
|
369
409
|
const md = this.Provider;
|
|
370
410
|
try {
|
|
371
411
|
const list = await md.GetEntityObject('MJ: Lists', md.CurrentUser);
|
|
@@ -390,6 +430,10 @@ export class ListManagementService {
|
|
|
390
430
|
return null;
|
|
391
431
|
}
|
|
392
432
|
}
|
|
433
|
+
/** @deprecated Use {@link CreateList}. */
|
|
434
|
+
async createList(config) {
|
|
435
|
+
return this.CreateList(config);
|
|
436
|
+
}
|
|
393
437
|
/**
|
|
394
438
|
* Check if a cache entry is still valid
|
|
395
439
|
*/
|
|
@@ -401,7 +445,7 @@ export class ListManagementService {
|
|
|
401
445
|
/**
|
|
402
446
|
* Invalidate cache for a specific entity or all caches
|
|
403
447
|
*/
|
|
404
|
-
|
|
448
|
+
InvalidateCache(entityId) {
|
|
405
449
|
if (entityId) {
|
|
406
450
|
this.invalidateListCache(entityId);
|
|
407
451
|
}
|
|
@@ -411,6 +455,10 @@ export class ListManagementService {
|
|
|
411
455
|
this.membershipCache.clear();
|
|
412
456
|
}
|
|
413
457
|
}
|
|
458
|
+
/** @deprecated Use {@link InvalidateCache}. */
|
|
459
|
+
invalidateCache(entityId) {
|
|
460
|
+
return this.InvalidateCache(entityId);
|
|
461
|
+
}
|
|
414
462
|
/**
|
|
415
463
|
* Invalidate list cache for a specific entity
|
|
416
464
|
*/
|