@memberjunction/ng-entity-viewer 5.27.1 → 5.28.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/README.md +101 -0
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts +14 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.d.ts.map +1 -1
- package/dist/lib/entity-data-grid/entity-data-grid.component.js +199 -172
- package/dist/lib/entity-data-grid/entity-data-grid.component.js.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts +9 -1
- package/dist/lib/entity-viewer/entity-viewer.component.d.ts.map +1 -1
- package/dist/lib/entity-viewer/entity-viewer.component.js +58 -38
- package/dist/lib/entity-viewer/entity-viewer.component.js.map +1 -1
- package/dist/lib/recycle-bin/events/recycle-bin-events.d.ts +91 -0
- package/dist/lib/recycle-bin/events/recycle-bin-events.d.ts.map +1 -0
- package/dist/lib/recycle-bin/events/recycle-bin-events.js +10 -0
- package/dist/lib/recycle-bin/events/recycle-bin-events.js.map +1 -0
- package/dist/lib/recycle-bin/recycle-bin-chip.component.d.ts +75 -0
- package/dist/lib/recycle-bin/recycle-bin-chip.component.d.ts.map +1 -0
- package/dist/lib/recycle-bin/recycle-bin-chip.component.js +228 -0
- package/dist/lib/recycle-bin/recycle-bin-chip.component.js.map +1 -0
- package/dist/lib/recycle-bin/recycle-bin.component.d.ts +178 -0
- package/dist/lib/recycle-bin/recycle-bin.component.d.ts.map +1 -0
- package/dist/lib/recycle-bin/recycle-bin.component.js +681 -0
- package/dist/lib/recycle-bin/recycle-bin.component.js.map +1 -0
- package/dist/module.d.ts +13 -9
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +23 -7
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +13 -11
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event arg types for {@link RecycleBinComponent}.
|
|
3
|
+
*
|
|
4
|
+
* Follows the same Before/After cancelable pattern used by
|
|
5
|
+
* {@link EntityDataGridComponent}: any event whose name starts with
|
|
6
|
+
* `Before` carries `cancel: boolean` and `cancelReason?: string` so
|
|
7
|
+
* consumers can intercept and abort or take over processing.
|
|
8
|
+
*/
|
|
9
|
+
import { MJRecordChangeEntity } from '@memberjunction/core-entities';
|
|
10
|
+
/** Forward type to avoid circular dependency with the component. */
|
|
11
|
+
export type RecycleBinComponentRef = unknown;
|
|
12
|
+
/**
|
|
13
|
+
* Base shape for every Recycle Bin event.
|
|
14
|
+
*/
|
|
15
|
+
export interface RecycleBinEventArgs {
|
|
16
|
+
/** The Recycle Bin component instance that raised the event. */
|
|
17
|
+
bin: RecycleBinComponentRef;
|
|
18
|
+
/** When the event was raised. */
|
|
19
|
+
timestamp: Date;
|
|
20
|
+
/** The entity the bin is operating on. */
|
|
21
|
+
entityName: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base shape for cancelable Recycle Bin events. Set `cancel = true` to
|
|
25
|
+
* abort the operation; the matching `after*` event will not fire.
|
|
26
|
+
*/
|
|
27
|
+
export interface CancelableRecycleBinEventArgs extends RecycleBinEventArgs {
|
|
28
|
+
/** Set to true to abort. */
|
|
29
|
+
cancel: boolean;
|
|
30
|
+
/** Optional reason surfaced by the consumer. */
|
|
31
|
+
cancelReason?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface BeforeRecycleBinOpenEventArgs extends CancelableRecycleBinEventArgs {
|
|
34
|
+
/** Reserved for future filter/scope params the consumer may want to validate. */
|
|
35
|
+
readonly _kind: 'beforeRecycleBinOpen';
|
|
36
|
+
}
|
|
37
|
+
export interface AfterRecycleBinOpenEventArgs extends RecycleBinEventArgs {
|
|
38
|
+
/** Number of distinct deleted records discovered when the bin opened. */
|
|
39
|
+
deletedRecordCount: number;
|
|
40
|
+
readonly _kind: 'afterRecycleBinOpen';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* One deleted-record entry surfaced by the bin. Built from the most recent
|
|
44
|
+
* Delete RecordChange for a given EntityID + RecordID.
|
|
45
|
+
*/
|
|
46
|
+
export interface RecycleBinEntry {
|
|
47
|
+
/** The Delete RecordChange row that captured this snapshot. */
|
|
48
|
+
RecordChange: MJRecordChangeEntity;
|
|
49
|
+
/** The composite-key string that identified the record. */
|
|
50
|
+
RecordID: string;
|
|
51
|
+
/** The user-friendly summary line (e.g., a name field from the snapshot). */
|
|
52
|
+
DisplaySummary: string;
|
|
53
|
+
/** Up to N supporting fields chosen heuristically for the card. */
|
|
54
|
+
SupportingFields: Array<{
|
|
55
|
+
Name: string;
|
|
56
|
+
DisplayName: string;
|
|
57
|
+
Value: string;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
export interface BeforeRecordRestoreEventArgs extends CancelableRecycleBinEventArgs {
|
|
61
|
+
entry: RecycleBinEntry;
|
|
62
|
+
readonly _kind: 'beforeRecordRestore';
|
|
63
|
+
}
|
|
64
|
+
export interface AfterRecordRestoreEventArgs extends RecycleBinEventArgs {
|
|
65
|
+
entry: RecycleBinEntry;
|
|
66
|
+
/** True when the underlying insert succeeded. */
|
|
67
|
+
success: boolean;
|
|
68
|
+
/** Error message when success is false. */
|
|
69
|
+
errorMessage?: string;
|
|
70
|
+
readonly _kind: 'afterRecordRestore';
|
|
71
|
+
}
|
|
72
|
+
export interface BeforeRestoreCommitEventArgs extends CancelableRecycleBinEventArgs {
|
|
73
|
+
entry: RecycleBinEntry;
|
|
74
|
+
/** Field values that will be applied to the new record. */
|
|
75
|
+
fieldValues: Array<{
|
|
76
|
+
FieldName: string;
|
|
77
|
+
Value: unknown;
|
|
78
|
+
}>;
|
|
79
|
+
/** Optional reason captured at restore time. */
|
|
80
|
+
reason: string | null;
|
|
81
|
+
readonly _kind: 'beforeRestoreCommit';
|
|
82
|
+
}
|
|
83
|
+
export interface AfterRestoreCommitEventArgs extends RecycleBinEventArgs {
|
|
84
|
+
entry: RecycleBinEntry;
|
|
85
|
+
success: boolean;
|
|
86
|
+
/** ID of the newly created record (when success). */
|
|
87
|
+
newRecordID?: string;
|
|
88
|
+
errorMessage?: string;
|
|
89
|
+
readonly _kind: 'afterRestoreCommit';
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=recycle-bin-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recycle-bin-events.d.ts","sourceRoot":"","sources":["../../../../src/lib/recycle-bin/events/recycle-bin-events.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,oEAAoE;AACpE,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,GAAG,EAAE,sBAAsB,CAAC;IAC5B,iCAAiC;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB;IACxE,4BAA4B;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,WAAW,6BAA8B,SAAQ,6BAA6B;IAClF,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;CACxC;AAED,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACvE,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;CACvC;AAID;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,YAAY,EAAE,oBAAoB,CAAC;IACnC,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,gBAAgB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,4BAA6B,SAAQ,6BAA6B;IACjF,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;CACvC;AAED,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE,KAAK,EAAE,eAAe,CAAC;IACvB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;CACtC;AAID,MAAM,WAAW,4BAA6B,SAAQ,6BAA6B;IACjF,KAAK,EAAE,eAAe,CAAC;IACvB,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,gDAAgD;IAChD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;CACvC;AAED,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;CACtC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event arg types for {@link RecycleBinComponent}.
|
|
3
|
+
*
|
|
4
|
+
* Follows the same Before/After cancelable pattern used by
|
|
5
|
+
* {@link EntityDataGridComponent}: any event whose name starts with
|
|
6
|
+
* `Before` carries `cancel: boolean` and `cancelReason?: string` so
|
|
7
|
+
* consumers can intercept and abort or take over processing.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=recycle-bin-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recycle-bin-events.js","sourceRoot":"","sources":["../../../../src/lib/recycle-bin/events/recycle-bin-events.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG","sourcesContent":["/**\n * Event arg types for {@link RecycleBinComponent}.\n *\n * Follows the same Before/After cancelable pattern used by\n * {@link EntityDataGridComponent}: any event whose name starts with\n * `Before` carries `cancel: boolean` and `cancelReason?: string` so\n * consumers can intercept and abort or take over processing.\n */\n\nimport { MJRecordChangeEntity } from '@memberjunction/core-entities';\n\n/** Forward type to avoid circular dependency with the component. */\nexport type RecycleBinComponentRef = unknown;\n\n/**\n * Base shape for every Recycle Bin event.\n */\nexport interface RecycleBinEventArgs {\n /** The Recycle Bin component instance that raised the event. */\n bin: RecycleBinComponentRef;\n /** When the event was raised. */\n timestamp: Date;\n /** The entity the bin is operating on. */\n entityName: string;\n}\n\n/**\n * Base shape for cancelable Recycle Bin events. Set `cancel = true` to\n * abort the operation; the matching `after*` event will not fire.\n */\nexport interface CancelableRecycleBinEventArgs extends RecycleBinEventArgs {\n /** Set to true to abort. */\n cancel: boolean;\n /** Optional reason surfaced by the consumer. */\n cancelReason?: string;\n}\n\n// ─── Open / Close ──────────────────────────────────────────────────\n\nexport interface BeforeRecycleBinOpenEventArgs extends CancelableRecycleBinEventArgs {\n /** Reserved for future filter/scope params the consumer may want to validate. */\n readonly _kind: 'beforeRecycleBinOpen';\n}\n\nexport interface AfterRecycleBinOpenEventArgs extends RecycleBinEventArgs {\n /** Number of distinct deleted records discovered when the bin opened. */\n deletedRecordCount: number;\n readonly _kind: 'afterRecycleBinOpen';\n}\n\n// ─── Per-record restore (the user clicked Restore on a single card) ─\n\n/**\n * One deleted-record entry surfaced by the bin. Built from the most recent\n * Delete RecordChange for a given EntityID + RecordID.\n */\nexport interface RecycleBinEntry {\n /** The Delete RecordChange row that captured this snapshot. */\n RecordChange: MJRecordChangeEntity;\n /** The composite-key string that identified the record. */\n RecordID: string;\n /** The user-friendly summary line (e.g., a name field from the snapshot). */\n DisplaySummary: string;\n /** Up to N supporting fields chosen heuristically for the card. */\n SupportingFields: Array<{ Name: string; DisplayName: string; Value: string }>;\n}\n\nexport interface BeforeRecordRestoreEventArgs extends CancelableRecycleBinEventArgs {\n entry: RecycleBinEntry;\n readonly _kind: 'beforeRecordRestore';\n}\n\nexport interface AfterRecordRestoreEventArgs extends RecycleBinEventArgs {\n entry: RecycleBinEntry;\n /** True when the underlying insert succeeded. */\n success: boolean;\n /** Error message when success is false. */\n errorMessage?: string;\n readonly _kind: 'afterRecordRestore';\n}\n\n// ─── Restore commit (after the user confirms in the preview panel) ──\n\nexport interface BeforeRestoreCommitEventArgs extends CancelableRecycleBinEventArgs {\n entry: RecycleBinEntry;\n /** Field values that will be applied to the new record. */\n fieldValues: Array<{ FieldName: string; Value: unknown }>;\n /** Optional reason captured at restore time. */\n reason: string | null;\n readonly _kind: 'beforeRestoreCommit';\n}\n\nexport interface AfterRestoreCommitEventArgs extends RecycleBinEventArgs {\n entry: RecycleBinEntry;\n success: boolean;\n /** ID of the newly created record (when success). */\n newRecordID?: string;\n errorMessage?: string;\n readonly _kind: 'afterRestoreCommit';\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ChangeDetectorRef, EventEmitter, OnInit } from '@angular/core';
|
|
2
|
+
import { UserInfo } from '@memberjunction/core';
|
|
3
|
+
import { AfterRecordRestoreEventArgs, AfterRecycleBinOpenEventArgs, AfterRestoreCommitEventArgs, BeforeRecordRestoreEventArgs, BeforeRecycleBinOpenEventArgs, BeforeRestoreCommitEventArgs } from './events/recycle-bin-events';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Tiny composite that renders a Recycle Bin **chip button** (with live
|
|
7
|
+
* deleted-record count badge) and hosts the {@link RecycleBinComponent}
|
|
8
|
+
* slide-in panel that opens when clicked.
|
|
9
|
+
*
|
|
10
|
+
* Designed to be dropped into any toolbar in three lines:
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* <mj-recycle-bin-chip
|
|
14
|
+
* *ngIf="ShowRecycleBin"
|
|
15
|
+
* [EntityName]="effectiveEntity?.Name">
|
|
16
|
+
* </mj-recycle-bin-chip>
|
|
17
|
+
*
|
|
18
|
+
* The chip auto-hides itself when:
|
|
19
|
+
* - No `EntityName` is provided
|
|
20
|
+
* - The entity has `TrackRecordChanges = false`
|
|
21
|
+
* - The user lacks `CanDelete` permission on the entity
|
|
22
|
+
* - The deleted-record count is zero
|
|
23
|
+
*
|
|
24
|
+
* Each of those is the right behavior to avoid cluttering toolbars on
|
|
25
|
+
* entities where the bin is irrelevant.
|
|
26
|
+
*
|
|
27
|
+
* Consumers who want to intercept any bin action can pass through the
|
|
28
|
+
* standard cancelable Before/After events.
|
|
29
|
+
*/
|
|
30
|
+
export declare class RecycleBinChipComponent implements OnInit {
|
|
31
|
+
private cdr;
|
|
32
|
+
/**
|
|
33
|
+
* Entity name whose deleted records will be surfaced. When null/empty,
|
|
34
|
+
* the chip hides itself entirely.
|
|
35
|
+
*/
|
|
36
|
+
private _entityName;
|
|
37
|
+
set EntityName(value: string | null);
|
|
38
|
+
get EntityName(): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Optional context user for permission checks. Falls back to
|
|
41
|
+
* `Metadata.Provider.CurrentUser` when omitted.
|
|
42
|
+
*/
|
|
43
|
+
ContextUser: UserInfo | null;
|
|
44
|
+
BeforeRecycleBinOpen: EventEmitter<BeforeRecycleBinOpenEventArgs>;
|
|
45
|
+
AfterRecycleBinOpen: EventEmitter<AfterRecycleBinOpenEventArgs>;
|
|
46
|
+
BeforeRecordRestore: EventEmitter<BeforeRecordRestoreEventArgs>;
|
|
47
|
+
AfterRecordRestore: EventEmitter<AfterRecordRestoreEventArgs>;
|
|
48
|
+
BeforeRestoreCommit: EventEmitter<BeforeRestoreCommitEventArgs>;
|
|
49
|
+
AfterRestoreCommit: EventEmitter<AfterRestoreCommitEventArgs>;
|
|
50
|
+
DeletedCount: number;
|
|
51
|
+
PanelVisible: boolean;
|
|
52
|
+
IsVisible: boolean;
|
|
53
|
+
CanDelete: boolean;
|
|
54
|
+
TracksChanges: boolean;
|
|
55
|
+
private isInitialized;
|
|
56
|
+
constructor(cdr: ChangeDetectorRef);
|
|
57
|
+
ngOnInit(): void;
|
|
58
|
+
Toggle(): void;
|
|
59
|
+
OnPanelClosed(): void;
|
|
60
|
+
/**
|
|
61
|
+
* After-events bubble through but we also use them to refresh the count
|
|
62
|
+
* — restoring a record means it's no longer "deleted".
|
|
63
|
+
*/
|
|
64
|
+
OnAfterRecycleBinOpen(e: AfterRecycleBinOpenEventArgs): void;
|
|
65
|
+
OnAfterRestoreCommit(e: AfterRestoreCommitEventArgs): void;
|
|
66
|
+
/**
|
|
67
|
+
* Loads the deleted-record count and visibility flags. Called on init,
|
|
68
|
+
* when EntityName changes, and after the panel closes (so a restore
|
|
69
|
+
* decrements the badge).
|
|
70
|
+
*/
|
|
71
|
+
private refreshCount;
|
|
72
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RecycleBinChipComponent, never>;
|
|
73
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RecycleBinChipComponent, "mj-recycle-bin-chip", never, { "EntityName": { "alias": "EntityName"; "required": false; }; "ContextUser": { "alias": "ContextUser"; "required": false; }; }, { "BeforeRecycleBinOpen": "BeforeRecycleBinOpen"; "AfterRecycleBinOpen": "AfterRecycleBinOpen"; "BeforeRecordRestore": "BeforeRecordRestore"; "AfterRecordRestore": "AfterRecordRestore"; "BeforeRestoreCommit": "BeforeRestoreCommit"; "AfterRestoreCommit": "AfterRestoreCommit"; }, never, never, false, never>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=recycle-bin-chip.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recycle-bin-chip.component.d.ts","sourceRoot":"","sources":["../../../src/lib/recycle-bin/recycle-bin-chip.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EACjB,YAAY,EAEZ,MAAM,EAGP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,6BAA6B,CAAC;;AAErC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBA+Da,uBAAwB,YAAW,MAAM;IA0CxC,OAAO,CAAC,GAAG;IAzCvB;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAuB;IAC1C,IACI,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAKlC;IACD,IAAI,UAAU,IAAI,MAAM,GAAG,IAAI,CAE9B;IAED;;;OAGG;IACM,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAInC,oBAAoB,8CAAqD;IACzE,mBAAmB,6CAAoD;IACvE,mBAAmB,6CAAoD;IACvE,kBAAkB,4CAAmD;IACrE,mBAAmB,6CAAoD;IACvE,kBAAkB,4CAAmD;IAIxE,YAAY,SAAK;IACjB,YAAY,UAAS;IACrB,SAAS,UAAS;IAClB,SAAS,UAAS;IAClB,aAAa,UAAS;IAE7B,OAAO,CAAC,aAAa,CAAS;gBAEV,GAAG,EAAE,iBAAiB;IAE1C,QAAQ,IAAI,IAAI;IAKT,MAAM,IAAI,IAAI;IAKd,aAAa,IAAI,IAAI;IAM5B;;;OAGG;IACI,qBAAqB,CAAC,CAAC,EAAE,4BAA4B,GAAG,IAAI;IAM5D,oBAAoB,CAAC,CAAC,EAAE,2BAA2B,GAAG,IAAI;IAMjE;;;;OAIG;YACW,YAAY;yCAjFf,uBAAuB;2CAAvB,uBAAuB;CA6InC"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { Component, ChangeDetectionStrategy, EventEmitter, Input, Output, ViewEncapsulation, } from '@angular/core';
|
|
2
|
+
import { Metadata, RunView } from '@memberjunction/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "./recycle-bin.component";
|
|
5
|
+
function RecycleBinChipComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
6
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
7
|
+
i0.ɵɵelementStart(0, "button", 0);
|
|
8
|
+
i0.ɵɵlistener("click", function RecycleBinChipComponent_Conditional_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Toggle()); });
|
|
9
|
+
i0.ɵɵelement(1, "i", 1);
|
|
10
|
+
i0.ɵɵelementStart(2, "span", 2);
|
|
11
|
+
i0.ɵɵtext(3, "Recycle Bin");
|
|
12
|
+
i0.ɵɵelementEnd();
|
|
13
|
+
i0.ɵɵelementStart(4, "span", 3);
|
|
14
|
+
i0.ɵɵtext(5);
|
|
15
|
+
i0.ɵɵelementEnd()();
|
|
16
|
+
i0.ɵɵelementStart(6, "mj-recycle-bin", 4);
|
|
17
|
+
i0.ɵɵlistener("Closed", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_Closed_6_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnPanelClosed()); })("BeforeRecycleBinOpen", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_BeforeRecycleBinOpen_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.BeforeRecycleBinOpen.emit($event)); })("AfterRecycleBinOpen", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_AfterRecycleBinOpen_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnAfterRecycleBinOpen($event)); })("BeforeRecordRestore", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_BeforeRecordRestore_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.BeforeRecordRestore.emit($event)); })("AfterRecordRestore", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_AfterRecordRestore_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.AfterRecordRestore.emit($event)); })("BeforeRestoreCommit", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_BeforeRestoreCommit_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.BeforeRestoreCommit.emit($event)); })("AfterRestoreCommit", function RecycleBinChipComponent_Conditional_0_Template_mj_recycle_bin_AfterRestoreCommit_6_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnAfterRestoreCommit($event)); });
|
|
18
|
+
i0.ɵɵelementEnd();
|
|
19
|
+
} if (rf & 2) {
|
|
20
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
21
|
+
i0.ɵɵattribute("title", "Recycle Bin \u00B7 " + ctx_r1.DeletedCount + " deleted record" + (ctx_r1.DeletedCount === 1 ? "" : "s"));
|
|
22
|
+
i0.ɵɵadvance(5);
|
|
23
|
+
i0.ɵɵtextInterpolate(ctx_r1.DeletedCount);
|
|
24
|
+
i0.ɵɵadvance();
|
|
25
|
+
i0.ɵɵproperty("Visible", ctx_r1.PanelVisible)("EntityName", ctx_r1.EntityName)("ContextUser", ctx_r1.ContextUser);
|
|
26
|
+
} }
|
|
27
|
+
/**
|
|
28
|
+
* Tiny composite that renders a Recycle Bin **chip button** (with live
|
|
29
|
+
* deleted-record count badge) and hosts the {@link RecycleBinComponent}
|
|
30
|
+
* slide-in panel that opens when clicked.
|
|
31
|
+
*
|
|
32
|
+
* Designed to be dropped into any toolbar in three lines:
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <mj-recycle-bin-chip
|
|
36
|
+
* *ngIf="ShowRecycleBin"
|
|
37
|
+
* [EntityName]="effectiveEntity?.Name">
|
|
38
|
+
* </mj-recycle-bin-chip>
|
|
39
|
+
*
|
|
40
|
+
* The chip auto-hides itself when:
|
|
41
|
+
* - No `EntityName` is provided
|
|
42
|
+
* - The entity has `TrackRecordChanges = false`
|
|
43
|
+
* - The user lacks `CanDelete` permission on the entity
|
|
44
|
+
* - The deleted-record count is zero
|
|
45
|
+
*
|
|
46
|
+
* Each of those is the right behavior to avoid cluttering toolbars on
|
|
47
|
+
* entities where the bin is irrelevant.
|
|
48
|
+
*
|
|
49
|
+
* Consumers who want to intercept any bin action can pass through the
|
|
50
|
+
* standard cancelable Before/After events.
|
|
51
|
+
*/
|
|
52
|
+
export class RecycleBinChipComponent {
|
|
53
|
+
cdr;
|
|
54
|
+
/**
|
|
55
|
+
* Entity name whose deleted records will be surfaced. When null/empty,
|
|
56
|
+
* the chip hides itself entirely.
|
|
57
|
+
*/
|
|
58
|
+
_entityName = null;
|
|
59
|
+
set EntityName(value) {
|
|
60
|
+
if (value !== this._entityName) {
|
|
61
|
+
this._entityName = value;
|
|
62
|
+
if (this.isInitialized)
|
|
63
|
+
this.refreshCount();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
get EntityName() {
|
|
67
|
+
return this._entityName;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Optional context user for permission checks. Falls back to
|
|
71
|
+
* `Metadata.Provider.CurrentUser` when omitted.
|
|
72
|
+
*/
|
|
73
|
+
ContextUser = null;
|
|
74
|
+
// ─── Re-emitted events from the inner panel ────────────────────
|
|
75
|
+
BeforeRecycleBinOpen = new EventEmitter();
|
|
76
|
+
AfterRecycleBinOpen = new EventEmitter();
|
|
77
|
+
BeforeRecordRestore = new EventEmitter();
|
|
78
|
+
AfterRecordRestore = new EventEmitter();
|
|
79
|
+
BeforeRestoreCommit = new EventEmitter();
|
|
80
|
+
AfterRestoreCommit = new EventEmitter();
|
|
81
|
+
// ─── Public template state ──────────────────────────────────────
|
|
82
|
+
DeletedCount = 0;
|
|
83
|
+
PanelVisible = false;
|
|
84
|
+
IsVisible = false;
|
|
85
|
+
CanDelete = false;
|
|
86
|
+
TracksChanges = false;
|
|
87
|
+
isInitialized = false;
|
|
88
|
+
constructor(cdr) {
|
|
89
|
+
this.cdr = cdr;
|
|
90
|
+
}
|
|
91
|
+
ngOnInit() {
|
|
92
|
+
this.isInitialized = true;
|
|
93
|
+
this.refreshCount();
|
|
94
|
+
}
|
|
95
|
+
Toggle() {
|
|
96
|
+
this.PanelVisible = !this.PanelVisible;
|
|
97
|
+
this.cdr.markForCheck();
|
|
98
|
+
}
|
|
99
|
+
OnPanelClosed() {
|
|
100
|
+
this.PanelVisible = false;
|
|
101
|
+
// Refresh count — a restore may have removed an entry from the bin
|
|
102
|
+
this.refreshCount();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* After-events bubble through but we also use them to refresh the count
|
|
106
|
+
* — restoring a record means it's no longer "deleted".
|
|
107
|
+
*/
|
|
108
|
+
OnAfterRecycleBinOpen(e) {
|
|
109
|
+
this.DeletedCount = e.deletedRecordCount;
|
|
110
|
+
this.AfterRecycleBinOpen.emit(e);
|
|
111
|
+
this.cdr.markForCheck();
|
|
112
|
+
}
|
|
113
|
+
OnAfterRestoreCommit(e) {
|
|
114
|
+
if (e.success)
|
|
115
|
+
this.DeletedCount = Math.max(0, this.DeletedCount - 1);
|
|
116
|
+
this.AfterRestoreCommit.emit(e);
|
|
117
|
+
this.cdr.markForCheck();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Loads the deleted-record count and visibility flags. Called on init,
|
|
121
|
+
* when EntityName changes, and after the panel closes (so a restore
|
|
122
|
+
* decrements the badge).
|
|
123
|
+
*/
|
|
124
|
+
async refreshCount() {
|
|
125
|
+
this.IsVisible = false;
|
|
126
|
+
this.DeletedCount = 0;
|
|
127
|
+
if (!this._entityName) {
|
|
128
|
+
this.cdr.markForCheck();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const md = new Metadata();
|
|
132
|
+
const entityInfo = md.Entities.find(e => e.Name.trim().toLowerCase() === this._entityName.trim().toLowerCase());
|
|
133
|
+
if (!entityInfo) {
|
|
134
|
+
this.cdr.markForCheck();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
this.TracksChanges = !!entityInfo.TrackRecordChanges;
|
|
138
|
+
if (!this.TracksChanges) {
|
|
139
|
+
this.cdr.markForCheck();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const effectiveUser = this.ContextUser ?? md.CurrentUser;
|
|
143
|
+
if (!effectiveUser) {
|
|
144
|
+
this.cdr.markForCheck();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const perms = entityInfo.GetUserPermisions(effectiveUser);
|
|
148
|
+
this.CanDelete = perms?.CanDelete ?? false;
|
|
149
|
+
if (!this.CanDelete) {
|
|
150
|
+
this.cdr.markForCheck();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Cheap count query — just IDs, capped low
|
|
154
|
+
try {
|
|
155
|
+
const rv = new RunView();
|
|
156
|
+
const result = await rv.RunView({
|
|
157
|
+
EntityName: 'MJ: Record Changes',
|
|
158
|
+
Fields: ['ID', 'RecordID'],
|
|
159
|
+
ExtraFilter: `EntityID='${entityInfo.ID}' AND Type='Delete'`,
|
|
160
|
+
OrderBy: 'ChangedAt DESC',
|
|
161
|
+
MaxRows: 500,
|
|
162
|
+
ResultType: 'simple',
|
|
163
|
+
}, this.ContextUser ?? undefined);
|
|
164
|
+
if (result.Success) {
|
|
165
|
+
// Distinct RecordIDs (a record might have been deleted, recreated, deleted again)
|
|
166
|
+
const distinct = new Set(result.Results.map(r => r.RecordID));
|
|
167
|
+
this.DeletedCount = distinct.size;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Silently ignore — chip just won't show
|
|
172
|
+
}
|
|
173
|
+
this.IsVisible = this.DeletedCount > 0;
|
|
174
|
+
this.cdr.markForCheck();
|
|
175
|
+
}
|
|
176
|
+
static ɵfac = function RecycleBinChipComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RecycleBinChipComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
177
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecycleBinChipComponent, selectors: [["mj-recycle-bin-chip"]], inputs: { EntityName: "EntityName", ContextUser: "ContextUser" }, outputs: { BeforeRecycleBinOpen: "BeforeRecycleBinOpen", AfterRecycleBinOpen: "AfterRecycleBinOpen", BeforeRecordRestore: "BeforeRecordRestore", AfterRecordRestore: "AfterRecordRestore", BeforeRestoreCommit: "BeforeRestoreCommit", AfterRestoreCommit: "AfterRestoreCommit" }, standalone: false, decls: 1, vars: 1, consts: [["type", "button", 1, "rbc-chip", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-trash-can-arrow-up"], [1, "rbc-chip-label"], [1, "rbc-chip-count"], [3, "Closed", "BeforeRecycleBinOpen", "AfterRecycleBinOpen", "BeforeRecordRestore", "AfterRecordRestore", "BeforeRestoreCommit", "AfterRestoreCommit", "Visible", "EntityName", "ContextUser"]], template: function RecycleBinChipComponent_Template(rf, ctx) { if (rf & 1) {
|
|
178
|
+
i0.ɵɵconditionalCreate(0, RecycleBinChipComponent_Conditional_0_Template, 7, 5);
|
|
179
|
+
} if (rf & 2) {
|
|
180
|
+
i0.ɵɵconditional(ctx.IsVisible ? 0 : -1);
|
|
181
|
+
} }, dependencies: [i1.RecycleBinComponent], styles: ["\n .rbc-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 11px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 25%, var(--mj-border-default));\n cursor: pointer;\n font-family: inherit;\n transition: background-color 0.1s, border-color 0.1s;\n }\n .rbc-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n border-color: var(--mj-status-info);\n }\n .rbc-chip-label {\n /* always show on wider screens; hide on narrow if needed */\n }\n .rbc-chip-count {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-radius: 10px;\n padding: 1px 7px;\n font-size: 10px;\n font-weight: 700;\n }\n "], encapsulation: 2, changeDetection: 0 });
|
|
182
|
+
}
|
|
183
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecycleBinChipComponent, [{
|
|
184
|
+
type: Component,
|
|
185
|
+
args: [{ standalone: false, selector: 'mj-recycle-bin-chip', template: `
|
|
186
|
+
@if (IsVisible) {
|
|
187
|
+
<button class="rbc-chip"
|
|
188
|
+
type="button"
|
|
189
|
+
(click)="Toggle()"
|
|
190
|
+
[attr.title]="'Recycle Bin · ' + DeletedCount + ' deleted record' + (DeletedCount === 1 ? '' : 's')">
|
|
191
|
+
<i class="fa-solid fa-trash-can-arrow-up" aria-hidden="true"></i>
|
|
192
|
+
<span class="rbc-chip-label">Recycle Bin</span>
|
|
193
|
+
<span class="rbc-chip-count">{{ DeletedCount }}</span>
|
|
194
|
+
</button>
|
|
195
|
+
|
|
196
|
+
<mj-recycle-bin
|
|
197
|
+
[Visible]="PanelVisible"
|
|
198
|
+
[EntityName]="EntityName"
|
|
199
|
+
[ContextUser]="ContextUser"
|
|
200
|
+
(Closed)="OnPanelClosed()"
|
|
201
|
+
(BeforeRecycleBinOpen)="BeforeRecycleBinOpen.emit($event)"
|
|
202
|
+
(AfterRecycleBinOpen)="OnAfterRecycleBinOpen($event)"
|
|
203
|
+
(BeforeRecordRestore)="BeforeRecordRestore.emit($event)"
|
|
204
|
+
(AfterRecordRestore)="AfterRecordRestore.emit($event)"
|
|
205
|
+
(BeforeRestoreCommit)="BeforeRestoreCommit.emit($event)"
|
|
206
|
+
(AfterRestoreCommit)="OnAfterRestoreCommit($event)">
|
|
207
|
+
</mj-recycle-bin>
|
|
208
|
+
}
|
|
209
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, styles: ["\n .rbc-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 11px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 25%, var(--mj-border-default));\n cursor: pointer;\n font-family: inherit;\n transition: background-color 0.1s, border-color 0.1s;\n }\n .rbc-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n border-color: var(--mj-status-info);\n }\n .rbc-chip-label {\n /* always show on wider screens; hide on narrow if needed */\n }\n .rbc-chip-count {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-radius: 10px;\n padding: 1px 7px;\n font-size: 10px;\n font-weight: 700;\n }\n "] }]
|
|
210
|
+
}], () => [{ type: i0.ChangeDetectorRef }], { EntityName: [{
|
|
211
|
+
type: Input
|
|
212
|
+
}], ContextUser: [{
|
|
213
|
+
type: Input
|
|
214
|
+
}], BeforeRecycleBinOpen: [{
|
|
215
|
+
type: Output
|
|
216
|
+
}], AfterRecycleBinOpen: [{
|
|
217
|
+
type: Output
|
|
218
|
+
}], BeforeRecordRestore: [{
|
|
219
|
+
type: Output
|
|
220
|
+
}], AfterRecordRestore: [{
|
|
221
|
+
type: Output
|
|
222
|
+
}], BeforeRestoreCommit: [{
|
|
223
|
+
type: Output
|
|
224
|
+
}], AfterRestoreCommit: [{
|
|
225
|
+
type: Output
|
|
226
|
+
}] }); })();
|
|
227
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RecycleBinChipComponent, { className: "RecycleBinChipComponent", filePath: "src/lib/recycle-bin/recycle-bin-chip.component.ts", lineNumber: 109 }); })();
|
|
228
|
+
//# sourceMappingURL=recycle-bin-chip.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recycle-bin-chip.component.js","sourceRoot":"","sources":["../../../src/lib/recycle-bin/recycle-bin-chip.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n EventEmitter,\n Input,\n OnInit,\n Output,\n ViewEncapsulation,\n} from '@angular/core';\nimport { Metadata, RunView, UserInfo } from '@memberjunction/core';\nimport {\n AfterRecordRestoreEventArgs,\n AfterRecycleBinOpenEventArgs,\n AfterRestoreCommitEventArgs,\n BeforeRecordRestoreEventArgs,\n BeforeRecycleBinOpenEventArgs,\n BeforeRestoreCommitEventArgs,\n} from './events/recycle-bin-events';\n\n/**\n * Tiny composite that renders a Recycle Bin **chip button** (with live\n * deleted-record count badge) and hosts the {@link RecycleBinComponent}\n * slide-in panel that opens when clicked.\n *\n * Designed to be dropped into any toolbar in three lines:\n *\n * @example\n * <mj-recycle-bin-chip\n * *ngIf=\"ShowRecycleBin\"\n * [EntityName]=\"effectiveEntity?.Name\">\n * </mj-recycle-bin-chip>\n *\n * The chip auto-hides itself when:\n * - No `EntityName` is provided\n * - The entity has `TrackRecordChanges = false`\n * - The user lacks `CanDelete` permission on the entity\n * - The deleted-record count is zero\n *\n * Each of those is the right behavior to avoid cluttering toolbars on\n * entities where the bin is irrelevant.\n *\n * Consumers who want to intercept any bin action can pass through the\n * standard cancelable Before/After events.\n */\n@Component({\n standalone: false,\n selector: 'mj-recycle-bin-chip',\n template: `\n @if (IsVisible) {\n <button class=\"rbc-chip\"\n type=\"button\"\n (click)=\"Toggle()\"\n [attr.title]=\"'Recycle Bin · ' + DeletedCount + ' deleted record' + (DeletedCount === 1 ? '' : 's')\">\n <i class=\"fa-solid fa-trash-can-arrow-up\" aria-hidden=\"true\"></i>\n <span class=\"rbc-chip-label\">Recycle Bin</span>\n <span class=\"rbc-chip-count\">{{ DeletedCount }}</span>\n </button>\n\n <mj-recycle-bin\n [Visible]=\"PanelVisible\"\n [EntityName]=\"EntityName\"\n [ContextUser]=\"ContextUser\"\n (Closed)=\"OnPanelClosed()\"\n (BeforeRecycleBinOpen)=\"BeforeRecycleBinOpen.emit($event)\"\n (AfterRecycleBinOpen)=\"OnAfterRecycleBinOpen($event)\"\n (BeforeRecordRestore)=\"BeforeRecordRestore.emit($event)\"\n (AfterRecordRestore)=\"AfterRecordRestore.emit($event)\"\n (BeforeRestoreCommit)=\"BeforeRestoreCommit.emit($event)\"\n (AfterRestoreCommit)=\"OnAfterRestoreCommit($event)\">\n </mj-recycle-bin>\n }\n `,\n styles: [`\n .rbc-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 11px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 25%, var(--mj-border-default));\n cursor: pointer;\n font-family: inherit;\n transition: background-color 0.1s, border-color 0.1s;\n }\n .rbc-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n border-color: var(--mj-status-info);\n }\n .rbc-chip-label {\n /* always show on wider screens; hide on narrow if needed */\n }\n .rbc-chip-count {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-radius: 10px;\n padding: 1px 7px;\n font-size: 10px;\n font-weight: 700;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class RecycleBinChipComponent implements OnInit {\n /**\n * Entity name whose deleted records will be surfaced. When null/empty,\n * the chip hides itself entirely.\n */\n private _entityName: string | null = null;\n @Input()\n set EntityName(value: string | null) {\n if (value !== this._entityName) {\n this._entityName = value;\n if (this.isInitialized) this.refreshCount();\n }\n }\n get EntityName(): string | null {\n return this._entityName;\n }\n\n /**\n * Optional context user for permission checks. Falls back to\n * `Metadata.Provider.CurrentUser` when omitted.\n */\n @Input() ContextUser: UserInfo | null = null;\n\n // ─── Re-emitted events from the inner panel ────────────────────\n\n @Output() BeforeRecycleBinOpen = new EventEmitter<BeforeRecycleBinOpenEventArgs>();\n @Output() AfterRecycleBinOpen = new EventEmitter<AfterRecycleBinOpenEventArgs>();\n @Output() BeforeRecordRestore = new EventEmitter<BeforeRecordRestoreEventArgs>();\n @Output() AfterRecordRestore = new EventEmitter<AfterRecordRestoreEventArgs>();\n @Output() BeforeRestoreCommit = new EventEmitter<BeforeRestoreCommitEventArgs>();\n @Output() AfterRestoreCommit = new EventEmitter<AfterRestoreCommitEventArgs>();\n\n // ─── Public template state ──────────────────────────────────────\n\n public DeletedCount = 0;\n public PanelVisible = false;\n public IsVisible = false;\n public CanDelete = false;\n public TracksChanges = false;\n\n private isInitialized = false;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n this.isInitialized = true;\n this.refreshCount();\n }\n\n public Toggle(): void {\n this.PanelVisible = !this.PanelVisible;\n this.cdr.markForCheck();\n }\n\n public OnPanelClosed(): void {\n this.PanelVisible = false;\n // Refresh count — a restore may have removed an entry from the bin\n this.refreshCount();\n }\n\n /**\n * After-events bubble through but we also use them to refresh the count\n * — restoring a record means it's no longer \"deleted\".\n */\n public OnAfterRecycleBinOpen(e: AfterRecycleBinOpenEventArgs): void {\n this.DeletedCount = e.deletedRecordCount;\n this.AfterRecycleBinOpen.emit(e);\n this.cdr.markForCheck();\n }\n\n public OnAfterRestoreCommit(e: AfterRestoreCommitEventArgs): void {\n if (e.success) this.DeletedCount = Math.max(0, this.DeletedCount - 1);\n this.AfterRestoreCommit.emit(e);\n this.cdr.markForCheck();\n }\n\n /**\n * Loads the deleted-record count and visibility flags. Called on init,\n * when EntityName changes, and after the panel closes (so a restore\n * decrements the badge).\n */\n private async refreshCount(): Promise<void> {\n this.IsVisible = false;\n this.DeletedCount = 0;\n\n if (!this._entityName) {\n this.cdr.markForCheck();\n return;\n }\n\n const md = new Metadata();\n const entityInfo = md.Entities.find(\n e => e.Name.trim().toLowerCase() === this._entityName!.trim().toLowerCase(),\n );\n if (!entityInfo) {\n this.cdr.markForCheck();\n return;\n }\n\n this.TracksChanges = !!entityInfo.TrackRecordChanges;\n if (!this.TracksChanges) {\n this.cdr.markForCheck();\n return;\n }\n\n const effectiveUser = this.ContextUser ?? md.CurrentUser;\n if (!effectiveUser) {\n this.cdr.markForCheck();\n return;\n }\n const perms = entityInfo.GetUserPermisions(effectiveUser);\n this.CanDelete = perms?.CanDelete ?? false;\n if (!this.CanDelete) {\n this.cdr.markForCheck();\n return;\n }\n\n // Cheap count query — just IDs, capped low\n try {\n const rv = new RunView();\n const result = await rv.RunView<{ ID: string; RecordID: string }>({\n EntityName: 'MJ: Record Changes',\n Fields: ['ID', 'RecordID'],\n ExtraFilter: `EntityID='${entityInfo.ID}' AND Type='Delete'`,\n OrderBy: 'ChangedAt DESC',\n MaxRows: 500,\n ResultType: 'simple',\n }, this.ContextUser ?? undefined);\n\n if (result.Success) {\n // Distinct RecordIDs (a record might have been deleted, recreated, deleted again)\n const distinct = new Set(result.Results.map(r => r.RecordID));\n this.DeletedCount = distinct.size;\n }\n } catch {\n // Silently ignore — chip just won't show\n }\n\n this.IsVisible = this.DeletedCount > 0;\n this.cdr.markForCheck();\n }\n}\n"]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { ChangeDetectorRef, EventEmitter, OnInit } from '@angular/core';
|
|
2
|
+
import { UserInfo } from '@memberjunction/core';
|
|
3
|
+
import { RestoreCommitEvent } from '@memberjunction/ng-record-changes';
|
|
4
|
+
import { AfterRecordRestoreEventArgs, AfterRecycleBinOpenEventArgs, AfterRestoreCommitEventArgs, BeforeRecordRestoreEventArgs, BeforeRecycleBinOpenEventArgs, BeforeRestoreCommitEventArgs, RecycleBinEntry } from './events/recycle-bin-events';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* Slide-in panel that lists all hard-deleted records for a single entity
|
|
8
|
+
* and lets a user with `Delete` permission re-create any of them from its
|
|
9
|
+
* historical RecordChange snapshot.
|
|
10
|
+
*
|
|
11
|
+
* ### When to use
|
|
12
|
+
*
|
|
13
|
+
* Surface this component from any entity-viewing context where the user
|
|
14
|
+
* might need to restore a hard-deleted record. The {@link EntityViewerComponent},
|
|
15
|
+
* {@link EntityDataGridComponent}, and {@link EntityCardsComponent}
|
|
16
|
+
* already expose a `ShowRecycleBin` input (default `true`) that renders a
|
|
17
|
+
* chip in their toolbar — you only need to use this component directly if
|
|
18
|
+
* you're building a custom viewer.
|
|
19
|
+
*
|
|
20
|
+
* ### Permissions
|
|
21
|
+
*
|
|
22
|
+
* The chip / panel is gated on `entity.UserPermissions.CanDelete` —
|
|
23
|
+
* rationale: there is no native "undelete" permission in MemberJunction,
|
|
24
|
+
* but if a user has the higher-trust permission to *delete* records of an
|
|
25
|
+
* entity, restoring deleted ones is well within scope. The actual
|
|
26
|
+
* re-create action additionally requires `CanCreate`; without it the
|
|
27
|
+
* Restore button on each card disables with a tooltip.
|
|
28
|
+
*
|
|
29
|
+
* ### Soft deletes vs hard deletes
|
|
30
|
+
*
|
|
31
|
+
* This component only surfaces *hard*-deleted records. Soft-deletes (e.g.,
|
|
32
|
+
* `IsDeleted` flags, `Status='Inactive'`, etc.) leave the record visible
|
|
33
|
+
* in normal entity views, so the standard Record Changes panel + restore
|
|
34
|
+
* preview already handles them — no Recycle Bin needed.
|
|
35
|
+
*
|
|
36
|
+
* ### Cancelable Before/After event surface
|
|
37
|
+
*
|
|
38
|
+
* Every meaningful action emits a paired `before*` / `after*` event. The
|
|
39
|
+
* `before*` event carries `cancel: boolean` so consumers can intercept
|
|
40
|
+
* — useful for custom approval workflows, audit logging, or to take over
|
|
41
|
+
* the actual restore execution entirely. See {@link BeforeRecordRestoreEventArgs}
|
|
42
|
+
* and friends.
|
|
43
|
+
*
|
|
44
|
+
* @example Basic usage (rare — usually embedded by entity-viewer)
|
|
45
|
+
* <mj-recycle-bin
|
|
46
|
+
* [Visible]="showBin"
|
|
47
|
+
* [EntityName]="'Customers'"
|
|
48
|
+
* (Closed)="showBin = false"
|
|
49
|
+
* (BeforeRecordRestore)="auditRestore($event)"
|
|
50
|
+
* (AfterRestoreCommit)="onRestored($event)">
|
|
51
|
+
* </mj-recycle-bin>
|
|
52
|
+
*
|
|
53
|
+
* @example Intercepting a restore
|
|
54
|
+
* onBeforeRecordRestore(e: BeforeRecordRestoreEventArgs) {
|
|
55
|
+
* if (!myCustomApproval(e.entry)) {
|
|
56
|
+
* e.cancel = true;
|
|
57
|
+
* e.cancelReason = 'Awaiting compliance approval';
|
|
58
|
+
* }
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
export declare class RecycleBinComponent implements OnInit {
|
|
62
|
+
private cdr;
|
|
63
|
+
/**
|
|
64
|
+
* Controls panel visibility. Set to true to slide in (and trigger an
|
|
65
|
+
* initial load); false to slide out.
|
|
66
|
+
*/
|
|
67
|
+
private _visible;
|
|
68
|
+
set Visible(value: boolean);
|
|
69
|
+
get Visible(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The name of the entity whose deleted records will be listed. Required.
|
|
72
|
+
*/
|
|
73
|
+
EntityName: string | null;
|
|
74
|
+
/**
|
|
75
|
+
* Optional context user. When omitted, falls back to
|
|
76
|
+
* {@link Metadata.Provider.CurrentUser} per standard MJ conventions.
|
|
77
|
+
*/
|
|
78
|
+
ContextUser: UserInfo | null;
|
|
79
|
+
/**
|
|
80
|
+
* Maximum number of deleted-record cards to load. Defaults to 200 — this
|
|
81
|
+
* is a UI affordance, not a hard limit; consumers needing pagination
|
|
82
|
+
* should listen to {@link AfterRecycleBinOpen} and surface their own UI
|
|
83
|
+
* if `deletedRecordCount === MaxRecords`.
|
|
84
|
+
*/
|
|
85
|
+
MaxRecords: number;
|
|
86
|
+
/** Fires when the user closes the panel. */
|
|
87
|
+
Closed: EventEmitter<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Cancelable. Fires when {@link Visible} flips to true and the bin is
|
|
90
|
+
* about to query for deleted records. Setting `cancel = true` aborts
|
|
91
|
+
* the query (and the panel will show the empty state).
|
|
92
|
+
*/
|
|
93
|
+
BeforeRecycleBinOpen: EventEmitter<BeforeRecycleBinOpenEventArgs>;
|
|
94
|
+
/** Fires after the deleted-record query completes. */
|
|
95
|
+
AfterRecycleBinOpen: EventEmitter<AfterRecycleBinOpenEventArgs>;
|
|
96
|
+
/**
|
|
97
|
+
* Cancelable. Fires when the user clicks Restore on a deleted-record
|
|
98
|
+
* card, before the preview panel opens. Setting `cancel = true` skips
|
|
99
|
+
* the preview entirely — useful for consumers that want to take over
|
|
100
|
+
* the restore flow themselves.
|
|
101
|
+
*/
|
|
102
|
+
BeforeRecordRestore: EventEmitter<BeforeRecordRestoreEventArgs>;
|
|
103
|
+
/**
|
|
104
|
+
* Fires after the user closes the restore preview, with `success`
|
|
105
|
+
* indicating whether the actual insert worked.
|
|
106
|
+
*/
|
|
107
|
+
AfterRecordRestore: EventEmitter<AfterRecordRestoreEventArgs>;
|
|
108
|
+
/**
|
|
109
|
+
* Cancelable. Fires after the user clicks Restore in the preview but
|
|
110
|
+
* before the entity is inserted. Setting `cancel = true` aborts the
|
|
111
|
+
* insert.
|
|
112
|
+
*/
|
|
113
|
+
BeforeRestoreCommit: EventEmitter<BeforeRestoreCommitEventArgs>;
|
|
114
|
+
/** Fires after the insert completes (success or failure). */
|
|
115
|
+
AfterRestoreCommit: EventEmitter<AfterRestoreCommitEventArgs>;
|
|
116
|
+
IsLoading: boolean;
|
|
117
|
+
LoadError: string | null;
|
|
118
|
+
Entries: RecycleBinEntry[];
|
|
119
|
+
/** The currently selected entry whose preview is open. */
|
|
120
|
+
SelectedEntry: RecycleBinEntry | null;
|
|
121
|
+
PreviewVisible: boolean;
|
|
122
|
+
/** Permission flags (computed once when EntityName is set). */
|
|
123
|
+
CanDelete: boolean;
|
|
124
|
+
CanCreate: boolean;
|
|
125
|
+
private isInitialized;
|
|
126
|
+
private resolvedEntityInfo;
|
|
127
|
+
constructor(cdr: ChangeDetectorRef);
|
|
128
|
+
ngOnInit(): void;
|
|
129
|
+
get HeaderSubtitle(): string;
|
|
130
|
+
/**
|
|
131
|
+
* The user has Delete permission and may browse the bin. The Restore
|
|
132
|
+
* button on each card additionally requires {@link CanCreate}.
|
|
133
|
+
*/
|
|
134
|
+
get HasAccess(): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Manually trigger a re-load — useful for consumers who want to refresh
|
|
137
|
+
* after some external event (e.g., a delete happened and they want the
|
|
138
|
+
* bin to re-populate immediately).
|
|
139
|
+
*/
|
|
140
|
+
LoadDeletedRecords(): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* User clicked Restore on a card — open the preview panel (unless a
|
|
143
|
+
* BeforeRecordRestore handler cancelled).
|
|
144
|
+
*/
|
|
145
|
+
OnRestoreClicked(entry: RecycleBinEntry): void;
|
|
146
|
+
/**
|
|
147
|
+
* Preview panel emitted RestoreConfirmed — perform the insert and emit
|
|
148
|
+
* the matching after* events.
|
|
149
|
+
*/
|
|
150
|
+
OnPreviewConfirmed(commit: RestoreCommitEvent): Promise<void>;
|
|
151
|
+
OnPreviewCancelled(): void;
|
|
152
|
+
OnClose(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Dedupes the raw delete-change rows: keeps only the most recent Delete
|
|
155
|
+
* per RecordID (since a record could in principle have been recreated
|
|
156
|
+
* and re-deleted). Builds the display fields heuristically by reading
|
|
157
|
+
* the snapshot JSON.
|
|
158
|
+
*/
|
|
159
|
+
private dedupeAndBuildEntries;
|
|
160
|
+
/**
|
|
161
|
+
* Builds the headline of the card. Prefers the entity's name field, then
|
|
162
|
+
* any non-PK string field, then the RecordID itself as a last resort.
|
|
163
|
+
*/
|
|
164
|
+
private buildDisplaySummary;
|
|
165
|
+
/**
|
|
166
|
+
* Picks up to 3 "interesting" fields from the snapshot to render as
|
|
167
|
+
* supporting metadata under the headline. Heuristic: prefer fields that
|
|
168
|
+
* are non-empty, non-PK, non-system, and have a display name.
|
|
169
|
+
*/
|
|
170
|
+
private buildSupportingFields;
|
|
171
|
+
private formatFieldValue;
|
|
172
|
+
private parseSnapshot;
|
|
173
|
+
formatTimestamp(date: Date | string | null): string;
|
|
174
|
+
getUserDisplay(user: string | null): string;
|
|
175
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RecycleBinComponent, never>;
|
|
176
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RecycleBinComponent, "mj-recycle-bin", never, { "Visible": { "alias": "Visible"; "required": false; }; "EntityName": { "alias": "EntityName"; "required": false; }; "ContextUser": { "alias": "ContextUser"; "required": false; }; "MaxRecords": { "alias": "MaxRecords"; "required": false; }; }, { "Closed": "Closed"; "BeforeRecycleBinOpen": "BeforeRecycleBinOpen"; "AfterRecycleBinOpen": "AfterRecycleBinOpen"; "BeforeRecordRestore": "BeforeRecordRestore"; "AfterRecordRestore": "AfterRecordRestore"; "BeforeRestoreCommit": "BeforeRestoreCommit"; "AfterRestoreCommit": "AfterRestoreCommit"; }, never, never, false, never>;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=recycle-bin.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recycle-bin.component.d.ts","sourceRoot":"","sources":["../../../src/lib/recycle-bin/recycle-bin.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EACjB,YAAY,EAEZ,MAAM,EAGP,MAAM,eAAe,CAAC;AACvB,OAAO,EAKL,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,eAAe,EAChB,MAAM,6BAA6B,CAAC;;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,qBAQa,mBAAoB,YAAW,MAAM;IA+FpC,OAAO,CAAC,GAAG;IA5FvB;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAS;IACzB,IACI,OAAO,CAAC,KAAK,EAAE,OAAO,EAMzB;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACM,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;OAGG;IACM,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE7C;;;;;OAKG;IACM,UAAU,SAAO;IAI1B,4CAA4C;IAClC,MAAM,qBAA4B;IAE5C;;;;OAIG;IACO,oBAAoB,8CAAqD;IAEnF,sDAAsD;IAC5C,mBAAmB,6CAAoD;IAEjF;;;;;OAKG;IACO,mBAAmB,6CAAoD;IAEjF;;;OAGG;IACO,kBAAkB,4CAAmD;IAE/E;;;;OAIG;IACO,mBAAmB,6CAAoD;IAEjF,6DAA6D;IACnD,kBAAkB,4CAAmD;IAIxE,SAAS,UAAS;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,OAAO,EAAE,eAAe,EAAE,CAAM;IAEvC,0DAA0D;IACnD,aAAa,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC7C,cAAc,UAAS;IAE9B,+DAA+D;IACxD,SAAS,UAAS;IAClB,SAAS,UAAS;IAEzB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,kBAAkB,CAA2B;gBAEjC,GAAG,EAAE,iBAAiB;IAE1C,QAAQ,IAAI,IAAI;IAOhB,IAAW,cAAc,IAAI,MAAM,CAIlC;IAED;;;OAGG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAID;;;;OAIG;IACU,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA4FhD;;;OAGG;IACI,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAmBrD;;;OAGG;IACU,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+FnE,kBAAkB,IAAI,IAAI;IAM1B,OAAO,IAAI,IAAI;IAQtB;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAyB7B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;IAWd,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM;IAYnD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;yCArdvC,mBAAmB;2CAAnB,mBAAmB;CA0d/B"}
|