@memberjunction/ng-base-forms 2.121.0 → 2.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/base-form-component.d.ts +25 -2
- package/dist/lib/base-form-component.d.ts.map +1 -1
- package/dist/lib/base-form-component.js +90 -25
- package/dist/lib/base-form-component.js.map +1 -1
- package/dist/lib/collapsible-panel.component.d.ts +3 -3
- package/dist/lib/collapsible-panel.component.d.ts.map +1 -1
- package/dist/lib/collapsible-panel.component.js +11 -20
- package/dist/lib/collapsible-panel.component.js.map +1 -1
- package/dist/lib/form-state.interface.d.ts +27 -0
- package/dist/lib/form-state.interface.d.ts.map +1 -0
- package/dist/lib/form-state.interface.js +15 -0
- package/dist/lib/form-state.interface.js.map +1 -0
- package/dist/lib/form-state.service.d.ts +153 -0
- package/dist/lib/form-state.service.d.ts.map +1 -0
- package/dist/lib/form-state.service.js +360 -0
- package/dist/lib/form-state.service.js.map +1 -0
- package/dist/lib/link-field.component.d.ts +3 -3
- package/dist/lib/link-field.component.d.ts.map +1 -1
- package/dist/lib/link-field.component.js +10 -17
- package/dist/lib/link-field.component.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { FormState, FormSectionState } from './form-state.interface';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Service for managing form state persistence per entity.
|
|
6
|
+
* State is stored in the User Settings entity and shared reactively
|
|
7
|
+
* across all form instances for the same entity.
|
|
8
|
+
*/
|
|
9
|
+
export declare class FormStateService {
|
|
10
|
+
/** Cache of BehaviorSubjects per entity name */
|
|
11
|
+
private stateCache;
|
|
12
|
+
/** Debounce timeouts per entity name */
|
|
13
|
+
private saveTimeouts;
|
|
14
|
+
/** Track which entities have been loaded from DB */
|
|
15
|
+
private loadedEntities;
|
|
16
|
+
/** Track loading promises to prevent duplicate loads */
|
|
17
|
+
private loadingPromises;
|
|
18
|
+
private metadata;
|
|
19
|
+
/**
|
|
20
|
+
* Get the observable state for an entity.
|
|
21
|
+
* Automatically loads from User Settings on first access.
|
|
22
|
+
* @param entityName The entity name
|
|
23
|
+
* @returns Observable of the form state
|
|
24
|
+
*/
|
|
25
|
+
getState$(entityName: string): Observable<FormState>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the current state value for an entity.
|
|
28
|
+
* @param entityName The entity name
|
|
29
|
+
* @returns Current form state
|
|
30
|
+
*/
|
|
31
|
+
getCurrentState(entityName: string): FormState;
|
|
32
|
+
/**
|
|
33
|
+
* Initialize state for an entity by loading from User Settings.
|
|
34
|
+
* Call this when a form component initializes.
|
|
35
|
+
* @param entityName The entity name
|
|
36
|
+
*/
|
|
37
|
+
initializeState(entityName: string): Promise<FormState>;
|
|
38
|
+
/**
|
|
39
|
+
* Get section state, returning defaults if section doesn't exist yet.
|
|
40
|
+
* @param entityName The entity name
|
|
41
|
+
* @param sectionKey The section key
|
|
42
|
+
* @returns Section state with defaults applied
|
|
43
|
+
*/
|
|
44
|
+
getSectionState(entityName: string, sectionKey: string): FormSectionState;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a section is expanded.
|
|
47
|
+
* @param entityName The entity name
|
|
48
|
+
* @param sectionKey The section key
|
|
49
|
+
* @returns True if expanded
|
|
50
|
+
*/
|
|
51
|
+
isSectionExpanded(entityName: string, sectionKey: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Set section expanded state.
|
|
54
|
+
* @param entityName The entity name
|
|
55
|
+
* @param sectionKey The section key
|
|
56
|
+
* @param isExpanded Whether the section is expanded
|
|
57
|
+
*/
|
|
58
|
+
setSectionExpanded(entityName: string, sectionKey: string, isExpanded: boolean): void;
|
|
59
|
+
/**
|
|
60
|
+
* Toggle section expanded state.
|
|
61
|
+
* @param entityName The entity name
|
|
62
|
+
* @param sectionKey The section key
|
|
63
|
+
*/
|
|
64
|
+
toggleSection(entityName: string, sectionKey: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get section width mode.
|
|
67
|
+
* @param entityName The entity name
|
|
68
|
+
* @param sectionKey The section key
|
|
69
|
+
* @returns Width mode ('normal' or 'full-width')
|
|
70
|
+
*/
|
|
71
|
+
getSectionWidthMode(entityName: string, sectionKey: string): 'normal' | 'full-width';
|
|
72
|
+
/**
|
|
73
|
+
* Set section width mode.
|
|
74
|
+
* @param entityName The entity name
|
|
75
|
+
* @param sectionKey The section key
|
|
76
|
+
* @param widthMode The width mode
|
|
77
|
+
*/
|
|
78
|
+
setSectionWidthMode(entityName: string, sectionKey: string, widthMode: 'normal' | 'full-width'): void;
|
|
79
|
+
/**
|
|
80
|
+
* Toggle section width mode between normal and full-width.
|
|
81
|
+
* @param entityName The entity name
|
|
82
|
+
* @param sectionKey The section key
|
|
83
|
+
*/
|
|
84
|
+
toggleSectionWidthMode(entityName: string, sectionKey: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get showEmptyFields preference for an entity.
|
|
87
|
+
* @param entityName The entity name
|
|
88
|
+
* @returns Whether to show empty fields
|
|
89
|
+
*/
|
|
90
|
+
getShowEmptyFields(entityName: string): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Set showEmptyFields preference for an entity.
|
|
93
|
+
* @param entityName The entity name
|
|
94
|
+
* @param show Whether to show empty fields
|
|
95
|
+
*/
|
|
96
|
+
setShowEmptyFields(entityName: string, show: boolean): void;
|
|
97
|
+
/**
|
|
98
|
+
* Expand all sections for an entity.
|
|
99
|
+
* @param entityName The entity name
|
|
100
|
+
* @param sectionKeys Array of all section keys to expand
|
|
101
|
+
*/
|
|
102
|
+
expandAllSections(entityName: string, sectionKeys: string[]): void;
|
|
103
|
+
/**
|
|
104
|
+
* Collapse all sections for an entity.
|
|
105
|
+
* @param entityName The entity name
|
|
106
|
+
* @param sectionKeys Array of all section keys to collapse
|
|
107
|
+
*/
|
|
108
|
+
collapseAllSections(entityName: string, sectionKeys: string[]): void;
|
|
109
|
+
/**
|
|
110
|
+
* Reset all panel widths to normal for an entity.
|
|
111
|
+
* @param entityName The entity name
|
|
112
|
+
*/
|
|
113
|
+
resetAllPanelWidths(entityName: string): void;
|
|
114
|
+
/**
|
|
115
|
+
* Reset state to defaults for an entity.
|
|
116
|
+
* @param entityName The entity name
|
|
117
|
+
*/
|
|
118
|
+
resetToDefaults(entityName: string): void;
|
|
119
|
+
/**
|
|
120
|
+
* Get the count of expanded sections.
|
|
121
|
+
* @param entityName The entity name
|
|
122
|
+
* @param sectionKeys Array of section keys to check
|
|
123
|
+
* @returns Number of expanded sections
|
|
124
|
+
*/
|
|
125
|
+
getExpandedCount(entityName: string, sectionKeys: string[]): number;
|
|
126
|
+
/**
|
|
127
|
+
* Get or create the BehaviorSubject for an entity.
|
|
128
|
+
*/
|
|
129
|
+
private getOrCreateSubject;
|
|
130
|
+
/**
|
|
131
|
+
* Update a single section's state.
|
|
132
|
+
*/
|
|
133
|
+
private updateSectionState;
|
|
134
|
+
/**
|
|
135
|
+
* Generate the User Settings key for an entity.
|
|
136
|
+
*/
|
|
137
|
+
private getSettingKey;
|
|
138
|
+
/**
|
|
139
|
+
* Load state from User Settings.
|
|
140
|
+
*/
|
|
141
|
+
private loadState;
|
|
142
|
+
/**
|
|
143
|
+
* Debounced save to avoid too many writes.
|
|
144
|
+
*/
|
|
145
|
+
private debouncedSave;
|
|
146
|
+
/**
|
|
147
|
+
* Save state to User Settings.
|
|
148
|
+
*/
|
|
149
|
+
private saveState;
|
|
150
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FormStateService, never>;
|
|
151
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<FormStateService>;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=form-state.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-state.service.d.ts","sourceRoot":"","sources":["../../src/lib/form-state.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAA6C,MAAM,wBAAwB,CAAC;;AAKhH;;;;GAIG;AACH,qBAGa,gBAAgB;IACzB,gDAAgD;IAChD,OAAO,CAAC,UAAU,CAAiD;IAEnE,wCAAwC;IACxC,OAAO,CAAC,YAAY,CAAoD;IAExE,oDAAoD;IACpD,OAAO,CAAC,cAAc,CAAqB;IAE3C,wDAAwD;IACxD,OAAO,CAAC,eAAe,CAAoC;IAE3D,OAAO,CAAC,QAAQ,CAAkB;IAElC;;;;;OAKG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC;IAIpD;;;;OAIG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;IAI9C;;;;OAIG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA0B7D;;;;;OAKG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB;IAKzE;;;;;OAKG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAIlE;;;;;OAKG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI;IAIrF;;;;OAIG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAK3D;;;;;OAKG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY;IAIpF;;;;;OAKG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,YAAY,GAAG,IAAI;IAIrG;;;;OAIG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAKpE;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI/C;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAW3D;;;;OAIG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;IAiBlE;;;;OAIG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;IAiBpE;;;OAGG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAa7C;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMzC;;;;;OAKG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM;IAUnE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoB1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;YACW,SAAS;IAkCvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;YACW,SAAS;yCA3Vd,gBAAgB;6CAAhB,gBAAgB;CA6X5B"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { Metadata, RunView } from '@memberjunction/core';
|
|
4
|
+
import { DEFAULT_FORM_STATE, DEFAULT_SECTION_STATE } from './form-state.interface';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
const SETTING_KEY_PREFIX = 'Form.State.';
|
|
7
|
+
const SAVE_DEBOUNCE_MS = 1000;
|
|
8
|
+
/**
|
|
9
|
+
* Service for managing form state persistence per entity.
|
|
10
|
+
* State is stored in the User Settings entity and shared reactively
|
|
11
|
+
* across all form instances for the same entity.
|
|
12
|
+
*/
|
|
13
|
+
export class FormStateService {
|
|
14
|
+
/** Cache of BehaviorSubjects per entity name */
|
|
15
|
+
stateCache = new Map();
|
|
16
|
+
/** Debounce timeouts per entity name */
|
|
17
|
+
saveTimeouts = new Map();
|
|
18
|
+
/** Track which entities have been loaded from DB */
|
|
19
|
+
loadedEntities = new Set();
|
|
20
|
+
/** Track loading promises to prevent duplicate loads */
|
|
21
|
+
loadingPromises = new Map();
|
|
22
|
+
metadata = new Metadata();
|
|
23
|
+
/**
|
|
24
|
+
* Get the observable state for an entity.
|
|
25
|
+
* Automatically loads from User Settings on first access.
|
|
26
|
+
* @param entityName The entity name
|
|
27
|
+
* @returns Observable of the form state
|
|
28
|
+
*/
|
|
29
|
+
getState$(entityName) {
|
|
30
|
+
return this.getOrCreateSubject(entityName).asObservable();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the current state value for an entity.
|
|
34
|
+
* @param entityName The entity name
|
|
35
|
+
* @returns Current form state
|
|
36
|
+
*/
|
|
37
|
+
getCurrentState(entityName) {
|
|
38
|
+
return this.getOrCreateSubject(entityName).value;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Initialize state for an entity by loading from User Settings.
|
|
42
|
+
* Call this when a form component initializes.
|
|
43
|
+
* @param entityName The entity name
|
|
44
|
+
*/
|
|
45
|
+
async initializeState(entityName) {
|
|
46
|
+
// If already loaded, return current state
|
|
47
|
+
if (this.loadedEntities.has(entityName)) {
|
|
48
|
+
return this.getCurrentState(entityName);
|
|
49
|
+
}
|
|
50
|
+
// If currently loading, wait for that promise
|
|
51
|
+
const existingPromise = this.loadingPromises.get(entityName);
|
|
52
|
+
if (existingPromise) {
|
|
53
|
+
await existingPromise;
|
|
54
|
+
return this.getCurrentState(entityName);
|
|
55
|
+
}
|
|
56
|
+
// Start loading
|
|
57
|
+
const loadPromise = this.loadState(entityName);
|
|
58
|
+
this.loadingPromises.set(entityName, loadPromise);
|
|
59
|
+
try {
|
|
60
|
+
await loadPromise;
|
|
61
|
+
this.loadedEntities.add(entityName);
|
|
62
|
+
return this.getCurrentState(entityName);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
this.loadingPromises.delete(entityName);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get section state, returning defaults if section doesn't exist yet.
|
|
70
|
+
* @param entityName The entity name
|
|
71
|
+
* @param sectionKey The section key
|
|
72
|
+
* @returns Section state with defaults applied
|
|
73
|
+
*/
|
|
74
|
+
getSectionState(entityName, sectionKey) {
|
|
75
|
+
const state = this.getCurrentState(entityName);
|
|
76
|
+
return state.sections[sectionKey] || { ...DEFAULT_SECTION_STATE };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if a section is expanded.
|
|
80
|
+
* @param entityName The entity name
|
|
81
|
+
* @param sectionKey The section key
|
|
82
|
+
* @returns True if expanded
|
|
83
|
+
*/
|
|
84
|
+
isSectionExpanded(entityName, sectionKey) {
|
|
85
|
+
return this.getSectionState(entityName, sectionKey).isExpanded;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Set section expanded state.
|
|
89
|
+
* @param entityName The entity name
|
|
90
|
+
* @param sectionKey The section key
|
|
91
|
+
* @param isExpanded Whether the section is expanded
|
|
92
|
+
*/
|
|
93
|
+
setSectionExpanded(entityName, sectionKey, isExpanded) {
|
|
94
|
+
this.updateSectionState(entityName, sectionKey, { isExpanded });
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Toggle section expanded state.
|
|
98
|
+
* @param entityName The entity name
|
|
99
|
+
* @param sectionKey The section key
|
|
100
|
+
*/
|
|
101
|
+
toggleSection(entityName, sectionKey) {
|
|
102
|
+
const current = this.isSectionExpanded(entityName, sectionKey);
|
|
103
|
+
this.setSectionExpanded(entityName, sectionKey, !current);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get section width mode.
|
|
107
|
+
* @param entityName The entity name
|
|
108
|
+
* @param sectionKey The section key
|
|
109
|
+
* @returns Width mode ('normal' or 'full-width')
|
|
110
|
+
*/
|
|
111
|
+
getSectionWidthMode(entityName, sectionKey) {
|
|
112
|
+
return this.getSectionState(entityName, sectionKey).widthMode;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Set section width mode.
|
|
116
|
+
* @param entityName The entity name
|
|
117
|
+
* @param sectionKey The section key
|
|
118
|
+
* @param widthMode The width mode
|
|
119
|
+
*/
|
|
120
|
+
setSectionWidthMode(entityName, sectionKey, widthMode) {
|
|
121
|
+
this.updateSectionState(entityName, sectionKey, { widthMode });
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Toggle section width mode between normal and full-width.
|
|
125
|
+
* @param entityName The entity name
|
|
126
|
+
* @param sectionKey The section key
|
|
127
|
+
*/
|
|
128
|
+
toggleSectionWidthMode(entityName, sectionKey) {
|
|
129
|
+
const current = this.getSectionWidthMode(entityName, sectionKey);
|
|
130
|
+
this.setSectionWidthMode(entityName, sectionKey, current === 'normal' ? 'full-width' : 'normal');
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get showEmptyFields preference for an entity.
|
|
134
|
+
* @param entityName The entity name
|
|
135
|
+
* @returns Whether to show empty fields
|
|
136
|
+
*/
|
|
137
|
+
getShowEmptyFields(entityName) {
|
|
138
|
+
return this.getCurrentState(entityName).showEmptyFields;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Set showEmptyFields preference for an entity.
|
|
142
|
+
* @param entityName The entity name
|
|
143
|
+
* @param show Whether to show empty fields
|
|
144
|
+
*/
|
|
145
|
+
setShowEmptyFields(entityName, show) {
|
|
146
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
147
|
+
const currentState = subject.value;
|
|
148
|
+
const newState = {
|
|
149
|
+
...currentState,
|
|
150
|
+
showEmptyFields: show
|
|
151
|
+
};
|
|
152
|
+
subject.next(newState);
|
|
153
|
+
this.debouncedSave(entityName);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Expand all sections for an entity.
|
|
157
|
+
* @param entityName The entity name
|
|
158
|
+
* @param sectionKeys Array of all section keys to expand
|
|
159
|
+
*/
|
|
160
|
+
expandAllSections(entityName, sectionKeys) {
|
|
161
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
162
|
+
const currentState = subject.value;
|
|
163
|
+
const newSections = { ...currentState.sections };
|
|
164
|
+
for (const key of sectionKeys) {
|
|
165
|
+
newSections[key] = {
|
|
166
|
+
...DEFAULT_SECTION_STATE,
|
|
167
|
+
...newSections[key],
|
|
168
|
+
isExpanded: true
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
subject.next({ ...currentState, sections: newSections });
|
|
172
|
+
this.debouncedSave(entityName);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Collapse all sections for an entity.
|
|
176
|
+
* @param entityName The entity name
|
|
177
|
+
* @param sectionKeys Array of all section keys to collapse
|
|
178
|
+
*/
|
|
179
|
+
collapseAllSections(entityName, sectionKeys) {
|
|
180
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
181
|
+
const currentState = subject.value;
|
|
182
|
+
const newSections = { ...currentState.sections };
|
|
183
|
+
for (const key of sectionKeys) {
|
|
184
|
+
newSections[key] = {
|
|
185
|
+
...DEFAULT_SECTION_STATE,
|
|
186
|
+
...newSections[key],
|
|
187
|
+
isExpanded: false
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
subject.next({ ...currentState, sections: newSections });
|
|
191
|
+
this.debouncedSave(entityName);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Reset all panel widths to normal for an entity.
|
|
195
|
+
* @param entityName The entity name
|
|
196
|
+
*/
|
|
197
|
+
resetAllPanelWidths(entityName) {
|
|
198
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
199
|
+
const currentState = subject.value;
|
|
200
|
+
const newSections = {};
|
|
201
|
+
for (const [key, section] of Object.entries(currentState.sections)) {
|
|
202
|
+
newSections[key] = { ...section, widthMode: 'normal' };
|
|
203
|
+
}
|
|
204
|
+
subject.next({ ...currentState, sections: newSections });
|
|
205
|
+
this.debouncedSave(entityName);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Reset state to defaults for an entity.
|
|
209
|
+
* @param entityName The entity name
|
|
210
|
+
*/
|
|
211
|
+
resetToDefaults(entityName) {
|
|
212
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
213
|
+
subject.next({ ...DEFAULT_FORM_STATE });
|
|
214
|
+
this.debouncedSave(entityName);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get the count of expanded sections.
|
|
218
|
+
* @param entityName The entity name
|
|
219
|
+
* @param sectionKeys Array of section keys to check
|
|
220
|
+
* @returns Number of expanded sections
|
|
221
|
+
*/
|
|
222
|
+
getExpandedCount(entityName, sectionKeys) {
|
|
223
|
+
const state = this.getCurrentState(entityName);
|
|
224
|
+
return sectionKeys.filter(key => {
|
|
225
|
+
const section = state.sections[key];
|
|
226
|
+
return section ? section.isExpanded : DEFAULT_SECTION_STATE.isExpanded;
|
|
227
|
+
}).length;
|
|
228
|
+
}
|
|
229
|
+
// -------------------- Private Methods --------------------
|
|
230
|
+
/**
|
|
231
|
+
* Get or create the BehaviorSubject for an entity.
|
|
232
|
+
*/
|
|
233
|
+
getOrCreateSubject(entityName) {
|
|
234
|
+
let subject = this.stateCache.get(entityName);
|
|
235
|
+
if (!subject) {
|
|
236
|
+
subject = new BehaviorSubject({ ...DEFAULT_FORM_STATE });
|
|
237
|
+
this.stateCache.set(entityName, subject);
|
|
238
|
+
}
|
|
239
|
+
return subject;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Update a single section's state.
|
|
243
|
+
*/
|
|
244
|
+
updateSectionState(entityName, sectionKey, updates) {
|
|
245
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
246
|
+
const currentState = subject.value;
|
|
247
|
+
const currentSection = currentState.sections[sectionKey] || { ...DEFAULT_SECTION_STATE };
|
|
248
|
+
const newState = {
|
|
249
|
+
...currentState,
|
|
250
|
+
sections: {
|
|
251
|
+
...currentState.sections,
|
|
252
|
+
[sectionKey]: {
|
|
253
|
+
...currentSection,
|
|
254
|
+
...updates
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
subject.next(newState);
|
|
259
|
+
this.debouncedSave(entityName);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Generate the User Settings key for an entity.
|
|
263
|
+
*/
|
|
264
|
+
getSettingKey(entityName) {
|
|
265
|
+
return `${SETTING_KEY_PREFIX}${entityName}`;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Load state from User Settings.
|
|
269
|
+
*/
|
|
270
|
+
async loadState(entityName) {
|
|
271
|
+
try {
|
|
272
|
+
const userId = this.metadata.CurrentUser?.ID;
|
|
273
|
+
if (!userId) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const settingKey = this.getSettingKey(entityName);
|
|
277
|
+
const rv = new RunView();
|
|
278
|
+
const result = await rv.RunView({
|
|
279
|
+
EntityName: 'MJ: User Settings',
|
|
280
|
+
ExtraFilter: `UserID='${userId}' AND Setting='${settingKey}'`,
|
|
281
|
+
ResultType: 'entity_object'
|
|
282
|
+
});
|
|
283
|
+
const subject = this.getOrCreateSubject(entityName);
|
|
284
|
+
if (result.Success && result.Results.length > 0) {
|
|
285
|
+
const setting = result.Results[0];
|
|
286
|
+
if (setting.Value) {
|
|
287
|
+
const savedState = JSON.parse(setting.Value);
|
|
288
|
+
// Merge with defaults to handle new properties
|
|
289
|
+
subject.next({ ...DEFAULT_FORM_STATE, ...savedState });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// No saved state, use defaults
|
|
294
|
+
subject.next({ ...DEFAULT_FORM_STATE });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
console.warn(`Failed to load form state for ${entityName}:`, error);
|
|
299
|
+
// Keep default state on error
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Debounced save to avoid too many writes.
|
|
304
|
+
*/
|
|
305
|
+
debouncedSave(entityName) {
|
|
306
|
+
const existingTimeout = this.saveTimeouts.get(entityName);
|
|
307
|
+
if (existingTimeout) {
|
|
308
|
+
clearTimeout(existingTimeout);
|
|
309
|
+
}
|
|
310
|
+
const timeout = setTimeout(() => {
|
|
311
|
+
this.saveState(entityName);
|
|
312
|
+
this.saveTimeouts.delete(entityName);
|
|
313
|
+
}, SAVE_DEBOUNCE_MS);
|
|
314
|
+
this.saveTimeouts.set(entityName, timeout);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Save state to User Settings.
|
|
318
|
+
*/
|
|
319
|
+
async saveState(entityName) {
|
|
320
|
+
try {
|
|
321
|
+
const userId = this.metadata.CurrentUser?.ID;
|
|
322
|
+
if (!userId) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const settingKey = this.getSettingKey(entityName);
|
|
326
|
+
const state = this.getCurrentState(entityName);
|
|
327
|
+
const md = new Metadata();
|
|
328
|
+
const rv = new RunView();
|
|
329
|
+
// Check if setting exists
|
|
330
|
+
const result = await rv.RunView({
|
|
331
|
+
EntityName: 'MJ: User Settings',
|
|
332
|
+
ExtraFilter: `UserID='${userId}' AND Setting='${settingKey}'`,
|
|
333
|
+
ResultType: 'entity_object'
|
|
334
|
+
});
|
|
335
|
+
let setting;
|
|
336
|
+
if (result.Success && result.Results.length > 0) {
|
|
337
|
+
setting = result.Results[0];
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
setting = await md.GetEntityObject('MJ: User Settings');
|
|
341
|
+
setting.UserID = userId;
|
|
342
|
+
setting.Setting = settingKey;
|
|
343
|
+
}
|
|
344
|
+
setting.Value = JSON.stringify(state);
|
|
345
|
+
await setting.Save();
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
console.warn(`Failed to save form state for ${entityName}:`, error);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
static ɵfac = function FormStateService_Factory(t) { return new (t || FormStateService)(); };
|
|
352
|
+
static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: FormStateService, factory: FormStateService.ɵfac, providedIn: 'root' });
|
|
353
|
+
}
|
|
354
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FormStateService, [{
|
|
355
|
+
type: Injectable,
|
|
356
|
+
args: [{
|
|
357
|
+
providedIn: 'root'
|
|
358
|
+
}]
|
|
359
|
+
}], null, null); })();
|
|
360
|
+
//# sourceMappingURL=form-state.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-state.service.js","sourceRoot":"","sources":["../../src/lib/form-state.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AfterViewInit, ElementRef, ChangeDetectorRef } from "@angular/core";
|
|
2
2
|
import { BaseRecordComponent } from "./base-record-component";
|
|
3
3
|
import { BaseEntity, EntityFieldInfo, EntityInfo } from "@memberjunction/core";
|
|
4
|
-
import {
|
|
4
|
+
import { NavigationService } from "@memberjunction/ng-shared";
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
/**
|
|
7
7
|
* This component is used to automatically generate a UI for any field in a given BaseEntity object. The CodeGen tool will generate forms and form sections that
|
|
@@ -11,8 +11,8 @@ import * as i0 from "@angular/core";
|
|
|
11
11
|
*/
|
|
12
12
|
export declare class MJLinkField extends BaseRecordComponent implements AfterViewInit {
|
|
13
13
|
private cdr;
|
|
14
|
-
private
|
|
15
|
-
constructor(cdr: ChangeDetectorRef,
|
|
14
|
+
private navigationService;
|
|
15
|
+
constructor(cdr: ChangeDetectorRef, navigationService: NavigationService);
|
|
16
16
|
/**
|
|
17
17
|
* The record object that contains the field to be rendered. This object should be an instance of BaseEntity or a derived class.
|
|
18
18
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-field.component.d.ts","sourceRoot":"","sources":["../../src/lib/link-field.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAoB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"link-field.component.d.ts","sourceRoot":"","sources":["../../src/lib/link-field.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAoB,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAgB,eAAe,EAAE,UAAU,EAAqB,MAAM,sBAAsB,CAAC;AAEhH,OAAO,EAAiB,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;;AAE7E;;;;;GAKG;AACH,qBAKa,WAAY,SAAQ,mBAAoB,YAAW,aAAa;IAC7D,OAAO,CAAC,GAAG;IAAqB,OAAO,CAAC,iBAAiB;gBAAjD,GAAG,EAAE,iBAAiB,EAAU,iBAAiB,EAAE,iBAAiB;IAGxF;;OAEG;IACM,MAAM,EAAG,UAAU,CAAC;IAE7B;;OAEG;IACM,SAAS,EAAE,MAAM,CAAM;IAEhC;;OAEG;IACM,UAAU,CAAC,EAAE,MAAM,CAAM;IAElC;;;OAGG;IACM,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAY;IAEvD,iBAAiB,EAAE,UAAU,GAAG,SAAS,CAAa;IAE7D,OAAO,CAAC,eAAe,CAAqC;IAC5D,IAAW,cAAc,IAAI,UAAU,GAAG,SAAS,CAElD;IACD,IAAW,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,EAOpD;IACM,YAAY,EAAE,OAAO,CAAS;IAC9B,oBAAoB,EAAE,UAAU,EAAE,CAAM;IACxC,mBAAmB,EAAE,OAAO,CAAS;IACrC,eAAe,EAAE,eAAe,EAAE,CAAM;IAEL,QAAQ,EAAG,UAAU,CAAC;YAElD,aAAa;IA0CrB,eAAe;IAIrB,OAAO,CAAC,mCAAmC,CAAwB;IACnE,IAAW,4BAA4B,IAAI,OAAO,CAcjD;IAEM,YAAY;cAcH,kBAAkB;IAoBlC,IAAW,KAAK,IAAI,GAAG,CAEtB;IAED,IAAW,KAAK,CAAC,GAAG,EAAE,GAAG,EAQxB;IAED,IAAW,WAAW,IAAI,eAAe,GAAG,SAAS,CAEpD;IACD,IAAW,WAAW,IAAI,MAAM,CAM/B;IAGM,cAAc;IAOd,sBAAsB,EAAE,MAAM,CAAM;cAC3B,oBAAoB,CAAC,KAAK,EAAE,MAAM;IAuD3C,sBAAsB,CAAC,MAAM,EAAE,GAAG;cAazB,oBAAoB;cA4BpB,gBAAgB;IAIzB,gBAAgB,CAAC,YAAY,EAAE,UAAU;yCArRvC,WAAW;2CAAX,WAAW;CAsSvB"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Component, Input, ViewChild } from "@angular/core";
|
|
2
2
|
import { BaseRecordComponent } from "./base-record-component";
|
|
3
|
-
import { CompositeKey,
|
|
3
|
+
import { CompositeKey, Metadata, RunView } from "@memberjunction/core";
|
|
4
4
|
import { debounceTime, fromEvent } from 'rxjs';
|
|
5
5
|
import { SharedService } from "@memberjunction/ng-shared";
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
|
-
import * as i1 from "@
|
|
7
|
+
import * as i1 from "@memberjunction/ng-shared";
|
|
8
8
|
import * as i2 from "@angular/common";
|
|
9
9
|
import * as i3 from "@angular/forms";
|
|
10
10
|
import * as i4 from "@progress/kendo-angular-buttons";
|
|
@@ -93,11 +93,11 @@ function MJLinkField_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
93
93
|
*/
|
|
94
94
|
export class MJLinkField extends BaseRecordComponent {
|
|
95
95
|
cdr;
|
|
96
|
-
|
|
97
|
-
constructor(cdr,
|
|
96
|
+
navigationService;
|
|
97
|
+
constructor(cdr, navigationService) {
|
|
98
98
|
super();
|
|
99
99
|
this.cdr = cdr;
|
|
100
|
-
this.
|
|
100
|
+
this.navigationService = navigationService;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* The record object that contains the field to be rendered. This object should be an instance of BaseEntity or a derived class.
|
|
@@ -194,15 +194,8 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
194
194
|
onNewClicked() {
|
|
195
195
|
// user wants to create a new record, double check to make sure we can create a record
|
|
196
196
|
if (this.UserCanCreateNewLinkedRecord && this.RelatedEntityInfo) {
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
const newURL = ['resource', 'record', keyVals];
|
|
200
|
-
this.router.navigate(newURL, { queryParams: { Entity: this.RelatedEntityInfo.Name } }).then(params => {
|
|
201
|
-
console.log('navigated to:', newURL.join('/'));
|
|
202
|
-
}).catch(err => {
|
|
203
|
-
const newURLString = newURL.join('/');
|
|
204
|
-
LogError(`Error navigating to ${newURLString}: ${err}`);
|
|
205
|
-
});
|
|
197
|
+
// Use NavigationService to open a new record form
|
|
198
|
+
this.navigationService.OpenNewEntityRecord(this.RelatedEntityInfo.Name);
|
|
206
199
|
}
|
|
207
200
|
else {
|
|
208
201
|
// user can't create a new record, so let's tell them
|
|
@@ -364,7 +357,7 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
364
357
|
}
|
|
365
358
|
this.cdr.detectChanges();
|
|
366
359
|
}
|
|
367
|
-
static ɵfac = function MJLinkField_Factory(t) { return new (t || MJLinkField)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.
|
|
360
|
+
static ɵfac = function MJLinkField_Factory(t) { return new (t || MJLinkField)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.NavigationService)); };
|
|
368
361
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJLinkField, selectors: [["mj-link-field"]], viewQuery: function MJLinkField_Query(rf, ctx) { if (rf & 1) {
|
|
369
362
|
i0.ɵɵviewQuery(_c0, 5);
|
|
370
363
|
} if (rf & 2) {
|
|
@@ -382,7 +375,7 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
382
375
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJLinkField, [{
|
|
383
376
|
type: Component,
|
|
384
377
|
args: [{ selector: 'mj-link-field', template: "<div>\n @if (LinkComponentType === 'Search') {\n <input \n #inputBox\n type=\"text\" \n class=\"input-box\" \n [ngClass]=\"RecordLinked ? 'record-linked' : ''\" \n [(ngModel)]=\"RecordName\" \n kendoTextBox \n />\n <button kendoButton (click)=\"onClearClicked()\" title=\"Clear\" [ngClass]=\"UserCanCreateNewLinkedRecord ? '' : 'last-button-in-row'\"><span class=\"fa-solid fa-delete-left\"></span></button>\n @if (UserCanCreateNewLinkedRecord) {\n <button kendoButton (click)=\"onNewClicked()\" title=\"Create New Record\" class=\"last-button-in-row\"><span class=\"fa-solid fa-plus\"></span></button>\n }\n\n <ul *ngIf=\"showMatchingRecords\" class=\"matching-records\">\n <li *ngFor=\"let record of RelatedEntityRecords\" (click)=\"onRecordSelected(record)\">\n {{ GetRecordDisplayString(record)}}\n </li>\n </ul>\n }\n @else {\n @if (RelatedEntityInfo) {\n <kendo-multicolumncombobox \n [data]=\"RelatedEntityRecords\"\n [textField]=\"RelatedEntityInfo.NameField ? RelatedEntityInfo.NameField.Name : RelatedEntityInfo.FirstPrimaryKey.Name\"\n [valueField]=\"RelatedEntityInfo.FirstPrimaryKey.Name\"\n [(value)]=\"SelectedRecord\"\n >\n @for (d of dropDownColumns; track d) {\n <kendo-combobox-column\n [field]=\"d.Name\"\n [title]=\"d.DisplayNameOrName\"\n >\n </kendo-combobox-column>\n }\n </kendo-multicolumncombobox> \n }\n }\n</div>", styles: [".record-linked {\n color: darkblue;\n text-decoration: underline;\n}\n\n.input-box {\n width: 406px;\n border-radius: 3px 0 0 3px; /* top-left, top-right, bottom-right, bottom-left don't make the right/top and right/bottom rounded so it ties up to the buttons better */\n}\n\nbutton {\n width: 28px;\n border-radius: 0 0 0 0; \n border-left: 0; /* remove the left border */\n}\n\nbutton.last-button-in-row {\n border-radius: 0 3px 3px 0; /*round the top right and bottom right for the last button only*/ \n}\n\n.matching-records {\n width: 406px;\n list-style-type: none;\n margin: 0;\n padding: 0;\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid #ccc;\n}\n\n.matching-records li {\n padding: 8px;\n cursor: pointer;\n}\n\n.matching-records li:hover {\n background-color: #f0f0f0;\n}\n"] }]
|
|
385
|
-
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.
|
|
378
|
+
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.NavigationService }], { record: [{
|
|
386
379
|
type: Input
|
|
387
380
|
}], FieldName: [{
|
|
388
381
|
type: Input
|
|
@@ -394,5 +387,5 @@ export class MJLinkField extends BaseRecordComponent {
|
|
|
394
387
|
type: ViewChild,
|
|
395
388
|
args: ['inputBox', { static: false }]
|
|
396
389
|
}] }); })();
|
|
397
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJLinkField, { className: "MJLinkField", filePath: "src/lib/link-field.component.ts", lineNumber:
|
|
390
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJLinkField, { className: "MJLinkField", filePath: "src/lib/link-field.component.ts", lineNumber: 18 }); })();
|
|
398
391
|
//# sourceMappingURL=link-field.component.js.map
|