@memberjunction/ng-record-clone 0.0.1-seed.1 → 6.2.0-edge.2
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/LICENSE +183 -0
- package/README.md +241 -3
- package/dist/lib/clone-lineage-chip.component.d.ts +50 -0
- package/dist/lib/clone-lineage-chip.component.d.ts.map +1 -0
- package/dist/lib/clone-lineage-chip.component.js +448 -0
- package/dist/lib/clone-lineage-chip.component.js.map +1 -0
- package/dist/lib/clone-plan-tree.component.d.ts +51 -0
- package/dist/lib/clone-plan-tree.component.d.ts.map +1 -0
- package/dist/lib/clone-plan-tree.component.js +634 -0
- package/dist/lib/clone-plan-tree.component.js.map +1 -0
- package/dist/lib/clone-progress.component.d.ts +12 -0
- package/dist/lib/clone-progress.component.d.ts.map +1 -0
- package/dist/lib/clone-progress.component.js +151 -0
- package/dist/lib/clone-progress.component.js.map +1 -0
- package/dist/lib/clone-result.component.d.ts +40 -0
- package/dist/lib/clone-result.component.d.ts.map +1 -0
- package/dist/lib/clone-result.component.js +357 -0
- package/dist/lib/clone-result.component.js.map +1 -0
- package/dist/lib/clone-review.component.d.ts +58 -0
- package/dist/lib/clone-review.component.d.ts.map +1 -0
- package/dist/lib/clone-review.component.js +581 -0
- package/dist/lib/clone-review.component.js.map +1 -0
- package/dist/lib/clone-scope-controls.component.d.ts +81 -0
- package/dist/lib/clone-scope-controls.component.d.ts.map +1 -0
- package/dist/lib/clone-scope-controls.component.js +394 -0
- package/dist/lib/clone-scope-controls.component.js.map +1 -0
- package/dist/lib/clone-values.component.d.ts +55 -0
- package/dist/lib/clone-values.component.d.ts.map +1 -0
- package/dist/lib/clone-values.component.js +493 -0
- package/dist/lib/clone-values.component.js.map +1 -0
- package/dist/lib/record-clone-panel.component.d.ts +247 -0
- package/dist/lib/record-clone-panel.component.d.ts.map +1 -0
- package/dist/lib/record-clone-panel.component.js +1252 -0
- package/dist/lib/record-clone-panel.component.js.map +1 -0
- package/dist/lib/record-clone-slide-in.component.d.ts +83 -0
- package/dist/lib/record-clone-slide-in.component.d.ts.map +1 -0
- package/dist/lib/record-clone-slide-in.component.js +206 -0
- package/dist/lib/record-clone-slide-in.component.js.map +1 -0
- package/dist/lib/record-clone-types.d.ts +89 -0
- package/dist/lib/record-clone-types.d.ts.map +1 -0
- package/dist/lib/record-clone-types.js +29 -0
- package/dist/lib/record-clone-types.js.map +1 -0
- package/dist/lib/record-clone.module.d.ts +16 -0
- package/dist/lib/record-clone.module.d.ts.map +1 -0
- package/dist/lib/record-clone.module.js +69 -0
- package/dist/lib/record-clone.module.js.map +1 -0
- package/dist/lib/record-clone.service.d.ts +42 -0
- package/dist/lib/record-clone.service.d.ts.map +1 -0
- package/dist/lib/record-clone.service.js +123 -0
- package/dist/lib/record-clone.service.js.map +1 -0
- package/dist/public-api.d.ts +16 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +16 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +47 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-review.component.js","sourceRoot":"","sources":["../../src/lib/clone-review.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Review and preflight execution component for record cloning.\n *\n * Implements §12.3 & §12.4 of the Record Cloning architectural blueprint. Displays\n * stat badges (Create / Reference / Skip / Warnings), blocked alert banner with reasons,\n * warnings grouped by severity linking to nodes, field-change diffs, and confirmation actions.\n */\n\nimport {\n Component,\n ChangeDetectionStrategy,\n Input,\n Output,\n EventEmitter,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n MJButtonDirective,\n MJStatBadgeComponent,\n} from '@memberjunction/ng-ui-components';\nimport type {\n RecordClonePlanDetails,\n RecordClonePlanNode,\n RecordClonePlanWarning,\n RecordClonePlanFieldChange,\n} from '@memberjunction/core-entities';\n\ninterface NodeFieldChangesSummary {\n Node: RecordClonePlanNode;\n Changes: RecordClonePlanFieldChange[];\n}\n\n@Component({\n standalone: true,\n selector: 'mj-clone-review',\n template: `\n <div class=\"clone-review-container\">\n <!-- Stat Badges Row -->\n <div class=\"stat-badges-row\">\n <mj-stat-badge\n [Count]=\"CreateCount\"\n Label=\"to create\"\n Variant=\"success\"\n Icon=\"fa-solid fa-plus\">\n </mj-stat-badge>\n\n @if (ReferenceCount > 0) {\n <mj-stat-badge\n [Count]=\"ReferenceCount\"\n Label=\"referenced\"\n Variant=\"info\"\n Icon=\"fa-solid fa-link\">\n </mj-stat-badge>\n }\n\n @if (SkipCount > 0) {\n <mj-stat-badge\n [Count]=\"SkipCount\"\n Label=\"skipped\"\n Variant=\"default\"\n Icon=\"fa-solid fa-forward\">\n </mj-stat-badge>\n }\n\n @if (TotalWarningsCount > 0) {\n <mj-stat-badge\n [Count]=\"TotalWarningsCount\"\n Label=\"warnings\"\n Variant=\"warning\"\n Icon=\"fa-solid fa-triangle-exclamation\">\n </mj-stat-badge>\n }\n\n @if (IsBlocked) {\n <mj-stat-badge\n Label=\"BLOCKED\"\n Variant=\"error\"\n Icon=\"fa-solid fa-ban\">\n </mj-stat-badge>\n }\n </div>\n\n <!-- Blocked Banner -->\n @if (IsBlocked) {\n <div class=\"blocked-banner\" role=\"alert\">\n <div class=\"blocked-banner-header\">\n <i class=\"fa-solid fa-circle-exclamation blocked-icon\"></i>\n <span class=\"blocked-title\">Cloning Cannot Proceed</span>\n </div>\n <p class=\"blocked-description\">\n One or more constraints or validation rules prevent this record graph from being cloned:\n </p>\n <ul class=\"blocked-reasons-list\">\n @for (warning of BlockingErrors; track warning.Code + (warning.NodeKey || '') + $index) {\n <li>\n <strong>{{warning.Code}}:</strong> {{warning.Message}}\n @if (warning.NodeKey) {\n <button\n type=\"button\"\n class=\"node-link-btn\"\n (click)=\"OnNodeClick(warning.NodeKey)\">\n [{{warning.NodeKey}}]\n </button>\n }\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Warnings Breakdown -->\n @if (NonBlockingWarnings.length > 0) {\n <div class=\"review-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-triangle-exclamation warning-icon\"></i>\n Warnings & Considerations ({{NonBlockingWarnings.length}})\n </h4>\n <div class=\"warnings-list\">\n @for (warn of NonBlockingWarnings; track warn.Code + (warn.NodeKey || '')) {\n <div class=\"warning-item\" [class.warning-amber]=\"warn.Severity === 'Warning'\">\n <span class=\"warning-badge\">{{warn.Severity}}</span>\n <span class=\"warning-message\">{{warn.Message}}</span>\n @if (warn.NodeKey) {\n <button\n type=\"button\"\n class=\"node-link-btn\"\n (click)=\"OnNodeClick(warn.NodeKey)\">\n [{{warn.NodeKey}}]\n </button>\n }\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Field Changes Diff Section -->\n @if (NodesWithFieldChanges.length > 0) {\n <div class=\"review-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-code-compare diff-icon\"></i>\n Field Value Modifications ({{TotalFieldChangesCount}})\n </h4>\n <p class=\"section-description\">\n Values the clone sets instead of copying (configured rules, names, remapped references and your entries):\n </p>\n\n <div class=\"diff-nodes-list\">\n @for (summary of NodesWithFieldChanges; track summary.Node.Key) {\n <div class=\"diff-node-card\">\n <div class=\"diff-node-header\">\n <span class=\"diff-entity-badge\">{{summary.Node.EntityName}}</span>\n <span class=\"diff-node-title\">{{summary.Node.DisplayName}}</span>\n <button\n type=\"button\"\n class=\"node-link-btn\"\n (click)=\"OnNodeClick(summary.Node.Key)\">\n [{{summary.Node.Key}}]\n </button>\n </div>\n <div class=\"diff-table\">\n @for (change of summary.Changes; track change.Field) {\n <div class=\"diff-row\">\n <span class=\"diff-field-name\">{{change.Field}}</span>\n <span class=\"diff-kind-chip\" [title]=\"change.Kind\">\n {{FormatChangeKind(change.Kind)}}\n </span>\n <div class=\"diff-values\">\n <span class=\"diff-old-val\" [title]=\"'Previous: ' + change.OldValue\">\n {{FormatDiffValue(change.OldValue)}}\n </span>\n <i class=\"fa-solid fa-arrow-right diff-arrow\"></i>\n <span class=\"diff-new-val\" [title]=\"'New: ' + change.NewValue\">\n {{FormatDiffValue(change.NewValue)}}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Execution Actions Bar -->\n <div class=\"actions-bar\">\n <button\n type=\"button\"\n mjButton\n variant=\"primary\"\n [disabled]=\"IsBlocked || IsExecuting || IsPlanning\"\n (click)=\"OnConfirm()\">\n @if (IsExecuting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Cloning...\n } @else if (IsPlanning) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Updating plan...\n } @else {\n <i class=\"fa-solid fa-clone\"></i>\n Execute Clone ({{CreateCount}} Records)\n }\n </button>\n\n <button\n type=\"button\"\n mjButton\n variant=\"outline\"\n [disabled]=\"IsExecuting\"\n (click)=\"OnCancel()\">\n Cancel\n </button>\n </div>\n </div>\n `,\n styles: [`\n .clone-review-container {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-1) 0;\n }\n\n .stat-badges-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) 0;\n }\n\n .blocked-banner {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n padding: var(--mj-space-3) var(--mj-space-4);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n border-radius: var(--mj-radius-md);\n color: var(--mj-status-error-text);\n }\n\n .blocked-banner-header {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n }\n\n .blocked-icon {\n font-size: var(--mj-text-base);\n color: var(--mj-status-error-text);\n }\n\n .blocked-title {\n font-size: var(--mj-text-sm);\n font-weight: 700;\n }\n\n .blocked-description {\n margin: 0;\n font-size: var(--mj-text-xs);\n }\n\n .blocked-reasons-list {\n margin: 0;\n padding-left: 20px;\n font-size: var(--mj-text-xs);\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .review-section {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n }\n\n .section-title {\n margin: 0;\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: var(--mj-text-sm);\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .section-description {\n margin: 0;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n }\n\n .warning-icon {\n color: var(--mj-status-warning-text);\n }\n\n .diff-icon {\n color: var(--mj-brand-primary);\n }\n\n .warnings-list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n }\n\n .warning-item {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: 6px 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n font-size: var(--mj-text-xs);\n }\n\n .warning-badge {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n padding: 1px 6px;\n border-radius: 8px;\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n }\n\n .warning-message {\n flex: 1;\n color: var(--mj-text-primary);\n }\n\n .node-link-btn {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n padding: 0 4px;\n font-size: 11px;\n text-decoration: underline;\n }\n\n .node-link-btn:hover {\n color: var(--mj-brand-primary-hover);\n }\n\n .diff-nodes-list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n }\n\n .diff-node-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n overflow: hidden;\n }\n\n .diff-node-header {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n padding: 6px 10px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n }\n\n .diff-entity-badge {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 1px 5px;\n border-radius: 3px;\n }\n\n .diff-node-title {\n font-size: var(--mj-text-xs);\n font-weight: 500;\n color: var(--mj-text-primary);\n flex: 1;\n }\n\n .diff-table {\n display: flex;\n flex-direction: column;\n }\n\n .diff-row {\n display: flex;\n align-items: center;\n gap: var(--mj-space-3);\n padding: 6px 10px;\n border-bottom: 1px solid var(--mj-border-default);\n font-size: var(--mj-text-xs);\n }\n\n .diff-row:last-child {\n border-bottom: none;\n }\n\n .diff-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n min-width: 120px;\n }\n\n .diff-kind-chip {\n font-size: 10px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n padding: 1px 6px;\n border-radius: 10px;\n text-transform: capitalize;\n }\n\n .diff-values {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n overflow: hidden;\n }\n\n .diff-old-val {\n color: var(--mj-status-error-text);\n text-decoration: line-through;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 140px;\n }\n\n .diff-arrow {\n font-size: 10px;\n color: var(--mj-text-muted);\n }\n\n .diff-new-val {\n color: var(--mj-status-success-text);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 200px;\n }\n\n .actions-bar {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding-top: var(--mj-space-3);\n border-top: 1px solid var(--mj-border-default);\n margin-top: var(--mj-space-1);\n }\n `],\n imports: [\n CommonModule,\n MJButtonDirective,\n MJStatBadgeComponent,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CloneReviewComponent {\n /** The plan to review: counts, warnings, blocked reasons and per-node field changes. */\n @Input() Plan: RecordClonePlanDetails | null = null;\n /** Name the root clone will get. */\n @Input() RootName = '';\n /** Reason the user entered, shown for confirmation. */\n @Input() Reason = '';\n /** Disables Confirm while the clone runs. */\n @Input() IsExecuting = false;\n /** Disables Confirm while the plan is being recomputed, so the user never confirms a plan they haven't seen. */\n @Input() IsPlanning = false;\n\n /** The user confirmed; the host executes the plan. */\n @Output() Confirm = new EventEmitter<void>();\n /** The user backed out of the clone. */\n @Output() Cancel = new EventEmitter<void>();\n /** Fires with a node key when the user clicks a warning or node to inspect it. */\n @Output() NodeClicked = new EventEmitter<string>();\n\n public get IsBlocked(): boolean {\n return !!this.Plan?.Blocked || this.BlockingErrors.length > 0;\n }\n\n public get CreateCount(): number {\n return this.Plan?.Counts?.Create ?? 0;\n }\n\n public get ReferenceCount(): number {\n if (!this.Plan?.Nodes) return 0;\n return this.Plan.Nodes.filter(n => n.Action === 'Reference').length;\n }\n\n public get SkipCount(): number {\n if (!this.Plan?.Nodes) return 0;\n return this.Plan.Nodes.filter(n => n.Action === 'Skip').length;\n }\n\n public get AllWarnings(): RecordClonePlanWarning[] {\n const list: RecordClonePlanWarning[] = [];\n if (this.Plan?.Warnings) {\n list.push(...this.Plan.Warnings);\n }\n if (this.Plan?.Nodes) {\n for (const node of this.Plan.Nodes) {\n if (node.Warnings) {\n for (const w of node.Warnings) {\n list.push({ ...w, NodeKey: w.NodeKey || node.Key });\n }\n }\n }\n }\n return list;\n }\n\n public get BlockingErrors(): RecordClonePlanWarning[] {\n return this.AllWarnings.filter(w => w.Severity === 'Error');\n }\n\n public get NonBlockingWarnings(): RecordClonePlanWarning[] {\n return this.AllWarnings.filter(w => w.Severity !== 'Error');\n }\n\n public get TotalWarningsCount(): number {\n return this.AllWarnings.length;\n }\n\n /**\n * The field changes a reviewer needs: every rule the clone applies (reset, ownership, rename,\n * remap, derived rule, override, prompt), configured exclusions and FLS denials. Plain copies,\n * columns that can't be written, and the automatic key and __mj_ timestamp exclusions are left out:\n * they are the same for every clone and would bury the rest.\n */\n public get NodesWithFieldChanges(): NodeFieldChangesSummary[] {\n if (!this.Plan?.Nodes) return [];\n const summaries: NodeFieldChangesSummary[] = [];\n for (const node of this.Plan.Nodes) {\n const changes = (node.FieldChanges ?? []).filter((c) => CloneReviewComponent.isReviewable(c));\n if (changes.length > 0) {\n summaries.push({ Node: node, Changes: changes });\n }\n }\n return summaries;\n }\n\n private static isReviewable(change: { Kind: string; Field: string; Reason: string }): boolean {\n if (change.Kind === 'Copy' || change.Kind === 'NotWritable') return false;\n if (change.Kind === 'Excluded') {\n // The engine always excludes the primary key and the __mj_ audit columns.\n return !change.Field.startsWith('__mj_') && !change.Reason.startsWith('Primary key');\n }\n return true;\n }\n\n public get TotalFieldChangesCount(): number {\n return this.NodesWithFieldChanges.reduce((sum, s) => sum + s.Changes.length, 0);\n }\n\n public FormatChangeKind(kind: string): string {\n return kind.replace(/_/g, ' ');\n }\n\n public FormatDiffValue(val: unknown): string {\n if (val === null || val === undefined) return '(null)';\n if (typeof val === 'string') return `\"${val}\"`;\n return String(val);\n }\n\n public OnNodeClick(nodeKey: string): void {\n this.NodeClicked.emit(nodeKey);\n }\n\n public OnConfirm(): void {\n if (!this.IsBlocked && !this.IsExecuting && !this.IsPlanning) {\n this.Confirm.emit();\n }\n }\n\n public OnCancel(): void {\n if (!this.IsExecuting) {\n this.Cancel.emit();\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Scope step controls for the record clone wizard.
|
|
3
|
+
*
|
|
4
|
+
* Implements §12.3 of the record cloning plan with the scope rules from the review:
|
|
5
|
+
* everyone sees the preset picker and a summary of what the clone will copy, taken from the
|
|
6
|
+
* entity's `Configuration.Clone`. Only a holder of `Clone Records: Override Scope` gets the
|
|
7
|
+
* developer overrides (depth, record cap, soft links, subtypes, hierarchy). The summary says
|
|
8
|
+
* whether Entity Actions run; changing that is not offered here (a caller holding
|
|
9
|
+
* `Clone Records: Fire Hooks` can set `EntityActions` on the request). The server applies the same rules.
|
|
10
|
+
*/
|
|
11
|
+
import { EventEmitter } from '@angular/core';
|
|
12
|
+
import type { RecordClonePlanOptions } from '@memberjunction/core-entities';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
/** The scope values the summary shows and the overrides edit. */
|
|
15
|
+
export interface CloneScopeValues {
|
|
16
|
+
MaxDepth: number;
|
|
17
|
+
MaxRecords: number;
|
|
18
|
+
Subtypes: 'include' | 'exclude';
|
|
19
|
+
Hierarchy: 'subtree' | 'node';
|
|
20
|
+
SoftLinks: 'skip' | 'include';
|
|
21
|
+
EntityActions: 'suppress' | 'fire';
|
|
22
|
+
}
|
|
23
|
+
interface ScopeFact {
|
|
24
|
+
Key: keyof CloneScopeValues;
|
|
25
|
+
Text: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class CloneScopeControlsComponent {
|
|
28
|
+
/** Preset keys from the entity's `Clone.Presets`. */
|
|
29
|
+
Presets: string[];
|
|
30
|
+
/** Label and description to show for each preset key; a key with none is shown as-is. */
|
|
31
|
+
PresetLabels: Record<string, {
|
|
32
|
+
Label: string;
|
|
33
|
+
Description?: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** The preset currently applied, if any. */
|
|
36
|
+
SelectedPreset?: string;
|
|
37
|
+
/** Effective depth the plan uses. */
|
|
38
|
+
MaxDepth: number;
|
|
39
|
+
/** Effective cap on records the clone may create. */
|
|
40
|
+
MaxRecords: number;
|
|
41
|
+
/** Whether IS-A subtype rows are cloned with their parent. */
|
|
42
|
+
Subtypes: 'include' | 'exclude';
|
|
43
|
+
/** For self-referencing hierarchies: copy the whole subtree, or only this node. */
|
|
44
|
+
Hierarchy: 'subtree' | 'node';
|
|
45
|
+
/** Whether polymorphic EntityID/RecordID rows (tags, attachments, notes) are cloned. */
|
|
46
|
+
SoftLinks: 'skip' | 'include';
|
|
47
|
+
/** Whether Entity Actions run during the clone's saves. */
|
|
48
|
+
EntityActions: 'suppress' | 'fire';
|
|
49
|
+
/** The entity's configured scope; the summary highlights where the effective values differ. Null = same as effective. */
|
|
50
|
+
ConfiguredScope: CloneScopeValues | null;
|
|
51
|
+
/** Entity being cloned, for the summary's source line. */
|
|
52
|
+
EntityName: string;
|
|
53
|
+
/** Show the depth, cap and scope toggles. True only for holders of `Clone Records: Override Scope`. */
|
|
54
|
+
CanOverrideScope: boolean;
|
|
55
|
+
private static nextId;
|
|
56
|
+
/** Prefix for this instance's element ids, so the switches' labels stay unique on a page with two panels. */
|
|
57
|
+
readonly IdPrefix: string;
|
|
58
|
+
/** Fires with the full option set whenever any control changes. */
|
|
59
|
+
ScopeChanged: EventEmitter<RecordClonePlanOptions>;
|
|
60
|
+
/** Fires when the user asks to drop every override and use the entity's configured scope. */
|
|
61
|
+
ResetToDefaults: EventEmitter<void>;
|
|
62
|
+
get Current(): CloneScopeValues;
|
|
63
|
+
/** Scope values that differ from the entity's configuration. */
|
|
64
|
+
get ChangedKeys(): Array<keyof CloneScopeValues>;
|
|
65
|
+
IsChanged(key: keyof CloneScopeValues): boolean;
|
|
66
|
+
get Facts(): ScopeFact[];
|
|
67
|
+
get SourceText(): string;
|
|
68
|
+
get DefaultsText(): string;
|
|
69
|
+
OnPresetChange(preset: string): void;
|
|
70
|
+
OnMaxDepthChange(depth: number | string): void;
|
|
71
|
+
OnMaxRecordsChange(records: number | string): void;
|
|
72
|
+
OnSubtypesToggle(checked: boolean): void;
|
|
73
|
+
OnHierarchyToggle(checked: boolean): void;
|
|
74
|
+
OnSoftLinksToggle(checked: boolean): void;
|
|
75
|
+
OnResetToDefaults(): void;
|
|
76
|
+
EmitScopeChanged(): void;
|
|
77
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CloneScopeControlsComponent, never>;
|
|
78
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<CloneScopeControlsComponent, "mj-clone-scope-controls", never, { "Presets": { "alias": "Presets"; "required": false; }; "PresetLabels": { "alias": "PresetLabels"; "required": false; }; "SelectedPreset": { "alias": "SelectedPreset"; "required": false; }; "MaxDepth": { "alias": "MaxDepth"; "required": false; }; "MaxRecords": { "alias": "MaxRecords"; "required": false; }; "Subtypes": { "alias": "Subtypes"; "required": false; }; "Hierarchy": { "alias": "Hierarchy"; "required": false; }; "SoftLinks": { "alias": "SoftLinks"; "required": false; }; "EntityActions": { "alias": "EntityActions"; "required": false; }; "ConfiguredScope": { "alias": "ConfiguredScope"; "required": false; }; "EntityName": { "alias": "EntityName"; "required": false; }; "CanOverrideScope": { "alias": "CanOverrideScope"; "required": false; }; }, { "ScopeChanged": "ScopeChanged"; "ResetToDefaults": "ResetToDefaults"; }, never, never, true, never>;
|
|
79
|
+
}
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=clone-scope-controls.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone-scope-controls.component.d.ts","sourceRoot":"","sources":["../../src/lib/clone-scope-controls.component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAKH,YAAY,EACf,MAAM,eAAe,CAAC;AAIvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;;AAE5E,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,SAAS,EAAE,SAAS,GAAG,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,aAAa,EAAE,UAAU,GAAG,MAAM,CAAC;CACtC;AAED,UAAU,SAAS;IACf,GAAG,EAAE,MAAM,gBAAgB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,qBA2Qa,2BAA2B;IACpC,qDAAqD;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAM;IAChC,yFAAyF;IAChF,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IACpF,4CAA4C;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC,qCAAqC;IAC5B,QAAQ,SAAK;IACtB,qDAAqD;IAC5C,UAAU,SAAO;IAC1B,8DAA8D;IACrD,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAa;IACrD,mFAAmF;IAC1E,SAAS,EAAE,SAAS,GAAG,MAAM,CAAa;IACnD,wFAAwF;IAC/E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAU;IAChD,2DAA2D;IAClD,aAAa,EAAE,UAAU,GAAG,MAAM,CAAU;IAErD,yHAAyH;IAChH,eAAe,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IACzD,0DAA0D;IACjD,UAAU,SAAM;IAEzB,uGAAuG;IAC9F,gBAAgB,UAAS;IAClC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAK;IAC1B,6GAA6G;IAC7G,SAAgB,QAAQ,SAA4D;IAEpF,mEAAmE;IACzD,YAAY,uCAA8C;IACpE,6FAA6F;IACnF,eAAe,qBAA4B;IAErD,IAAW,OAAO,IAAI,gBAAgB,CASrC;IAED,gEAAgE;IAChE,IAAW,WAAW,IAAI,KAAK,CAAC,MAAM,gBAAgB,CAAC,CAKtD;IAEM,SAAS,CAAC,GAAG,EAAE,MAAM,gBAAgB,GAAG,OAAO;IAItD,IAAW,KAAK,IAAI,SAAS,EAAE,CAS9B;IAED,IAAW,UAAU,IAAI,MAAM,CAI9B;IAED,IAAW,YAAY,IAAI,MAAM,CAIhC;IAEM,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKpC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO9C,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOlD,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKxC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKzC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKzC,iBAAiB,IAAI,IAAI;IAIzB,gBAAgB,IAAI,IAAI;yCAzHtB,2BAA2B;2CAA3B,2BAA2B;CA4HvC"}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Scope step controls for the record clone wizard.
|
|
3
|
+
*
|
|
4
|
+
* Implements §12.3 of the record cloning plan with the scope rules from the review:
|
|
5
|
+
* everyone sees the preset picker and a summary of what the clone will copy, taken from the
|
|
6
|
+
* entity's `Configuration.Clone`. Only a holder of `Clone Records: Override Scope` gets the
|
|
7
|
+
* developer overrides (depth, record cap, soft links, subtypes, hierarchy). The summary says
|
|
8
|
+
* whether Entity Actions run; changing that is not offered here (a caller holding
|
|
9
|
+
* `Clone Records: Fire Hooks` can set `EntityActions` on the request). The server applies the same rules.
|
|
10
|
+
*/
|
|
11
|
+
import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, } from '@angular/core';
|
|
12
|
+
import { CommonModule } from '@angular/common';
|
|
13
|
+
import { FormsModule } from '@angular/forms';
|
|
14
|
+
import { MJSwitchComponent } from '@memberjunction/ng-ui-components';
|
|
15
|
+
import * as i0 from "@angular/core";
|
|
16
|
+
import * as i1 from "@angular/forms";
|
|
17
|
+
const _forTrack0 = ($index, $item) => $item.Key;
|
|
18
|
+
function CloneScopeControlsComponent_Conditional_1_For_7_Template(rf, ctx) { if (rf & 1) {
|
|
19
|
+
i0.ɵɵelementStart(0, "option", 12);
|
|
20
|
+
i0.ɵɵtext(1);
|
|
21
|
+
i0.ɵɵelementEnd();
|
|
22
|
+
} if (rf & 2) {
|
|
23
|
+
const preset_r3 = ctx.$implicit;
|
|
24
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
25
|
+
i0.ɵɵproperty("value", preset_r3)("title", (ctx_r1.PresetLabels[preset_r3] == null ? null : ctx_r1.PresetLabels[preset_r3].Description) ?? "");
|
|
26
|
+
i0.ɵɵadvance();
|
|
27
|
+
i0.ɵɵtextInterpolate((ctx_r1.PresetLabels[preset_r3] == null ? null : ctx_r1.PresetLabels[preset_r3].Label) ?? preset_r3);
|
|
28
|
+
} }
|
|
29
|
+
function CloneScopeControlsComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
30
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
31
|
+
i0.ɵɵelementStart(0, "div", 1)(1, "label", 9);
|
|
32
|
+
i0.ɵɵtext(2, "Cloning Preset");
|
|
33
|
+
i0.ɵɵelementEnd();
|
|
34
|
+
i0.ɵɵelementStart(3, "select", 10);
|
|
35
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_1_Template_select_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnPresetChange($event)); });
|
|
36
|
+
i0.ɵɵelementStart(4, "option", 11);
|
|
37
|
+
i0.ɵɵtext(5, "Default (Custom)");
|
|
38
|
+
i0.ɵɵelementEnd();
|
|
39
|
+
i0.ɵɵrepeaterCreate(6, CloneScopeControlsComponent_Conditional_1_For_7_Template, 2, 3, "option", 12, i0.ɵɵrepeaterTrackByIdentity);
|
|
40
|
+
i0.ɵɵelementEnd()();
|
|
41
|
+
} if (rf & 2) {
|
|
42
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
43
|
+
i0.ɵɵadvance(3);
|
|
44
|
+
i0.ɵɵproperty("ngModel", ctx_r1.SelectedPreset ?? "");
|
|
45
|
+
i0.ɵɵadvance(3);
|
|
46
|
+
i0.ɵɵrepeater(ctx_r1.Presets);
|
|
47
|
+
} }
|
|
48
|
+
function CloneScopeControlsComponent_For_10_Template(rf, ctx) { if (rf & 1) {
|
|
49
|
+
i0.ɵɵelementStart(0, "span", 13);
|
|
50
|
+
i0.ɵɵtext(1);
|
|
51
|
+
i0.ɵɵelementEnd();
|
|
52
|
+
} if (rf & 2) {
|
|
53
|
+
const fact_r4 = ctx.$implicit;
|
|
54
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
55
|
+
i0.ɵɵclassProp("changed", ctx_r1.IsChanged(fact_r4.Key));
|
|
56
|
+
i0.ɵɵadvance();
|
|
57
|
+
i0.ɵɵtextInterpolate(fact_r4.Text);
|
|
58
|
+
} }
|
|
59
|
+
function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
61
|
+
i0.ɵɵelementStart(0, "div", 20)(1, "label", 21);
|
|
62
|
+
i0.ɵɵtext(2, "Max depth");
|
|
63
|
+
i0.ɵɵelementEnd();
|
|
64
|
+
i0.ɵɵelementStart(3, "input", 22);
|
|
65
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnMaxDepthChange($event)); });
|
|
66
|
+
i0.ɵɵelementEnd()();
|
|
67
|
+
i0.ɵɵelementStart(4, "div", 20)(5, "label", 23);
|
|
68
|
+
i0.ɵɵtext(6, "Max records");
|
|
69
|
+
i0.ɵɵelementEnd();
|
|
70
|
+
i0.ɵɵelementStart(7, "input", 24);
|
|
71
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_input_ngModelChange_7_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnMaxRecordsChange($event)); });
|
|
72
|
+
i0.ɵɵelementEnd()();
|
|
73
|
+
i0.ɵɵelementStart(8, "div", 20)(9, "span", 25);
|
|
74
|
+
i0.ɵɵlistener("click", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_span_click_9_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnSoftLinksToggle(ctx_r1.SoftLinks !== "include")); });
|
|
75
|
+
i0.ɵɵtext(10, "Include soft links");
|
|
76
|
+
i0.ɵɵelementEnd();
|
|
77
|
+
i0.ɵɵelementStart(11, "mj-switch", 26);
|
|
78
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_mj_switch_ngModelChange_11_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnSoftLinksToggle($event)); });
|
|
79
|
+
i0.ɵɵelementEnd();
|
|
80
|
+
i0.ɵɵelementStart(12, "span", 27);
|
|
81
|
+
i0.ɵɵtext(13, "Tags, attachments, notes and other EntityID/RecordID rows");
|
|
82
|
+
i0.ɵɵelementEnd()();
|
|
83
|
+
i0.ɵɵelementStart(14, "div", 20)(15, "span", 25);
|
|
84
|
+
i0.ɵɵlistener("click", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_span_click_15_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnSubtypesToggle(ctx_r1.Subtypes !== "include")); });
|
|
85
|
+
i0.ɵɵtext(16, "Include IS-A subtypes");
|
|
86
|
+
i0.ɵɵelementEnd();
|
|
87
|
+
i0.ɵɵelementStart(17, "mj-switch", 26);
|
|
88
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_mj_switch_ngModelChange_17_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnSubtypesToggle($event)); });
|
|
89
|
+
i0.ɵɵelementEnd()();
|
|
90
|
+
i0.ɵɵelementStart(18, "div", 20)(19, "span", 25);
|
|
91
|
+
i0.ɵɵlistener("click", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_span_click_19_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnHierarchyToggle(ctx_r1.Hierarchy !== "subtree")); });
|
|
92
|
+
i0.ɵɵtext(20, "Copy the whole hierarchy subtree");
|
|
93
|
+
i0.ɵɵelementEnd();
|
|
94
|
+
i0.ɵɵelementStart(21, "mj-switch", 26);
|
|
95
|
+
i0.ɵɵlistener("ngModelChange", function CloneScopeControlsComponent_Conditional_11_Conditional_10_Template_mj_switch_ngModelChange_21_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnHierarchyToggle($event)); });
|
|
96
|
+
i0.ɵɵelementEnd()();
|
|
97
|
+
} if (rf & 2) {
|
|
98
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
99
|
+
i0.ɵɵadvance(3);
|
|
100
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxDepth);
|
|
101
|
+
i0.ɵɵadvance(4);
|
|
102
|
+
i0.ɵɵproperty("ngModel", ctx_r1.MaxRecords);
|
|
103
|
+
i0.ɵɵadvance(2);
|
|
104
|
+
i0.ɵɵproperty("id", ctx_r1.IdPrefix + "-softlinks");
|
|
105
|
+
i0.ɵɵadvance(2);
|
|
106
|
+
i0.ɵɵproperty("AriaLabelledBy", ctx_r1.IdPrefix + "-softlinks")("ngModel", ctx_r1.SoftLinks === "include");
|
|
107
|
+
i0.ɵɵadvance(4);
|
|
108
|
+
i0.ɵɵproperty("id", ctx_r1.IdPrefix + "-subtypes");
|
|
109
|
+
i0.ɵɵadvance(2);
|
|
110
|
+
i0.ɵɵproperty("AriaLabelledBy", ctx_r1.IdPrefix + "-subtypes")("ngModel", ctx_r1.Subtypes === "include");
|
|
111
|
+
i0.ɵɵadvance(2);
|
|
112
|
+
i0.ɵɵproperty("id", ctx_r1.IdPrefix + "-hierarchy");
|
|
113
|
+
i0.ɵɵadvance(2);
|
|
114
|
+
i0.ɵɵproperty("AriaLabelledBy", ctx_r1.IdPrefix + "-hierarchy")("ngModel", ctx_r1.Hierarchy === "subtree");
|
|
115
|
+
} }
|
|
116
|
+
function CloneScopeControlsComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
117
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
118
|
+
i0.ɵɵelementStart(0, "details", 8)(1, "summary")(2, "span");
|
|
119
|
+
i0.ɵɵelement(3, "i", 14);
|
|
120
|
+
i0.ɵɵtext(4, "\u00A0 Developer overrides");
|
|
121
|
+
i0.ɵɵelementEnd();
|
|
122
|
+
i0.ɵɵelementStart(5, "span", 15);
|
|
123
|
+
i0.ɵɵtext(6);
|
|
124
|
+
i0.ɵɵelementEnd()();
|
|
125
|
+
i0.ɵɵelementStart(7, "div", 16)(8, "p", 17);
|
|
126
|
+
i0.ɵɵtext(9, " These change what the engine copies for this one clone and are saved on the clone log. ");
|
|
127
|
+
i0.ɵɵelementEnd();
|
|
128
|
+
i0.ɵɵconditionalCreate(10, CloneScopeControlsComponent_Conditional_11_Conditional_10_Template, 22, 11);
|
|
129
|
+
i0.ɵɵelementStart(11, "div", 18)(12, "span");
|
|
130
|
+
i0.ɵɵtext(13);
|
|
131
|
+
i0.ɵɵelementEnd();
|
|
132
|
+
i0.ɵɵelementStart(14, "button", 19);
|
|
133
|
+
i0.ɵɵlistener("click", function CloneScopeControlsComponent_Conditional_11_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnResetToDefaults()); });
|
|
134
|
+
i0.ɵɵtext(15, " Reset to entity defaults ");
|
|
135
|
+
i0.ɵɵelementEnd()()()();
|
|
136
|
+
} if (rf & 2) {
|
|
137
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
138
|
+
i0.ɵɵproperty("open", ctx_r1.ChangedKeys.length > 0);
|
|
139
|
+
i0.ɵɵadvance(6);
|
|
140
|
+
i0.ɵɵtextInterpolate(ctx_r1.ChangedKeys.length > 0 ? ctx_r1.ChangedKeys.length + " active" : "none");
|
|
141
|
+
i0.ɵɵadvance(4);
|
|
142
|
+
i0.ɵɵconditional(ctx_r1.CanOverrideScope ? 10 : -1);
|
|
143
|
+
i0.ɵɵadvance(3);
|
|
144
|
+
i0.ɵɵtextInterpolate(ctx_r1.DefaultsText);
|
|
145
|
+
i0.ɵɵadvance();
|
|
146
|
+
i0.ɵɵproperty("disabled", ctx_r1.ChangedKeys.length === 0);
|
|
147
|
+
} }
|
|
148
|
+
export class CloneScopeControlsComponent {
|
|
149
|
+
/** Preset keys from the entity's `Clone.Presets`. */
|
|
150
|
+
Presets = [];
|
|
151
|
+
/** Label and description to show for each preset key; a key with none is shown as-is. */
|
|
152
|
+
PresetLabels = {};
|
|
153
|
+
/** The preset currently applied, if any. */
|
|
154
|
+
SelectedPreset;
|
|
155
|
+
/** Effective depth the plan uses. */
|
|
156
|
+
MaxDepth = 3;
|
|
157
|
+
/** Effective cap on records the clone may create. */
|
|
158
|
+
MaxRecords = 500;
|
|
159
|
+
/** Whether IS-A subtype rows are cloned with their parent. */
|
|
160
|
+
Subtypes = 'include';
|
|
161
|
+
/** For self-referencing hierarchies: copy the whole subtree, or only this node. */
|
|
162
|
+
Hierarchy = 'subtree';
|
|
163
|
+
/** Whether polymorphic EntityID/RecordID rows (tags, attachments, notes) are cloned. */
|
|
164
|
+
SoftLinks = 'skip';
|
|
165
|
+
/** Whether Entity Actions run during the clone's saves. */
|
|
166
|
+
EntityActions = 'fire';
|
|
167
|
+
/** The entity's configured scope; the summary highlights where the effective values differ. Null = same as effective. */
|
|
168
|
+
ConfiguredScope = null;
|
|
169
|
+
/** Entity being cloned, for the summary's source line. */
|
|
170
|
+
EntityName = '';
|
|
171
|
+
/** Show the depth, cap and scope toggles. True only for holders of `Clone Records: Override Scope`. */
|
|
172
|
+
CanOverrideScope = false;
|
|
173
|
+
static nextId = 0;
|
|
174
|
+
/** Prefix for this instance's element ids, so the switches' labels stay unique on a page with two panels. */
|
|
175
|
+
IdPrefix = `mj-clone-scope-${++CloneScopeControlsComponent.nextId}`;
|
|
176
|
+
/** Fires with the full option set whenever any control changes. */
|
|
177
|
+
ScopeChanged = new EventEmitter();
|
|
178
|
+
/** Fires when the user asks to drop every override and use the entity's configured scope. */
|
|
179
|
+
ResetToDefaults = new EventEmitter();
|
|
180
|
+
get Current() {
|
|
181
|
+
return {
|
|
182
|
+
MaxDepth: this.MaxDepth,
|
|
183
|
+
MaxRecords: this.MaxRecords,
|
|
184
|
+
Subtypes: this.Subtypes,
|
|
185
|
+
Hierarchy: this.Hierarchy,
|
|
186
|
+
SoftLinks: this.SoftLinks,
|
|
187
|
+
EntityActions: this.EntityActions,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/** Scope values that differ from the entity's configuration. */
|
|
191
|
+
get ChangedKeys() {
|
|
192
|
+
const configured = this.ConfiguredScope;
|
|
193
|
+
if (!configured)
|
|
194
|
+
return [];
|
|
195
|
+
const current = this.Current;
|
|
196
|
+
return Object.keys(current).filter((k) => current[k] !== configured[k]);
|
|
197
|
+
}
|
|
198
|
+
IsChanged(key) {
|
|
199
|
+
return this.ChangedKeys.includes(key);
|
|
200
|
+
}
|
|
201
|
+
get Facts() {
|
|
202
|
+
return [
|
|
203
|
+
{ Key: 'MaxDepth', Text: `Depth ${this.MaxDepth}` },
|
|
204
|
+
{ Key: 'MaxRecords', Text: `Up to ${this.MaxRecords} records` },
|
|
205
|
+
{ Key: 'SoftLinks', Text: this.SoftLinks === 'include' ? 'Soft links included' : 'Soft links off' },
|
|
206
|
+
{ Key: 'Subtypes', Text: this.Subtypes === 'include' ? 'Subtypes included' : 'Subtypes excluded' },
|
|
207
|
+
{ Key: 'Hierarchy', Text: this.Hierarchy === 'subtree' ? 'Hierarchy subtree' : 'This node only' },
|
|
208
|
+
{ Key: 'EntityActions', Text: this.EntityActions === 'fire' ? 'Entity actions fire' : 'Entity actions suppressed' },
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
get SourceText() {
|
|
212
|
+
const entity = this.EntityName ? `the ${this.EntityName} clone configuration` : 'the entity clone configuration';
|
|
213
|
+
const n = this.ChangedKeys.length;
|
|
214
|
+
return n === 0 ? `Set by ${entity}` : `${entity.charAt(0).toUpperCase()}${entity.slice(1)}, with ${n} override${n === 1 ? '' : 's'}`;
|
|
215
|
+
}
|
|
216
|
+
get DefaultsText() {
|
|
217
|
+
const c = this.ConfiguredScope;
|
|
218
|
+
if (!c)
|
|
219
|
+
return '';
|
|
220
|
+
return `Entity defaults: depth ${c.MaxDepth} · ${c.MaxRecords} records · soft links ${c.SoftLinks === 'include' ? 'on' : 'off'}`;
|
|
221
|
+
}
|
|
222
|
+
OnPresetChange(preset) {
|
|
223
|
+
this.SelectedPreset = preset || undefined;
|
|
224
|
+
this.EmitScopeChanged();
|
|
225
|
+
}
|
|
226
|
+
OnMaxDepthChange(depth) {
|
|
227
|
+
const parsed = typeof depth === 'string' ? parseInt(depth, 10) : depth;
|
|
228
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
229
|
+
return;
|
|
230
|
+
this.MaxDepth = parsed;
|
|
231
|
+
this.EmitScopeChanged();
|
|
232
|
+
}
|
|
233
|
+
OnMaxRecordsChange(records) {
|
|
234
|
+
const parsed = typeof records === 'string' ? parseInt(records, 10) : records;
|
|
235
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
236
|
+
return;
|
|
237
|
+
this.MaxRecords = parsed;
|
|
238
|
+
this.EmitScopeChanged();
|
|
239
|
+
}
|
|
240
|
+
OnSubtypesToggle(checked) {
|
|
241
|
+
this.Subtypes = checked ? 'include' : 'exclude';
|
|
242
|
+
this.EmitScopeChanged();
|
|
243
|
+
}
|
|
244
|
+
OnHierarchyToggle(checked) {
|
|
245
|
+
this.Hierarchy = checked ? 'subtree' : 'node';
|
|
246
|
+
this.EmitScopeChanged();
|
|
247
|
+
}
|
|
248
|
+
OnSoftLinksToggle(checked) {
|
|
249
|
+
this.SoftLinks = checked ? 'include' : 'skip';
|
|
250
|
+
this.EmitScopeChanged();
|
|
251
|
+
}
|
|
252
|
+
OnResetToDefaults() {
|
|
253
|
+
this.ResetToDefaults.emit();
|
|
254
|
+
}
|
|
255
|
+
EmitScopeChanged() {
|
|
256
|
+
this.ScopeChanged.emit({ Preset: this.SelectedPreset, ...this.Current });
|
|
257
|
+
}
|
|
258
|
+
static ɵfac = function CloneScopeControlsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || CloneScopeControlsComponent)(); };
|
|
259
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CloneScopeControlsComponent, selectors: [["mj-clone-scope-controls"]], inputs: { Presets: "Presets", PresetLabels: "PresetLabels", SelectedPreset: "SelectedPreset", MaxDepth: "MaxDepth", MaxRecords: "MaxRecords", Subtypes: "Subtypes", Hierarchy: "Hierarchy", SoftLinks: "SoftLinks", EntityActions: "EntityActions", ConfiguredScope: "ConfiguredScope", EntityName: "EntityName", CanOverrideScope: "CanOverrideScope" }, outputs: { ScopeChanged: "ScopeChanged", ResetToDefaults: "ResetToDefaults" }, decls: 12, vars: 3, consts: [[1, "scope-controls-container"], [1, "control-group"], [1, "scope-summary"], [1, "summary-top"], [1, "summary-title"], [1, "summary-source"], [1, "facts"], [1, "fact", 3, "changed"], [1, "dev-overrides", 3, "open"], ["for", "preset-select", 1, "control-label"], ["id", "preset-select", 1, "mj-select", 3, "ngModelChange", "ngModel"], ["value", ""], [3, "value", "title"], [1, "fact"], [1, "fa-solid", "fa-code"], [1, "dev-count"], [1, "dev-body"], [1, "dev-warning"], [1, "dev-actions"], ["type", "button", 1, "link-btn", 3, "click", "disabled"], [1, "field-row"], ["for", "max-depth-input"], ["id", "max-depth-input", "type", "number", "min", "1", "max", "10", 1, "mj-input", "num-input", 3, "ngModelChange", "ngModel"], ["for", "max-records-input"], ["id", "max-records-input", "type", "number", "min", "1", "max", "5000", 1, "mj-input", "num-input", 3, "ngModelChange", "ngModel"], [1, "toggle-label", 3, "click", "id"], [3, "ngModelChange", "AriaLabelledBy", "ngModel"], [1, "field-hint"]], template: function CloneScopeControlsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
260
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
261
|
+
i0.ɵɵconditionalCreate(1, CloneScopeControlsComponent_Conditional_1_Template, 8, 1, "div", 1);
|
|
262
|
+
i0.ɵɵelementStart(2, "div", 2)(3, "div", 3)(4, "span", 4);
|
|
263
|
+
i0.ɵɵtext(5, "What will be copied");
|
|
264
|
+
i0.ɵɵelementEnd();
|
|
265
|
+
i0.ɵɵelementStart(6, "span", 5);
|
|
266
|
+
i0.ɵɵtext(7);
|
|
267
|
+
i0.ɵɵelementEnd()();
|
|
268
|
+
i0.ɵɵelementStart(8, "div", 6);
|
|
269
|
+
i0.ɵɵrepeaterCreate(9, CloneScopeControlsComponent_For_10_Template, 2, 3, "span", 7, _forTrack0);
|
|
270
|
+
i0.ɵɵelementEnd()();
|
|
271
|
+
i0.ɵɵconditionalCreate(11, CloneScopeControlsComponent_Conditional_11_Template, 16, 5, "details", 8);
|
|
272
|
+
i0.ɵɵelementEnd();
|
|
273
|
+
} if (rf & 2) {
|
|
274
|
+
i0.ɵɵadvance();
|
|
275
|
+
i0.ɵɵconditional(ctx.Presets && ctx.Presets.length > 0 ? 1 : -1);
|
|
276
|
+
i0.ɵɵadvance(6);
|
|
277
|
+
i0.ɵɵtextInterpolate(ctx.SourceText);
|
|
278
|
+
i0.ɵɵadvance(2);
|
|
279
|
+
i0.ɵɵrepeater(ctx.Facts);
|
|
280
|
+
i0.ɵɵadvance(2);
|
|
281
|
+
i0.ɵɵconditional(ctx.CanOverrideScope ? 11 : -1);
|
|
282
|
+
} }, dependencies: [CommonModule, FormsModule, i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.MinValidator, i1.MaxValidator, i1.NgModel, MJSwitchComponent], styles: [".scope-controls-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-2) 0;\n }\n\n .control-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n }\n\n .control-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .mj-select[_ngcontent-%COMP%], .mj-input[_ngcontent-%COMP%] {\n padding: var(--mj-space-1-5) var(--mj-space-2-5);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: var(--mj-text-sm);\n outline: none;\n }\n\n .mj-select[_ngcontent-%COMP%]:focus, .mj-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n }\n\n .scope-summary[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n }\n\n .summary-top[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: baseline;\n gap: var(--mj-space-2);\n }\n\n .summary-title[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .summary-source[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .facts[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1-5);\n }\n\n .fact[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n padding: 3px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n }\n\n .fact.changed[_ngcontent-%COMP%] {\n border-color: var(--mj-status-warning-border);\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n font-weight: 600;\n }\n\n .dev-overrides[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n }\n\n .dev-overrides[_ngcontent-%COMP%] summary[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n font-weight: 600;\n font-size: var(--mj-text-sm);\n cursor: pointer;\n list-style: none;\n }\n\n .dev-overrides[_ngcontent-%COMP%] summary[_ngcontent-%COMP%]::-webkit-details-marker {\n display: none;\n }\n\n .dev-overrides[_ngcontent-%COMP%] summary[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: -2px;\n }\n\n .dev-count[_ngcontent-%COMP%] {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n }\n\n .dev-body[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n padding: var(--mj-space-3);\n background: var(--mj-bg-surface);\n }\n\n .dev-warning[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n }\n\n .field-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--mj-space-1) var(--mj-space-3);\n }\n\n .field-row[_ngcontent-%COMP%] label[_ngcontent-%COMP%], .toggle-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n cursor: pointer;\n user-select: none;\n }\n\n .field-hint[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .num-input[_ngcontent-%COMP%] {\n width: 96px;\n font-variant-numeric: tabular-nums;\n }\n\n .dev-actions[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .link-btn[_ngcontent-%COMP%] {\n border: 0;\n background: none;\n padding: 0;\n color: var(--mj-brand-primary);\n font: inherit;\n cursor: pointer;\n }\n\n .link-btn[_ngcontent-%COMP%]:disabled {\n color: var(--mj-text-muted);\n cursor: default;\n }"], changeDetection: 0 });
|
|
283
|
+
}
|
|
284
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CloneScopeControlsComponent, [{
|
|
285
|
+
type: Component,
|
|
286
|
+
args: [{ standalone: true, selector: 'mj-clone-scope-controls', template: `
|
|
287
|
+
<div class="scope-controls-container">
|
|
288
|
+
@if (Presets && Presets.length > 0) {
|
|
289
|
+
<div class="control-group">
|
|
290
|
+
<label class="control-label" for="preset-select">Cloning Preset</label>
|
|
291
|
+
<select
|
|
292
|
+
id="preset-select"
|
|
293
|
+
class="mj-select"
|
|
294
|
+
[ngModel]="SelectedPreset ?? ''"
|
|
295
|
+
(ngModelChange)="OnPresetChange($event)">
|
|
296
|
+
<option value="">Default (Custom)</option>
|
|
297
|
+
@for (preset of Presets; track preset) {
|
|
298
|
+
<option [value]="preset" [title]="PresetLabels[preset]?.Description ?? ''">{{ PresetLabels[preset]?.Label ?? preset }}</option>
|
|
299
|
+
}
|
|
300
|
+
</select>
|
|
301
|
+
</div>
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
<div class="scope-summary">
|
|
305
|
+
<div class="summary-top">
|
|
306
|
+
<span class="summary-title">What will be copied</span>
|
|
307
|
+
<span class="summary-source">{{ SourceText }}</span>
|
|
308
|
+
</div>
|
|
309
|
+
<div class="facts">
|
|
310
|
+
@for (fact of Facts; track fact.Key) {
|
|
311
|
+
<span class="fact" [class.changed]="IsChanged(fact.Key)">{{ fact.Text }}</span>
|
|
312
|
+
}
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
@if (CanOverrideScope) {
|
|
317
|
+
<details class="dev-overrides" [open]="ChangedKeys.length > 0">
|
|
318
|
+
<summary>
|
|
319
|
+
<span><i class="fa-solid fa-code"></i> Developer overrides</span>
|
|
320
|
+
<span class="dev-count">{{ ChangedKeys.length > 0 ? ChangedKeys.length + ' active' : 'none' }}</span>
|
|
321
|
+
</summary>
|
|
322
|
+
<div class="dev-body">
|
|
323
|
+
<p class="dev-warning">
|
|
324
|
+
These change what the engine copies for this one clone and are saved on the clone log.
|
|
325
|
+
</p>
|
|
326
|
+
|
|
327
|
+
@if (CanOverrideScope) {
|
|
328
|
+
<div class="field-row">
|
|
329
|
+
<label for="max-depth-input">Max depth</label>
|
|
330
|
+
<input id="max-depth-input" type="number" min="1" max="10" class="mj-input num-input"
|
|
331
|
+
[ngModel]="MaxDepth" (ngModelChange)="OnMaxDepthChange($event)" />
|
|
332
|
+
</div>
|
|
333
|
+
<div class="field-row">
|
|
334
|
+
<label for="max-records-input">Max records</label>
|
|
335
|
+
<input id="max-records-input" type="number" min="1" max="5000" class="mj-input num-input"
|
|
336
|
+
[ngModel]="MaxRecords" (ngModelChange)="OnMaxRecordsChange($event)" />
|
|
337
|
+
</div>
|
|
338
|
+
<div class="field-row">
|
|
339
|
+
<span class="toggle-label" [id]="IdPrefix + '-softlinks'" (click)="OnSoftLinksToggle(SoftLinks !== 'include')">Include soft links</span>
|
|
340
|
+
<mj-switch [AriaLabelledBy]="IdPrefix + '-softlinks'" [ngModel]="SoftLinks === 'include'" (ngModelChange)="OnSoftLinksToggle($event)"></mj-switch>
|
|
341
|
+
<span class="field-hint">Tags, attachments, notes and other EntityID/RecordID rows</span>
|
|
342
|
+
</div>
|
|
343
|
+
<div class="field-row">
|
|
344
|
+
<span class="toggle-label" [id]="IdPrefix + '-subtypes'" (click)="OnSubtypesToggle(Subtypes !== 'include')">Include IS-A subtypes</span>
|
|
345
|
+
<mj-switch [AriaLabelledBy]="IdPrefix + '-subtypes'" [ngModel]="Subtypes === 'include'" (ngModelChange)="OnSubtypesToggle($event)"></mj-switch>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="field-row">
|
|
348
|
+
<span class="toggle-label" [id]="IdPrefix + '-hierarchy'" (click)="OnHierarchyToggle(Hierarchy !== 'subtree')">Copy the whole hierarchy subtree</span>
|
|
349
|
+
<mj-switch [AriaLabelledBy]="IdPrefix + '-hierarchy'" [ngModel]="Hierarchy === 'subtree'" (ngModelChange)="OnHierarchyToggle($event)"></mj-switch>
|
|
350
|
+
</div>
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
<div class="dev-actions">
|
|
354
|
+
<span>{{ DefaultsText }}</span>
|
|
355
|
+
<button type="button" class="link-btn" [disabled]="ChangedKeys.length === 0" (click)="OnResetToDefaults()">
|
|
356
|
+
Reset to entity defaults
|
|
357
|
+
</button>
|
|
358
|
+
</div>
|
|
359
|
+
</div>
|
|
360
|
+
</details>
|
|
361
|
+
}
|
|
362
|
+
</div>
|
|
363
|
+
`, imports: [CommonModule, FormsModule, MJSwitchComponent], changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n .scope-controls-container {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-2) 0;\n }\n\n .control-group {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n }\n\n .control-label {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .mj-select, .mj-input {\n padding: var(--mj-space-1-5) var(--mj-space-2-5);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-size: var(--mj-text-sm);\n outline: none;\n }\n\n .mj-select:focus, .mj-input:focus {\n border-color: var(--mj-brand-primary);\n }\n\n .scope-summary {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n }\n\n .summary-top {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: baseline;\n gap: var(--mj-space-2);\n }\n\n .summary-title {\n font-size: var(--mj-text-sm);\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .summary-source {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .facts {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1-5);\n }\n\n .fact {\n font-size: var(--mj-text-xs);\n padding: 3px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n }\n\n .fact.changed {\n border-color: var(--mj-status-warning-border);\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n font-weight: 600;\n }\n\n .dev-overrides {\n border: 1px solid var(--mj-status-warning-border);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n }\n\n .dev-overrides summary {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n font-weight: 600;\n font-size: var(--mj-text-sm);\n cursor: pointer;\n list-style: none;\n }\n\n .dev-overrides summary::-webkit-details-marker {\n display: none;\n }\n\n .dev-overrides summary:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: -2px;\n }\n\n .dev-count {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n }\n\n .dev-body {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n padding: var(--mj-space-3);\n background: var(--mj-bg-surface);\n }\n\n .dev-warning {\n margin: 0;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n }\n\n .field-row {\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: center;\n gap: var(--mj-space-1) var(--mj-space-3);\n }\n\n .field-row label, .toggle-label {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-primary);\n cursor: pointer;\n user-select: none;\n }\n\n .field-hint {\n grid-column: 1 / -1;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .num-input {\n width: 96px;\n font-variant-numeric: tabular-nums;\n }\n\n .dev-actions {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: var(--mj-space-2);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n }\n\n .link-btn {\n border: 0;\n background: none;\n padding: 0;\n color: var(--mj-brand-primary);\n font: inherit;\n cursor: pointer;\n }\n\n .link-btn:disabled {\n color: var(--mj-text-muted);\n cursor: default;\n }\n "] }]
|
|
364
|
+
}], null, { Presets: [{
|
|
365
|
+
type: Input
|
|
366
|
+
}], PresetLabels: [{
|
|
367
|
+
type: Input
|
|
368
|
+
}], SelectedPreset: [{
|
|
369
|
+
type: Input
|
|
370
|
+
}], MaxDepth: [{
|
|
371
|
+
type: Input
|
|
372
|
+
}], MaxRecords: [{
|
|
373
|
+
type: Input
|
|
374
|
+
}], Subtypes: [{
|
|
375
|
+
type: Input
|
|
376
|
+
}], Hierarchy: [{
|
|
377
|
+
type: Input
|
|
378
|
+
}], SoftLinks: [{
|
|
379
|
+
type: Input
|
|
380
|
+
}], EntityActions: [{
|
|
381
|
+
type: Input
|
|
382
|
+
}], ConfiguredScope: [{
|
|
383
|
+
type: Input
|
|
384
|
+
}], EntityName: [{
|
|
385
|
+
type: Input
|
|
386
|
+
}], CanOverrideScope: [{
|
|
387
|
+
type: Input
|
|
388
|
+
}], ScopeChanged: [{
|
|
389
|
+
type: Output
|
|
390
|
+
}], ResetToDefaults: [{
|
|
391
|
+
type: Output
|
|
392
|
+
}] }); })();
|
|
393
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CloneScopeControlsComponent, { className: "CloneScopeControlsComponent", filePath: "src/lib/clone-scope-controls.component.ts", lineNumber: 306 }); })();
|
|
394
|
+
//# sourceMappingURL=clone-scope-controls.component.js.map
|