pict-section-recordset 1.0.57 → 1.0.59
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/docs/.nojekyll +0 -0
- package/docs/README.md +76 -0
- package/docs/_sidebar.md +19 -0
- package/docs/api-reference.md +233 -0
- package/docs/cover.md +11 -0
- package/docs/filters.md +151 -0
- package/docs/index.html +51 -0
- package/docs/record-providers.md +155 -0
- package/docs/views/create/README.md +181 -0
- package/docs/views/dashboard/README.md +308 -0
- package/docs/views/list/README.md +260 -0
- package/docs/views/read/README.md +216 -0
- package/example_applications/README.md +25 -1
- package/package.json +11 -10
- package/source/application/Pict-Application-RecordSet.js +6 -0
- package/source/providers/Filter-Data-Provider.js +611 -187
- package/source/views/Filter-PersistenceView.js +534 -0
- package/source/views/RecordSet-Filters.js +141 -28
- package/test/PictSectionRecordSet-Basic_tests.js +39 -16
- package/test/PictSectionRecordSet-Filter-Data-Provider_tests.js +263 -0
- package/test/PictSectionRecordSet-RecordProvider-Meadow_tests.js +5 -3
- package/types/application/Pict-Application-RecordSet.d.ts.map +1 -1
- package/types/providers/Filter-Data-Provider.d.ts +225 -52
- package/types/providers/Filter-Data-Provider.d.ts.map +1 -1
- package/types/views/Filter-PersistenceView.d.ts +104 -0
- package/types/views/Filter-PersistenceView.d.ts.map +1 -0
- package/types/views/RecordSet-Filters.d.ts +43 -10
- package/types/views/RecordSet-Filters.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-Base-Range.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-Base.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-DateMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-DateRange.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateRange.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericRange.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinDateMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinDateRange.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericRange.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValue.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-NumericMatch.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-NumericRange.d.ts.map +1 -1
|
@@ -3,11 +3,53 @@ const libPictProvider = require('pict-provider');
|
|
|
3
3
|
const _DEFAULT_PROVIDER_CONFIGURATION =
|
|
4
4
|
{
|
|
5
5
|
ProviderIdentifier: 'FilterDataProvider',
|
|
6
|
-
|
|
7
6
|
AutoInitialize: true,
|
|
8
7
|
AutoInitializeOrdinal: 0,
|
|
9
8
|
};
|
|
10
9
|
|
|
10
|
+
/** Terminology for Filter Data Provider (to avoid confusion):
|
|
11
|
+
* A "Record Set" is a collection of records that can be filtered.
|
|
12
|
+
* A "Filter Experience" is a saved state of filters for a given record set.
|
|
13
|
+
* A "Filter Experience Hash" is a unique identifier for a Filter Experience (display name converted to a hash).
|
|
14
|
+
* A "Filter Experience Encoded URL Param" is the URL-encoded representation of the filter state for a Filter Experience.
|
|
15
|
+
* A "Filter Display Name" is a user-friendly name for a Filter Experience to select/view in the UI.
|
|
16
|
+
* A "Filter Clauses" is a list of all saved filters in the "Filter Experience" for a given Record Set.
|
|
17
|
+
* A "Filter Meta" is the metadata associated with a Filter Experience, including the Filter Clauses and Filter Display Name.
|
|
18
|
+
|
|
19
|
+
* Behavior Summary:
|
|
20
|
+
* - Save Filter Meta to LocalStorage under a key derived from Record Set, View Context, and Filter Experience Hash.
|
|
21
|
+
* - Load Filter Meta from LocalStorage using the same key.
|
|
22
|
+
* - Remove Filter Meta from LocalStorage when requested.
|
|
23
|
+
* - List all Filter Experiences for a given Record Set by scanning LocalStorage keys.
|
|
24
|
+
* - Manage default and last used Filter Experiences for each Record Set and View Context. (last used takes priority over default on load, if the check is enabled)
|
|
25
|
+
|
|
26
|
+
* Storage Key Structure:
|
|
27
|
+
* - Filter_Meta_{RecordSet}_{ViewContext}_{FilterExperienceHash} : stores the Filter Meta JSON.
|
|
28
|
+
|
|
29
|
+
* Object Shape for Filter Meta (filter experience):
|
|
30
|
+
* {
|
|
31
|
+
* RecordSet: string, (auto-filled on save)
|
|
32
|
+
* ViewContext: string, (auto-filled on save)
|
|
33
|
+
* LastModifiedDate: string (ISO date) (auto-filled on save)
|
|
34
|
+
* FilterClauses: Array<{ Label: string, ExactMatch: boolean, Value: string }>,
|
|
35
|
+
* FilterDisplayName: string,
|
|
36
|
+
* FilterExperienceHash: string, (display name converted to hash)
|
|
37
|
+
* FilterExperienceEncodedURLParam: string, (URL-encoded filter state)
|
|
38
|
+
|
|
39
|
+
* Object Shape for Filter Experience Settings:
|
|
40
|
+
* {
|
|
41
|
+
* ExcludedFromSelection: boolean,
|
|
42
|
+
* RememberLastUsedFilterExperience: boolean,
|
|
43
|
+
* LastUsedFilterExperienceHash: string | null,
|
|
44
|
+
* LastUsedFilterExperienceURLParam: string | null,
|
|
45
|
+
* DefaultFilterExperienceHash: string | null,
|
|
46
|
+
* DefaultFilterExperienceURLParam: string | null,
|
|
47
|
+
* FallbackDefaultExperienceURLParam: string | null,
|
|
48
|
+
* }
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
// TODO: would nice to convert the comments above to actual types for better clarity and enforcement, but could use help on how to do that.
|
|
52
|
+
|
|
11
53
|
class FilterDataProvider extends libPictProvider
|
|
12
54
|
{
|
|
13
55
|
/**
|
|
@@ -27,309 +69,692 @@ class FilterDataProvider extends libPictProvider
|
|
|
27
69
|
{
|
|
28
70
|
this.storageProvider = window.localStorage;
|
|
29
71
|
}
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
this.lastFilterExperienceHashMap = { };
|
|
72
|
+
// use this to track if we have unapplied filter changes
|
|
73
|
+
this.filterExperienceModifiedFromURLHash = false;
|
|
33
74
|
}
|
|
34
75
|
|
|
35
76
|
onBeforeInitialize()
|
|
36
77
|
{
|
|
37
|
-
this.loadFilters();
|
|
38
|
-
|
|
39
78
|
return super.onBeforeInitialize();
|
|
40
79
|
}
|
|
41
80
|
|
|
81
|
+
/** ===== UTILITY for Filter Experience ============= */
|
|
82
|
+
|
|
42
83
|
/**
|
|
43
|
-
*
|
|
84
|
+
* Using the information in the FilterClauses, try to generate a contextual default filter name for the display name of the current experience.
|
|
85
|
+
*
|
|
86
|
+
* @param {object} pFilterExperience - The filter experience to generate the default filter name for
|
|
87
|
+
* @param {string} [pRecordSet] - The current record set
|
|
88
|
+
* @param {string} [pViewContext] - The current view context
|
|
89
|
+
* @return {string} - The generated default filter name
|
|
44
90
|
*/
|
|
45
|
-
|
|
91
|
+
generateContextualDefaultFilterName(pFilterExperience, pRecordSet, pViewContext)
|
|
92
|
+
{
|
|
93
|
+
// if there is a display name, use that
|
|
94
|
+
if (pFilterExperience && pFilterExperience.FilterDisplayName && pFilterExperience.FilterDisplayName.length > 0)
|
|
95
|
+
{
|
|
96
|
+
return pFilterExperience.FilterDisplayName;
|
|
97
|
+
}
|
|
98
|
+
// otherwise, generate one based on the clauses
|
|
99
|
+
const tmpDisplayClauseLimit = 3;
|
|
100
|
+
const tmpRecordSet = pFilterExperience?.RecordSet || pRecordSet || '';
|
|
101
|
+
const tmpClauses = pFilterExperience?.FilterClauses || this.pict.Bundle._ActiveFilterState[tmpRecordSet]?.FilterClauses || [];
|
|
102
|
+
const displayClauses = tmpClauses.length > tmpDisplayClauseLimit ? tmpClauses.slice(0, tmpDisplayClauseLimit) : tmpClauses;
|
|
103
|
+
if (tmpClauses && tmpClauses.length > 0)
|
|
104
|
+
{
|
|
105
|
+
let tmpStringSuffix = '';
|
|
106
|
+
if (tmpClauses.length > tmpDisplayClauseLimit)
|
|
107
|
+
{
|
|
108
|
+
|
|
109
|
+
tmpStringSuffix = `... (${tmpClauses.length} total filters)`;
|
|
110
|
+
}
|
|
111
|
+
const clauseSummaries = displayClauses.map((clause) => {
|
|
112
|
+
return `${clause.Label || clause.FilterByColumn}`;
|
|
113
|
+
// TODO: We could provide exact values, but we need to account for all the internal/external entity look ups, plus selection handlers on each filter to update the value entered
|
|
114
|
+
// For now, let's just show the column/label since this is a generated suggestion name and will likely to be edited by the user to something more meaningful before saving, but this is an area we could enhance in the future to make the generated names more descriptive
|
|
115
|
+
//return `${clause.Label || clause.FilterByColumn} ${clause.ExactMatch ? 'IS' : 'CONTAINS'} ${clause.Value || clause?.Values?.join(',') || '(unset)'}`;
|
|
116
|
+
});
|
|
117
|
+
return `${clauseSummaries.join(' AND ')}${ tmpStringSuffix }`;
|
|
118
|
+
}
|
|
119
|
+
// give up, fall back to default name
|
|
120
|
+
return `New ${pRecordSet} ${pViewContext} Filter`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Re-render all views affected by a filter change.
|
|
125
|
+
* @param {object} tmpFilterExperience - The filter meta record that was changed/added.
|
|
126
|
+
* @param {string} pRecordSet - The record set to check.
|
|
127
|
+
* @param {string} pViewContext - The current view context
|
|
128
|
+
*/
|
|
129
|
+
navigateToFilterExperienceRoute(tmpFilterExperience, pRecordSet, pViewContext)
|
|
46
130
|
{
|
|
47
|
-
//
|
|
131
|
+
// go to the new url with the filter experience encoded param
|
|
132
|
+
if (tmpFilterExperience?.FilterExperienceEncodedURLParam && tmpFilterExperience?.FilterExperienceEncodedURLParam?.length > 0)
|
|
133
|
+
{
|
|
134
|
+
this.fable.providers.RecordSetRouter.pictRouter.navigate(`/PSRS/${pRecordSet}/${pViewContext}/FilterExperience/${tmpFilterExperience.FilterExperienceEncodedURLParam}`);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
console.info('No FilterExperienceEncodedURLParam found for the current filter experience; navigating to base record set URL.');
|
|
139
|
+
this.fable.providers.RecordSetRouter.pictRouter.navigate(`/PSRS/${pRecordSet}/${pViewContext}`);
|
|
140
|
+
}
|
|
48
141
|
}
|
|
49
142
|
|
|
50
143
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @param {string} pRecordSet -
|
|
54
|
-
*
|
|
55
|
-
* @return
|
|
144
|
+
* Apply the expected filter experience to load on application load for a given record set and view context. Last Used takes priority over Default.
|
|
145
|
+
* This is the main entry point to set the default/latest filter experience on app load for a given record set and view context.
|
|
146
|
+
* @param {string} pRecordSet - The record set to set the default filter experience for
|
|
147
|
+
* @param {string} pViewContext - The current view context
|
|
148
|
+
* @return {boolean} - Returns true when the default filter experience has been set
|
|
56
149
|
*/
|
|
57
|
-
|
|
150
|
+
applyExpectedFilterExperience(pRecordSet, pViewContext)
|
|
58
151
|
{
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
152
|
+
const applyLastUsed = this.getRememberLastUsedFilterExperience(pRecordSet, pViewContext);
|
|
153
|
+
if (applyLastUsed)
|
|
154
|
+
{
|
|
155
|
+
// first try to set last used filter experience as default on load
|
|
156
|
+
const tmpLastUsedFilterExperience = this.getLastUsedFilterExperience(pRecordSet, pViewContext);
|
|
157
|
+
if (tmpLastUsedFilterExperience)
|
|
158
|
+
{
|
|
159
|
+
this.pict.log.info(`Applying last used filter experience on load for record set: ${pRecordSet} with view context: ${pViewContext}`);
|
|
160
|
+
// if we are already on the last used filter experience by URL, skip loading it again
|
|
161
|
+
if (this.isCurrentFilterExperience(pRecordSet, pViewContext, tmpLastUsedFilterExperience.FilterExperienceHash))
|
|
162
|
+
{
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
this.loadFilterMeta(pRecordSet, pViewContext, tmpLastUsedFilterExperience.FilterExperienceHash, true);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// if no last used filter experience, fall back to default filter experience on load
|
|
170
|
+
const tmpDefaultFilterExperience = this.getDefaultFilterExperience(pRecordSet, pViewContext);
|
|
171
|
+
if (tmpDefaultFilterExperience)
|
|
172
|
+
{
|
|
173
|
+
this.pict.log.info(`Applying default filter experience on load for record set: ${pRecordSet} with view context: ${pViewContext}`);
|
|
174
|
+
// if we are already on the default filter experience by URL, skip loading it again
|
|
175
|
+
if (this.isCurrentFilterExperience(pRecordSet, pViewContext, tmpDefaultFilterExperience.FilterExperienceHash))
|
|
176
|
+
{
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
this.loadFilterMeta(pRecordSet, pViewContext, tmpDefaultFilterExperience.FilterExperienceHash, true);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
// finally, check for a fallback default experience URL param to load (could be server/customer provided)
|
|
183
|
+
const tmpFallbackDefaultExperienceURLParam = this.getFallbackDefaultFilterExperienceSettings(pRecordSet, pViewContext);
|
|
184
|
+
if (tmpFallbackDefaultExperienceURLParam)
|
|
185
|
+
{
|
|
186
|
+
if (tmpFallbackDefaultExperienceURLParam && tmpFallbackDefaultExperienceURLParam.length > 0)
|
|
187
|
+
{
|
|
188
|
+
this.pict.log.info(`Applying fallback default filter experience URL param on load for record set: ${pRecordSet} with view context: ${pViewContext}`);
|
|
189
|
+
this.fable.providers.RecordSetRouter.pictRouter.navigate(`/PSRS/${pRecordSet}/${pViewContext}/FilterExperience/${tmpFallbackDefaultExperienceURLParam}`);
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// no filter experience to apply
|
|
194
|
+
return false;
|
|
63
195
|
}
|
|
64
196
|
|
|
197
|
+
/** ===== CRUD Filter Experiences ============= */
|
|
198
|
+
|
|
65
199
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* @
|
|
200
|
+
* Initialize the filter experience settings for a given record set and view context if they do not already exist.
|
|
201
|
+
* @param {string} pRecordSet - The record set to initialize the settings for
|
|
202
|
+
* @param {string} pViewContext - The current view context
|
|
203
|
+
* @param {object} [pAdditionalSettings] - Additional settings to initialize with (pass through for future use)
|
|
204
|
+
* @return {string} - The filter experience settings object stringifyed (as if it was just read from storage).
|
|
69
205
|
*/
|
|
70
|
-
|
|
206
|
+
initializeFilterExperienceSettings(pRecordSet, pViewContext, pAdditionalSettings)
|
|
71
207
|
{
|
|
72
|
-
|
|
208
|
+
for (const recordSet in this.storageProvider)
|
|
209
|
+
{
|
|
210
|
+
if (recordSet.startsWith(`Filter_Meta_${pRecordSet}_${pViewContext}_` ) && recordSet.endsWith(`_SETTINGS`))
|
|
211
|
+
{
|
|
212
|
+
return this.storageProvider.getItem(recordSet);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const defaultSettings = {
|
|
216
|
+
ExcludedFromSelection: true, // this one is excluded from the selection list (it's just settings, not a real filter experience)
|
|
217
|
+
RememberLastUsedFilterExperience: false,
|
|
218
|
+
LastUsedFilterExperienceHash: null,
|
|
219
|
+
LastUsedFilterExperienceURLParam: null,
|
|
220
|
+
DefaultFilterExperienceHash: null,
|
|
221
|
+
DefaultFilterExperienceURLParam: null,
|
|
222
|
+
FallbackDefaultExperienceURLParam: null, // in case the default filter experience is deleted, what URL param to fall back to (could be a server/customer provided fallback)
|
|
223
|
+
};
|
|
224
|
+
// if additional settings were provided, merge them in
|
|
225
|
+
if (pAdditionalSettings && typeof(pAdditionalSettings) === 'object')
|
|
226
|
+
{
|
|
227
|
+
Object.assign(defaultSettings, pAdditionalSettings);
|
|
228
|
+
// ex: set 'FallbackDefaultExperienceURLParam' here for future use
|
|
229
|
+
}
|
|
230
|
+
// save the default settings to storage
|
|
231
|
+
this.storageProvider.setItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`, JSON.stringify(defaultSettings));
|
|
232
|
+
return JSON.stringify(defaultSettings);
|
|
73
233
|
}
|
|
74
234
|
|
|
75
235
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* @param {string}
|
|
79
|
-
* @param {
|
|
80
|
-
*
|
|
81
|
-
* @return {boolean}
|
|
236
|
+
* Set options like Last Used / Default hashes, which are stored in the settings object for a given record set and view context.
|
|
237
|
+
* @param {string} pRecordSet - The record set to get the setting for
|
|
238
|
+
* @param {string} pViewContext - The current view context
|
|
239
|
+
* @param {object} pSettings - The settings to update
|
|
240
|
+
* @return {object} - The filter experience settings object
|
|
82
241
|
*/
|
|
83
|
-
|
|
242
|
+
updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, pSettings)
|
|
84
243
|
{
|
|
85
|
-
|
|
86
|
-
|
|
244
|
+
let tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
245
|
+
let tmpSettings = tmpSavedSettings ? JSON.parse(tmpSavedSettings) : {};
|
|
246
|
+
// if we've never saved settings before, initialize them first
|
|
247
|
+
if (!tmpSettings)
|
|
87
248
|
{
|
|
88
|
-
|
|
249
|
+
tmpSavedSettings = this.initializeFilterExperienceSettings(pRecordSet, pViewContext);
|
|
250
|
+
tmpSettings = tmpSavedSettings ? JSON.parse(tmpSavedSettings) : {};
|
|
89
251
|
}
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
252
|
+
// always update the last modified date, recordSet, and viewContext for tracking
|
|
253
|
+
pSettings.RecordSet = pRecordSet ? pRecordSet : tmpSettings.RecordSet;
|
|
254
|
+
pSettings.ViewContext = pViewContext ? pViewContext : tmpSettings.ViewContext;
|
|
255
|
+
pSettings.LastModifiedDate = new Date().toISOString();
|
|
256
|
+
// merge in the new settings
|
|
257
|
+
tmpSettings = Object.assign({}, tmpSettings, pSettings);
|
|
258
|
+
this.storageProvider.setItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`, JSON.stringify(tmpSettings));
|
|
259
|
+
return tmpSettings;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get a single filter experience by its hash for a given record set and view context.
|
|
264
|
+
* @param {string} pRecordSet - The record set to get the filter experience for
|
|
265
|
+
* @param {string} pViewContext - The current view context
|
|
266
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to get
|
|
267
|
+
* @return {object} - The filter experience object
|
|
268
|
+
*/
|
|
269
|
+
getFilterExperienceByHash(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
270
|
+
{
|
|
271
|
+
if (!pRecordSet || !pViewContext)
|
|
272
|
+
{
|
|
273
|
+
console.error('No record set or view context provided to get filter experience.');
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
if (!pFilterExperienceHash || pFilterExperienceHash.length === 0)
|
|
277
|
+
{
|
|
278
|
+
console.warn('No filter experience hash provided to get filter experience.');
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
const tmpKey = this.getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
282
|
+
const tmpFilterExperienceJSON = this.storageProvider.getItem(tmpKey);
|
|
283
|
+
let tmpFilterExperience = tmpFilterExperienceJSON ? JSON.parse(tmpFilterExperienceJSON) : null;
|
|
284
|
+
return tmpFilterExperience;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* List all available filter experiences (from the Filter Meta data) for a given record set and return them as an array of filter meta objects.
|
|
289
|
+
* @param {string} pRecordSet - the record set to list the filter experiences for
|
|
290
|
+
* @param {string} pViewContext - the current view context
|
|
291
|
+
* @return {Array<object>} - An array of filter meta objects for the given record set.
|
|
292
|
+
*/
|
|
293
|
+
getAllFiltersExperiencesForRecordSet(pRecordSet, pViewContext)
|
|
294
|
+
{
|
|
295
|
+
let tmpFilterExperiences = [];
|
|
296
|
+
for (const recordSet in this.storageProvider)
|
|
297
|
+
{
|
|
298
|
+
if (recordSet.startsWith(`Filter_Meta_${pRecordSet}_${pViewContext}_`))
|
|
299
|
+
{
|
|
300
|
+
const tmpFilterMetaJSON = this.storageProvider.getItem(recordSet);
|
|
301
|
+
if (tmpFilterMetaJSON)
|
|
302
|
+
{
|
|
303
|
+
const tmpFilterMeta = JSON.parse(tmpFilterMetaJSON);
|
|
304
|
+
tmpFilterExperiences.push(tmpFilterMeta);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return tmpFilterExperiences;
|
|
97
309
|
}
|
|
98
310
|
|
|
99
311
|
/**
|
|
100
312
|
* Resolve a key in the LocalStorage keyspace for a filter experience for a given record set.
|
|
101
|
-
*
|
|
102
313
|
* @param {string} pRecordSet - The record set to resolve a key for
|
|
314
|
+
* @param {string} pViewContext - The current view context
|
|
103
315
|
* @param {string} pFilterExperienceHash - The scope to resolve a key for
|
|
104
316
|
*
|
|
105
317
|
* @return {string} A string that points to the record.
|
|
106
318
|
*/
|
|
107
|
-
getFilterStorageKey(pRecordSet, pFilterExperienceHash)
|
|
319
|
+
getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
108
320
|
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
321
|
+
let tmpFilterExperienceHash = (typeof(pFilterExperienceHash) === 'string') ? pFilterExperienceHash : null;
|
|
322
|
+
if (!tmpFilterExperienceHash || tmpFilterExperienceHash.length === 0)
|
|
323
|
+
{
|
|
324
|
+
console.error('No filter experience hash provided to resolve storage key.');
|
|
325
|
+
return '';
|
|
326
|
+
}
|
|
327
|
+
return `Filter_Meta_${pRecordSet}_${pViewContext}_${tmpFilterExperienceHash}`;
|
|
113
328
|
}
|
|
114
329
|
|
|
115
330
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* @param {string}
|
|
119
|
-
* @param {
|
|
331
|
+
* Check if a filter experience exists for a given record set and filter experience hash.
|
|
332
|
+
* @param {string} pRecordSet - The record set to check.
|
|
333
|
+
* @param {string} pViewContext - The current view context
|
|
334
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to check.
|
|
335
|
+
* @return {boolean} - True if the filter experience exists, false otherwise.
|
|
120
336
|
*/
|
|
121
|
-
|
|
337
|
+
checkIfFilterExperienceExists(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
122
338
|
{
|
|
123
|
-
const
|
|
339
|
+
const tmpKey = this.getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
340
|
+
const tmpFilterMetaJSON = this.storageProvider.getItem(tmpKey);
|
|
341
|
+
return (tmpFilterMetaJSON !== null);
|
|
342
|
+
}
|
|
124
343
|
|
|
125
|
-
|
|
126
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Save the application metadata (list of Filters, last loaded FilterExperienceHash, etc.)
|
|
346
|
+
* @param {string} pRecordSet - The record set to save the filter for;
|
|
347
|
+
* @param {string} pViewContext - The current view context
|
|
348
|
+
* @param {string} pFilterExperienceHash - The name of the filter to load
|
|
349
|
+
* @param {boolean} pSkipSaveAsLastUsed - Whether to skip saving this as the last used filter experience - useful when loading last used filter itself
|
|
350
|
+
* @return {boolean} - Returns true when the filter experience has been loaded.
|
|
351
|
+
*/
|
|
352
|
+
loadFilterMeta(pRecordSet, pViewContext, pFilterExperienceHash, pSkipSaveAsLastUsed)
|
|
353
|
+
{
|
|
354
|
+
// We get this every time in case the user has multiple tabs open
|
|
355
|
+
const tmpKey = this.getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
356
|
+
const tmpFilterExperienceJSON = this.storageProvider.getItem(tmpKey);
|
|
357
|
+
let tmpFilterExperience = tmpFilterExperienceJSON ? JSON.parse(tmpFilterExperienceJSON) : null;
|
|
358
|
+
if (!tmpFilterExperience)
|
|
359
|
+
{
|
|
360
|
+
// check if this is the "last used" filter experience, since that one is special and we can have the URL param stored separately for unsaved searches
|
|
361
|
+
const tmpLastUsedAndUnsavedExperience = this.isLastUsedFilterExperienceHash(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
362
|
+
if (tmpLastUsedAndUnsavedExperience)
|
|
363
|
+
{
|
|
364
|
+
const tmpLastUsedFilterExperience = this.getLastUsedFilterExperience(pRecordSet, pViewContext);
|
|
365
|
+
this.setCurrentFilterName(tmpLastUsedFilterExperience, pRecordSet, pViewContext, 'My Last Used Filter Experience');
|
|
366
|
+
this.navigateToFilterExperienceRoute(tmpLastUsedFilterExperience, pRecordSet, pViewContext);
|
|
367
|
+
// clear the unapplied changes flag since we just loaded a filter experience
|
|
368
|
+
this.filterExperienceModifiedFromURLHash = false;
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
127
371
|
|
|
128
|
-
|
|
372
|
+
this.pict.log.warn(`No filter experience available to remove for record set: ${pRecordSet} with filter experience hash: ${pFilterExperienceHash}`);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
// update the current filter name in the UI
|
|
376
|
+
this.setCurrentFilterName(tmpFilterExperience, pRecordSet, pViewContext);
|
|
377
|
+
// re-render views if needed
|
|
378
|
+
this.navigateToFilterExperienceRoute(tmpFilterExperience, pRecordSet, pViewContext);
|
|
379
|
+
// update the last used filter experience
|
|
380
|
+
if (!pSkipSaveAsLastUsed)
|
|
129
381
|
{
|
|
130
|
-
this.
|
|
382
|
+
this.setLastUsedFilterExperience(tmpFilterExperience, pRecordSet, pViewContext);
|
|
131
383
|
}
|
|
132
|
-
|
|
384
|
+
// clear the unapplied changes flag since we just loaded a filter experience
|
|
385
|
+
this.filterExperienceModifiedFromURLHash = false;
|
|
386
|
+
|
|
133
387
|
return true;
|
|
134
388
|
}
|
|
135
389
|
|
|
136
390
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
* @param {string}
|
|
140
|
-
* @param {
|
|
141
|
-
*
|
|
142
|
-
* @return {Array<object>} The list of available Filters.
|
|
391
|
+
* Remove a filter meta from storage for a given record set and filter experience hash.
|
|
392
|
+
* @param {string} pRecordSet - The record set to remove the filter for
|
|
393
|
+
* @param {string} pViewContext - The current view context
|
|
394
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to remove
|
|
395
|
+
* @return {boolean} - Returns true when the filter meta has been removed.
|
|
143
396
|
*/
|
|
144
|
-
|
|
397
|
+
removeFilterMeta(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
145
398
|
{
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
399
|
+
// TODO: add confirmation dialog in the UI before removing?
|
|
400
|
+
const tmpKey = this.getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
401
|
+
const tmpFilterExperienceJSON = this.storageProvider.getItem(tmpKey);
|
|
402
|
+
let tmpFilterExperience = tmpFilterExperienceJSON ? JSON.parse(tmpFilterExperienceJSON) : null;
|
|
403
|
+
if (!tmpFilterExperience)
|
|
149
404
|
{
|
|
150
|
-
|
|
405
|
+
this.pict.log.warn(`No filter experience available to remove for record set: ${pRecordSet} with filter experience hash: ${pFilterExperienceHash}`);
|
|
406
|
+
return false;
|
|
151
407
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let filtersList = tmpFilterMeta.FilterList;
|
|
155
|
-
this.filtersMap[pRecordSet] = filtersList;
|
|
156
|
-
this.lastFilterExperienceHashMap[pRecordSet] = tmpFilterMeta.LastFilterExperienceHash;
|
|
157
|
-
|
|
158
|
-
if (!Array.isArray(filtersList))
|
|
408
|
+
// check if the filter being removed is set as last used or default; if so, clear those settings too
|
|
409
|
+
if (this.isLastUsedFilterExperienceHash(pRecordSet, pViewContext, pFilterExperienceHash))
|
|
159
410
|
{
|
|
160
|
-
this.
|
|
161
|
-
|
|
162
|
-
this.saveFilterMeta(pRecordSet)
|
|
411
|
+
this.pict.log.info(`The filter experience being removed is set as the last used filter experience. Clearing last used filter experience settings.`);
|
|
412
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { LastUsedFilterExperienceHash: null, LastUsedFilterExperienceURLParam: null });
|
|
163
413
|
}
|
|
164
|
-
|
|
165
|
-
if (pRender && this.pict.views.FilterPersistenceView)
|
|
414
|
+
if (this.isDefaultFilterExperience(pRecordSet, pViewContext, pFilterExperienceHash))
|
|
166
415
|
{
|
|
167
|
-
this.pict.
|
|
416
|
+
this.pict.log.info(`The filter experience being removed is set as the default filter experience. Clearing default filter experience settings.`);
|
|
417
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { DefaultFilterExperienceHash: null, DefaultFilterExperienceURLParam: null });
|
|
168
418
|
}
|
|
419
|
+
if (this.isCurrentFilterExperience(pRecordSet, pViewContext, pFilterExperienceHash))
|
|
420
|
+
{
|
|
421
|
+
this.pict.log.info(`The filter experience being removed is the current active filter. Navigating to base record set URL.`);
|
|
422
|
+
this.pict.views['PRSP-Filters'].handleReset(null, pRecordSet, pViewContext);
|
|
423
|
+
}
|
|
424
|
+
// remove the filter meta from localStorage
|
|
425
|
+
this.storageProvider.removeItem(tmpKey);
|
|
426
|
+
// NOTE: I think we want to keep the last used filter experience even if the user deletes it from the list? (so they can undo)
|
|
169
427
|
|
|
170
|
-
return
|
|
428
|
+
return true;
|
|
171
429
|
}
|
|
172
430
|
|
|
173
431
|
/**
|
|
174
|
-
*
|
|
175
|
-
* @param {string}
|
|
176
|
-
* @param {
|
|
177
|
-
*
|
|
178
|
-
* @return {boolean} True if the filter experience hash was added, false if it already exists.
|
|
432
|
+
* Save the application metadata (list of Filters, last loaded FilterExperienceHash, etc.)
|
|
433
|
+
* @param {string} pRecordSet - The record set to save the filter for; TODO: should this have a default?
|
|
434
|
+
* @param {string} pViewContext - The current view context
|
|
435
|
+
* @return {boolean} - Returns true when the settings have been saved.
|
|
179
436
|
*/
|
|
180
|
-
|
|
437
|
+
saveFilterMeta(pRecordSet, pViewContext)
|
|
181
438
|
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const tmpFilterList = this.filtersMap[pRecordSet] || [];
|
|
187
|
-
|
|
188
|
-
let tmpFilterFilterExperienceHashIndex = tmpFilterList.indexOf(pFilterExperienceHash);
|
|
439
|
+
const activeFilterExperienceClauses = this.pict.Bundle._ActiveFilterState[pRecordSet]?.FilterClauses || [];
|
|
440
|
+
const filterDisplayName = this.getCurrentFilterName({ FilterClauses: activeFilterExperienceClauses }, pRecordSet, pViewContext);
|
|
441
|
+
const tmpFilterExperienceHash = filterDisplayName.replace(/[^a-zA-Z0-9_-]/g, '');
|
|
189
442
|
|
|
190
|
-
if (
|
|
443
|
+
if (this.checkIfFilterExperienceExists(pRecordSet, pViewContext, tmpFilterExperienceHash))
|
|
191
444
|
{
|
|
192
|
-
|
|
445
|
+
this.pict.log.info(`Filter experience with hash 'Filter_Meta_${pRecordSet}_${pViewContext}_${tmpFilterExperienceHash}' already exists for record set ${pRecordSet}. Overwriting.`);
|
|
446
|
+
// TODO: add a confirmation dialog in the UI and compare before overwriting?
|
|
193
447
|
}
|
|
194
|
-
const filtersList = this.filtersMap[pRecordSet] || [];
|
|
195
|
-
filtersList.push(pFilterExperienceHash);
|
|
196
|
-
this.filtersMap[pRecordSet] = filtersList;
|
|
197
|
-
|
|
198
|
-
this.saveFilterMeta(pRecordSet);
|
|
199
448
|
|
|
200
|
-
|
|
201
|
-
{
|
|
202
|
-
|
|
449
|
+
// TODO: BUG: Gotta have a more complex merge happen here for multiple tabs
|
|
450
|
+
const newFilterExperience = {
|
|
451
|
+
RecordSet: pRecordSet,
|
|
452
|
+
ViewContext: pViewContext,
|
|
453
|
+
FilterClauses: activeFilterExperienceClauses,
|
|
454
|
+
FilterDisplayName: filterDisplayName,
|
|
455
|
+
FilterExperienceHash: tmpFilterExperienceHash,
|
|
456
|
+
FilterExperienceEncodedURLParam: window.location.hash.split('/FilterExperience/')?.[1] || '',
|
|
457
|
+
LastModifiedDate: new Date().toISOString(),
|
|
203
458
|
}
|
|
459
|
+
// Save the specific filter metadata to localStorage
|
|
460
|
+
this.storageProvider.setItem(`Filter_Meta_${pRecordSet}_${pViewContext}_${tmpFilterExperienceHash}`, JSON.stringify(newFilterExperience));
|
|
461
|
+
// Also set the last used filter experience (this one is reserved and continually updated)
|
|
462
|
+
this.setLastUsedFilterExperience(newFilterExperience, pRecordSet, pViewContext);
|
|
463
|
+
// they should never get here if they have unsaved changes and navigate away since we check for that in the router, but just in case, we can clear the flag that tracks whether there are unapplied changes since we just saved
|
|
464
|
+
this.filterExperienceModifiedFromURLHash = false;
|
|
204
465
|
|
|
205
466
|
return true;
|
|
206
467
|
}
|
|
207
468
|
|
|
469
|
+
/** ===== LAST USED Filter Experience ============= */
|
|
470
|
+
|
|
208
471
|
/**
|
|
209
|
-
*
|
|
210
|
-
* @param {
|
|
211
|
-
* @param {
|
|
472
|
+
* Save the application metadata as the last used filter experience (continually updated).
|
|
473
|
+
* @param {object} pFilterExperience - The new filter experience object to save as last used
|
|
474
|
+
* @param {string} pRecordSet - The record set to save the filter for;
|
|
475
|
+
* @param {string} pViewContext - The current view context
|
|
476
|
+
* @return {boolean} - Returns true when the filter experience has been saved.
|
|
212
477
|
*/
|
|
213
|
-
|
|
478
|
+
setLastUsedFilterExperience(pFilterExperience, pRecordSet, pViewContext)
|
|
214
479
|
{
|
|
215
|
-
|
|
480
|
+
const activeFilterExperienceClauses = this.pict.Bundle._ActiveFilterState[pRecordSet]?.FilterClauses || [];
|
|
481
|
+
const filterDisplayName = this.getCurrentFilterName({ FilterClauses: activeFilterExperienceClauses }, pRecordSet, pViewContext);
|
|
482
|
+
const tmpFilterExperienceHash = filterDisplayName.replace(/[^a-zA-Z0-9_-]/g, '');
|
|
483
|
+
|
|
484
|
+
// NOTE: We probably don't want to save EVERY. SINGLE. SEARCH. so if no filter experience is provided (new unsaved search), we can just redirect to the url param rather than create a new saved filter experience
|
|
485
|
+
const filterMetaSettings = {
|
|
486
|
+
LastUsedFilterExperienceHash: pFilterExperience?.FilterExperienceHash || tmpFilterExperienceHash,
|
|
487
|
+
LastUsedFilterExperienceURLParam: pFilterExperience?.FilterExperienceEncodedURLParam || window.location.hash.split('/FilterExperience/')?.[1] || '',
|
|
488
|
+
}
|
|
489
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, filterMetaSettings);
|
|
216
490
|
|
|
217
|
-
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
218
493
|
|
|
219
|
-
|
|
494
|
+
/**
|
|
495
|
+
* Remove the last used filter experience for a given record set and view context. (used on "Clear" action to get back to empty filter state)
|
|
496
|
+
* @param {string} pRecordSet - The record set to remove the last used filter experience for
|
|
497
|
+
* @param {string} pViewContext - The current view context
|
|
498
|
+
* @return {boolean} - Returns true when the last used filter experience has been removed.
|
|
499
|
+
*/
|
|
500
|
+
removeLastUsedFilterExperience(pRecordSet, pViewContext)
|
|
501
|
+
{
|
|
502
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { LastUsedFilterExperienceHash: null, LastUsedFilterExperienceURLParam: null });
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
220
505
|
|
|
221
|
-
|
|
506
|
+
/**
|
|
507
|
+
* Get the last used filter experience for a given record set and view context.
|
|
508
|
+
* @param {string} pRecordSet - The record set to get the last used filter experience for
|
|
509
|
+
* @param {string} pViewContext - The current view context
|
|
510
|
+
* @return {object} - The last used filter experience (takes priority over default if both exist)
|
|
511
|
+
*/
|
|
512
|
+
getLastUsedFilterExperience(pRecordSet, pViewContext)
|
|
513
|
+
{
|
|
514
|
+
const tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
515
|
+
if (!tmpSavedSettings)
|
|
222
516
|
{
|
|
223
|
-
|
|
224
|
-
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
const tmpSettings = JSON.parse(tmpSavedSettings);
|
|
520
|
+
if (!tmpSettings.RememberLastUsedFilterExperience)
|
|
521
|
+
{
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
const lastUsedFilterExperienceHash = tmpSettings.LastUsedFilterExperienceHash;
|
|
525
|
+
const tmpKey = this.getFilterStorageKey(pRecordSet, pViewContext, lastUsedFilterExperienceHash);
|
|
526
|
+
const tmpFilterExperienceJSON = this.storageProvider.getItem(tmpKey);
|
|
527
|
+
let tmpFilterExperience = tmpFilterExperienceJSON ? JSON.parse(tmpFilterExperienceJSON) : null;
|
|
528
|
+
return tmpFilterExperience;
|
|
529
|
+
}
|
|
225
530
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
531
|
+
/**
|
|
532
|
+
* Check if the given filter experience is the last used filter experience for the given record set and view context.
|
|
533
|
+
* @param {string} pRecordSet - The record set to check
|
|
534
|
+
* @param {string} pViewContext - The current view context
|
|
535
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to check
|
|
536
|
+
* @return {boolean} - True if the given filter experience is the last used filter experience, false otherwise
|
|
537
|
+
*/
|
|
538
|
+
isLastUsedFilterExperienceHash(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
539
|
+
{
|
|
540
|
+
const tmpLastUsedFilter = this.getLastUsedFilterExperience(pRecordSet, pViewContext);
|
|
541
|
+
if (!tmpLastUsedFilter)
|
|
542
|
+
{
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
return (tmpLastUsedFilter.FilterExperienceHash === pFilterExperienceHash);
|
|
546
|
+
}
|
|
233
547
|
|
|
234
|
-
|
|
548
|
+
/**
|
|
549
|
+
* Set whether to remember the last used filter experience across sessions.
|
|
550
|
+
* @param {string} pRecordSet - The record set to set the setting for
|
|
551
|
+
* @param {string} pViewContext - The current view context
|
|
552
|
+
* @param {boolean} pRemember - Whether to remember the last used filter experience
|
|
553
|
+
*/
|
|
554
|
+
setRememberLastUsedFilterExperience(pRecordSet, pViewContext, pRemember)
|
|
555
|
+
{
|
|
556
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { RememberLastUsedFilterExperience: pRemember });
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
235
559
|
|
|
236
|
-
|
|
560
|
+
/**
|
|
561
|
+
* Get whether to remember the last used filter experience across sessions.
|
|
562
|
+
* @param {string} pRecordSet - The record set to get the setting for
|
|
563
|
+
* @param {string} pViewContext - The current view context
|
|
564
|
+
* @return {boolean} - Whether to remember the last used filter experience
|
|
565
|
+
*/
|
|
566
|
+
getRememberLastUsedFilterExperience(pRecordSet, pViewContext)
|
|
567
|
+
{
|
|
568
|
+
const tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
569
|
+
if (!tmpSavedSettings)
|
|
570
|
+
{
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
const tmpSettings = JSON.parse(tmpSavedSettings);
|
|
574
|
+
return tmpSettings.RememberLastUsedFilterExperience;
|
|
575
|
+
}
|
|
237
576
|
|
|
238
|
-
|
|
239
|
-
{
|
|
240
|
-
this.pict.views.FilterPersistenceView.render()
|
|
241
|
-
}
|
|
577
|
+
/** ===== CURRENT Filter Experience ============= */
|
|
242
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Check if the given filter experience hash is the current active filter for the given record set.
|
|
581
|
+
* @param {string} pRecordSet - The record set to check.
|
|
582
|
+
* @param {string} pViewContext - The current view context.
|
|
583
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to check.
|
|
584
|
+
* @return {boolean} - True if the given filter experience hash is the current active filter, false otherwise.
|
|
585
|
+
*/
|
|
586
|
+
isCurrentFilterExperience(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
587
|
+
{
|
|
588
|
+
// NOTE: Could be an confusing issue if we have the same URL param with different display names
|
|
589
|
+
const tmpExperienceURLParam = window.location.hash.split('/FilterExperience/')?.[1] || '';
|
|
590
|
+
// look in the map for the filter experience with the given hash
|
|
591
|
+
const filterExperiences = this.getAllFiltersExperiencesForRecordSet(pRecordSet, pViewContext) || [];
|
|
592
|
+
const matchingExperience = filterExperiences.find((pExperience) => pExperience.FilterExperienceHash === pFilterExperienceHash);
|
|
593
|
+
if (matchingExperience && (matchingExperience.FilterExperienceEncodedURLParam === tmpExperienceURLParam))
|
|
594
|
+
{
|
|
243
595
|
return true;
|
|
244
596
|
}
|
|
245
|
-
|
|
246
597
|
return false;
|
|
247
598
|
}
|
|
248
|
-
|
|
599
|
+
|
|
249
600
|
/**
|
|
250
|
-
*
|
|
251
|
-
* @param {
|
|
601
|
+
* Get the current filter name from the UI input (or generate a default one)
|
|
602
|
+
* @param {object} pFilterExperience - The filter experience to get the current filter name for
|
|
603
|
+
* @param {string} pRecordSet - The record set to get the filter name for
|
|
604
|
+
* @param {string} pViewContext - The current view context
|
|
605
|
+
* @return {string} - The current filter name
|
|
252
606
|
*/
|
|
253
|
-
|
|
607
|
+
getCurrentFilterName(pFilterExperience, pRecordSet, pViewContext)
|
|
254
608
|
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (
|
|
609
|
+
/* @type {HTMLInputElement} */
|
|
610
|
+
const tmpValue = this.pict.ContentAssignment.readContent('#FilterPersistenceView-CurrentFilterNameInput');
|
|
611
|
+
if (tmpValue && tmpValue.trim().length > 0)
|
|
258
612
|
{
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
613
|
+
return tmpValue.trim();
|
|
614
|
+
}
|
|
615
|
+
return this.generateContextualDefaultFilterName(pFilterExperience, pRecordSet, pViewContext);
|
|
616
|
+
}
|
|
262
617
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
618
|
+
/**
|
|
619
|
+
* Set the current filter name in the UI input
|
|
620
|
+
* @param {object} [pFilterExperience] - The filter experience to set the current filter name for
|
|
621
|
+
* @param {string} [pRecordSet] - The record set to set the filter name for
|
|
622
|
+
* @param {string} [pViewContext] - The current view context
|
|
623
|
+
* @param {string} [pNewName] - The new name to set
|
|
624
|
+
* @return {boolean} - Returns true when the name has been set
|
|
625
|
+
*/
|
|
626
|
+
setCurrentFilterName(pFilterExperience, pRecordSet, pViewContext, pNewName)
|
|
627
|
+
{
|
|
628
|
+
const tmpDisplayName = pNewName || this.generateContextualDefaultFilterName(pFilterExperience, pRecordSet, pViewContext);
|
|
629
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-CurrentFilterNameInput', tmpDisplayName);
|
|
630
|
+
return true;
|
|
631
|
+
}
|
|
267
632
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
633
|
+
/** ===== DEFAULT Filter Experience ============= */
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Set the default filter experience to load on application load for a given record set and filter experience hash.
|
|
637
|
+
* @param {string} pRecordSet - The record set to set the default filter experience for
|
|
638
|
+
* @param {string} pViewContext - The current view context
|
|
639
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to set as default on load
|
|
640
|
+
* @param {boolean} pSetAsDefault - Whether to set as default or not
|
|
641
|
+
* @return {boolean} - Returns true when the default filter experience has been set
|
|
642
|
+
*/
|
|
643
|
+
setDefaultFilterExperience(pRecordSet, pViewContext, pFilterExperienceHash, pSetAsDefault)
|
|
644
|
+
{
|
|
645
|
+
const tmpStorageKey = this.getFilterStorageKey(pRecordSet, pViewContext, pFilterExperienceHash);
|
|
646
|
+
const tmpFilterExperienceJSON = this.storageProvider.getItem(tmpStorageKey);
|
|
647
|
+
let tmpFilterExperience = tmpFilterExperienceJSON ? JSON.parse(tmpFilterExperienceJSON) : null;
|
|
648
|
+
if (!tmpFilterExperience)
|
|
649
|
+
{
|
|
650
|
+
this.pict.log.warn(`No filter experience available to set as default for record set: ${pRecordSet} with filter experience hash: ${pFilterExperienceHash}`);
|
|
651
|
+
return false;
|
|
274
652
|
}
|
|
275
|
-
|
|
653
|
+
// if already default, do nothing
|
|
654
|
+
if (pSetAsDefault && this.isDefaultFilterExperience(pRecordSet, pViewContext, tmpFilterExperience.FilterExperienceHash))
|
|
276
655
|
{
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
{
|
|
280
|
-
this.log.warn(`Filter ${tmpFilterExperienceHash} already exists but it was explicitly requested by the user. Loading insted.`);
|
|
281
|
-
return this.loadFilter(pRecordSet, tmpFilterExperienceHash);
|
|
282
|
-
}
|
|
656
|
+
this.pict.log.info(`Filter experience 'Filter_Meta_${pRecordSet}_${pViewContext}_${pFilterExperienceHash}' is already set as default on load. No action taken.`);
|
|
657
|
+
return true;
|
|
283
658
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (!tmpFilterExperienceHash)
|
|
659
|
+
// if unsetting default, but not currently default, do nothing
|
|
660
|
+
if (!pSetAsDefault && !this.isDefaultFilterExperience(pRecordSet, pViewContext, tmpFilterExperience.FilterExperienceHash))
|
|
287
661
|
{
|
|
288
|
-
this.log.
|
|
289
|
-
|
|
662
|
+
this.pict.log.info(`Filter experience 'Filter_Meta_${pRecordSet}_${pViewContext}_${pFilterExperienceHash}' is not currently set as default on load. No action taken.`);
|
|
663
|
+
return true;
|
|
290
664
|
}
|
|
665
|
+
// update the settings
|
|
666
|
+
// NOTE: We may probably want an customer-based fallback is there user default settings are cleared. For now, we will just clear it until we know that pattern.
|
|
667
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { DefaultFilterExperienceHash: pSetAsDefault ? pFilterExperienceHash : null });
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
291
670
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
671
|
+
/**
|
|
672
|
+
* Remove the default filter experience for a given record set and view context. (used on "Clear" action to get back to empty filter state)
|
|
673
|
+
* @param {string} pRecordSet - The record set to remove the default filter experience for
|
|
674
|
+
* @param {string} pViewContext - The current view context
|
|
675
|
+
* @return {boolean} - Returns true when the default filter experience has been removed.
|
|
676
|
+
*/
|
|
677
|
+
removeDefaultFilterExperience(pRecordSet, pViewContext)
|
|
678
|
+
{
|
|
679
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { DefaultFilterExperienceHash: null });
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
301
682
|
|
|
302
|
-
|
|
683
|
+
/**
|
|
684
|
+
* Get the default filter experience to load on application load for a given record set and view context.
|
|
685
|
+
* @param {string} pRecordSet - The record set to get the default filter experience for
|
|
686
|
+
* @param {string} pViewContext - The current view context
|
|
687
|
+
* @return {object} - The default filter experience to load on application load (used if no last used filter experience is found or they clear filters back to default)
|
|
688
|
+
*/
|
|
689
|
+
getDefaultFilterExperience(pRecordSet, pViewContext)
|
|
690
|
+
{
|
|
691
|
+
const tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
692
|
+
if (!tmpSavedSettings)
|
|
693
|
+
{
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
const tmpSettings = JSON.parse(tmpSavedSettings);
|
|
697
|
+
const tmpExpectedHash = tmpSettings.DefaultFilterExperienceHash;
|
|
698
|
+
if (!tmpExpectedHash || tmpExpectedHash.length === 0)
|
|
699
|
+
{
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
// look up the filter experience by hash (it's expected all Default hashes are saved filter experiences)
|
|
703
|
+
return this.getFilterExperienceByHash(pRecordSet, pViewContext, tmpExpectedHash);
|
|
303
704
|
}
|
|
304
705
|
|
|
305
706
|
/**
|
|
306
|
-
*
|
|
707
|
+
* Check if the given filter experience is the default filter experience to load on application load for the given record set and view context.
|
|
708
|
+
* @param {string} pRecordSet - The record set to check
|
|
709
|
+
* @param {string} pViewContext - The current view context
|
|
710
|
+
* @param {string} pFilterExperienceHash - The filter experience hash to check
|
|
711
|
+
* @return {boolean} - True if the given filter experience is the default filter experience on load, false otherwise
|
|
307
712
|
*/
|
|
308
|
-
|
|
713
|
+
isDefaultFilterExperience(pRecordSet, pViewContext, pFilterExperienceHash)
|
|
309
714
|
{
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
715
|
+
const tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
716
|
+
if (!tmpSavedSettings)
|
|
717
|
+
{
|
|
718
|
+
return false;
|
|
719
|
+
}
|
|
720
|
+
const tmpSettings = JSON.parse(tmpSavedSettings);
|
|
721
|
+
return (tmpSettings.DefaultFilterExperienceHash === pFilterExperienceHash);
|
|
314
722
|
}
|
|
315
723
|
|
|
316
724
|
/**
|
|
317
|
-
*
|
|
318
|
-
* @param {string}
|
|
725
|
+
* Get the fallback default filter experience URL param to load on application load for a given record set and view context.
|
|
726
|
+
* @param {string} pRecordSet - The record set to get the fallback default filter experience for
|
|
727
|
+
* @param {string} pViewContext - The current view context
|
|
728
|
+
* @return {string|null} - The fallback default filter experience URL param to load on application load (could be server/customer provided)
|
|
319
729
|
*/
|
|
320
|
-
|
|
730
|
+
getFallbackDefaultFilterExperienceSettings(pRecordSet, pViewContext)
|
|
321
731
|
{
|
|
322
|
-
|
|
323
|
-
if (
|
|
732
|
+
const tmpSavedSettings = this.storageProvider.getItem(`Filter_Meta_${pRecordSet}_${pViewContext}_SETTINGS`);
|
|
733
|
+
if (!tmpSavedSettings)
|
|
324
734
|
{
|
|
325
|
-
|
|
735
|
+
return null;
|
|
326
736
|
}
|
|
327
|
-
|
|
737
|
+
const tmpSettings = JSON.parse(tmpSavedSettings);
|
|
738
|
+
return tmpSettings.FallbackDefaultExperienceURLParam || null;
|
|
328
739
|
}
|
|
329
740
|
|
|
741
|
+
/**
|
|
742
|
+
* Set the fallback default filter experience URL param to load on application load for a given record set and view context. Expected to be used for server/customer provided fallbacks.
|
|
743
|
+
* @param {string} pRecordSet - The record set to set the fallback default filter experience for
|
|
744
|
+
* @param {string} pViewContext - The current view context
|
|
745
|
+
* @param {string} pURLParam - The fallback default filter experience URL param to set
|
|
746
|
+
* @return {boolean} - Returns true when the fallback default filter experience URL param has been set
|
|
747
|
+
*/
|
|
748
|
+
setFallbackDefaultFilterExperienceSettings(pRecordSet, pViewContext, pURLParam)
|
|
749
|
+
{
|
|
750
|
+
this.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, { FallbackDefaultExperienceURLParam: pURLParam });
|
|
751
|
+
return true;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/** ===== SIMPLE KEY-VALUE CACHE ============= */
|
|
755
|
+
|
|
330
756
|
/**
|
|
331
757
|
* @param {string} pKey - The key to get from the cache
|
|
332
|
-
*
|
|
333
758
|
* @return {any} - The value associated with the key, or false if not found
|
|
334
759
|
*/
|
|
335
760
|
getItem(pKey)
|
|
@@ -353,7 +778,6 @@ class FilterDataProvider extends libPictProvider
|
|
|
353
778
|
|
|
354
779
|
/**
|
|
355
780
|
* @param {string} pKey - The key to remove from the cache
|
|
356
|
-
*
|
|
357
781
|
* @return {boolean} - True if the item was removed, false if it was not found
|
|
358
782
|
*/
|
|
359
783
|
removeItem(pKey)
|