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
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _DEFAULT_CONFIGURATION_FilterPersistenceView = (
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: 'FilterPersistenceView',
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: 'FilterPersistenceView-Container',
|
|
8
|
+
DefaultDestinationAddress: '#FilterPersistenceView-Container',
|
|
9
|
+
DefaultTemplateRecordAddress: false,
|
|
10
|
+
|
|
11
|
+
// If this is set to true, when the App initializes this will.
|
|
12
|
+
// While the App initializes, initialize will be called.
|
|
13
|
+
AutoInitialize: false,
|
|
14
|
+
AutoInitializeOrdinal: 0,
|
|
15
|
+
|
|
16
|
+
// If this is set to true, when the App autorenders (on load) this will.
|
|
17
|
+
// After the App initializes, render will be called.
|
|
18
|
+
AutoRender: false,
|
|
19
|
+
AutoRenderOrdinal: 0,
|
|
20
|
+
|
|
21
|
+
AutoSolveWithApp: false,
|
|
22
|
+
AutoSolveOrdinal: 0,
|
|
23
|
+
|
|
24
|
+
CSS: false,
|
|
25
|
+
CSSPriority: 500,
|
|
26
|
+
|
|
27
|
+
Templates:
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
Hash: 'FilterPersistenceView-Container',
|
|
31
|
+
Template: /*html*/`
|
|
32
|
+
<!-- DefaultPackage pict view template: [FilterPersistenceView-Container] -->
|
|
33
|
+
<div id="FilterPersistenceView-Content">
|
|
34
|
+
<!-- Content for Filter Persistence View goes here -->
|
|
35
|
+
<div id="FilterPersistenceView-Header">
|
|
36
|
+
<h3>Filter Experience Settings</h3>
|
|
37
|
+
</div>
|
|
38
|
+
<div id="FilterPersistenceView-Body">
|
|
39
|
+
<div class="FilterPersistenceView-ActiveSettings">
|
|
40
|
+
<label for="CurrentFilterName">Current Filter Experience:</label>
|
|
41
|
+
<span id="FilterPersistenceView-CurrentFilterNameInput-ValidationMessage" style="color: red; font-size: 0.9em; margin-left: 10px;"></span>
|
|
42
|
+
<input type="text" id="FilterPersistenceView-CurrentFilterNameInput" name="CurrentFilterName" value="" onfocus="this.select()" />
|
|
43
|
+
<button type="button" id="FilterPersistenceView-SaveFilterButton" onclick="_Pict.views['FilterPersistenceView'].saveFilterPersistenceSettings(event)">
|
|
44
|
+
<span id="FilterPersistenceView-SaveFilterButtonText">Save</span>
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="FilterPersistenceView-StoredSettings">
|
|
48
|
+
<label for="StoredFilterName">Stored Filter Experiences:</label>
|
|
49
|
+
<select id="FilterPersistenceView-StoredFiltersSelect" onchange="_Pict.views['FilterPersistenceView'].setFilterExperienceToSelection(event)" name="StoredFilterName">
|
|
50
|
+
<!-- Options will be populated dynamically -->
|
|
51
|
+
</select>
|
|
52
|
+
<button type="button" id="FilterPersistenceView-LoadFilterButton" onclick="_Pict.views['FilterPersistenceView'].loadFilterPersistenceSettings(event)">Load</button>
|
|
53
|
+
<button type="button" id="FilterPersistenceView-SetAsDefaultButton" onclick="_Pict.views['FilterPersistenceView'].toggleFilterExperienceAsTheDefault(event, true)">Set As Default</button>
|
|
54
|
+
<button type="button" id="FilterPersistenceView-RemoveAsDefaultButton" onclick="_Pict.views['FilterPersistenceView'].toggleFilterExperienceAsTheDefault(event, false)">Remove As Default</button>
|
|
55
|
+
<button type="button" id="FilterPersistenceView-DeleteFilterButton" onclick="_Pict.views['FilterPersistenceView'].deleteFilterPersistenceSettings(event)">Delete</button>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="FilterPersistenceView-OptionalSettings">
|
|
58
|
+
<label for="OptionalSettings">Optional Settings:</label>
|
|
59
|
+
<label for="OptionalSettings-RememberLastUsed">
|
|
60
|
+
<input type="checkbox" id="OptionalSettings-RememberLastUsed" name="RememberLastUsed" onchange="_Pict.views['FilterPersistenceView'].toggleRememberLastUsedFilterExperience(event)" />
|
|
61
|
+
Remember my last search filter experience
|
|
62
|
+
</label>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div id="FilterPersistenceView-Footer">
|
|
66
|
+
<button type="button" id="FilterPersistenceView-CloseManageFiltersButton" onclick="_Pict.views['FilterPersistenceView'].closeFilterPersistenceUI()">Close</button>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<!-- DefaultPackage end view template: [FilterPersistenceView-Container] -->
|
|
70
|
+
`
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
Renderables:
|
|
75
|
+
[
|
|
76
|
+
{
|
|
77
|
+
RenderableHash: 'FilterPersistenceView-Renderable',
|
|
78
|
+
TemplateHash: 'FilterPersistenceView-Container',
|
|
79
|
+
DestinationAddress: '#FilterPersistenceView-Container',
|
|
80
|
+
RenderMethod: 'replace'
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
],
|
|
84
|
+
|
|
85
|
+
Manifests: {}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
class viewFilterPersistenceView extends libPictView
|
|
89
|
+
{
|
|
90
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
91
|
+
{
|
|
92
|
+
let tmpOptions = Object.assign({}, _DEFAULT_CONFIGURATION_FilterPersistenceView, pOptions);
|
|
93
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
94
|
+
|
|
95
|
+
this.currentRecordSet = null;
|
|
96
|
+
this.currentViewContext = null;
|
|
97
|
+
this.filterExperienceSelection = null;
|
|
98
|
+
this.filterExperienceInitialized = false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Initializes the filter persistence view UI for a given record set and view context. This will render the UI and populate it with the relevant filter experiences for the given context.
|
|
104
|
+
* @param {string} pRecordSet - The identifier of the record set.
|
|
105
|
+
* @param {string} pViewContext - The context of the view.
|
|
106
|
+
* @param {function} pCallback - A callback function to be executed after initializing the UI.
|
|
107
|
+
* @returns {boolean} - Returns true when the UI has been initialized.
|
|
108
|
+
*/
|
|
109
|
+
initializeFilterPersistenceViewUI(pRecordSet, pViewContext, pCallback)
|
|
110
|
+
{
|
|
111
|
+
if (!pRecordSet || !pViewContext)
|
|
112
|
+
{
|
|
113
|
+
this.pict.log.error('RecordSet and ViewContext are required to open the Filter Persistence UI.');
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!this.filterExperienceInitialized)
|
|
118
|
+
{
|
|
119
|
+
this.pict.providers.FilterDataProvider.initializeFilterExperienceSettings(pRecordSet, pViewContext);
|
|
120
|
+
this.filterExperienceInitialized = true;
|
|
121
|
+
}
|
|
122
|
+
this.currentRecordSet = pRecordSet;
|
|
123
|
+
this.currentViewContext = pViewContext;
|
|
124
|
+
// Implement the logic for toggling filter persistence UI here
|
|
125
|
+
this.render('FilterPersistenceView-Renderable', undefined, { RecordSet: pRecordSet, ViewContext: pViewContext });
|
|
126
|
+
|
|
127
|
+
// set checkbox for "Remember Last Used Filter Experience" based on provider setting
|
|
128
|
+
const checkboxElement = document.getElementById('OptionalSettings-RememberLastUsed');
|
|
129
|
+
if (checkboxElement)
|
|
130
|
+
{
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
checkboxElement.checked = this.pict.providers.FilterDataProvider.getRememberLastUsedFilterExperience(this.currentRecordSet, this.currentViewContext);
|
|
133
|
+
}
|
|
134
|
+
// build the select options for available filter experiences
|
|
135
|
+
this.buildSelectOptionsForAvailableFilterExperiences();
|
|
136
|
+
this.handleModifiedFiltersState();
|
|
137
|
+
|
|
138
|
+
// if a callback function was provided, execute it after the UI has been generated
|
|
139
|
+
if (pCallback && typeof pCallback === 'function')
|
|
140
|
+
{
|
|
141
|
+
pCallback();
|
|
142
|
+
};
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Updates the current filter experience name in the input field based on the current filter experience applied for the given record set and view context. This is used to ensure that if the filter experience was modified outside of the UI (ex: through the URL hash), we can reflect that in the input field and also handle the button states accordingly to prevent unintended consequences of saving in an invalid state.
|
|
148
|
+
* @param {string} pRecordSet - The identifier of the record set.
|
|
149
|
+
* @param {string} pViewContext - The context of the view.
|
|
150
|
+
* @param {boolean} pIgnoreCurrentExperienceURLParam - Whether to ignore the current experience when updating the input field, use this when in a modified state and the url is now outdated, to generate a new name.
|
|
151
|
+
*/
|
|
152
|
+
updateDisplayNameInputWithCurrentFilterExperience(pRecordSet, pViewContext, pIgnoreCurrentExperienceURLParam = false)
|
|
153
|
+
{
|
|
154
|
+
const tmpFilterExperienceList = this.pict.providers.FilterDataProvider.getAllFiltersExperiencesForRecordSet(pRecordSet, pViewContext);
|
|
155
|
+
// get the current filter experience hash from the URL
|
|
156
|
+
const tmpExperienceURLParam = this.pict.providers.PictRouter?.router?.current?.[0].hashString?.split?.('/FilterExperience/')?.[1] || '';
|
|
157
|
+
// look in the map for the filter experience with the given hash
|
|
158
|
+
const filterExperiences = this.pict.providers.FilterDataProvider.getAllFiltersExperiencesForRecordSet(pRecordSet, pViewContext);
|
|
159
|
+
// BUG?: We are doing a double lookup here to match both the name and the encoded URL param, because just looking up by URL param alone can lead to issues if there are multiple experiences with the same URL param but different names.
|
|
160
|
+
const matchingExperience = filterExperiences.find((pExperience) => pExperience.FilterExperienceHash === tmpFilterExperienceList.find((exp) => exp.FilterExperienceEncodedURLParam === tmpExperienceURLParam)?.FilterExperienceHash);
|
|
161
|
+
// If we found a matching experience (both name and encoded URL param), set it as the current filter name and the active selection in the selector
|
|
162
|
+
if (!pIgnoreCurrentExperienceURLParam && matchingExperience && (matchingExperience.FilterExperienceEncodedURLParam === tmpExperienceURLParam))
|
|
163
|
+
{
|
|
164
|
+
this.pict.providers.FilterDataProvider.setCurrentFilterName(matchingExperience, pRecordSet, pViewContext);
|
|
165
|
+
this.filterExperienceSelection = matchingExperience.FilterExperienceHash;
|
|
166
|
+
// check if the current filter experience is set as default on load, so we can set the button states accordingly
|
|
167
|
+
const isDefault = this.pict.providers.FilterDataProvider.isDefaultFilterExperience(pRecordSet, pViewContext, this.filterExperienceSelection);
|
|
168
|
+
this.handleSelectionButtonStates(isDefault);
|
|
169
|
+
}
|
|
170
|
+
else
|
|
171
|
+
{
|
|
172
|
+
this.pict.providers.FilterDataProvider.setCurrentFilterName(null, pRecordSet, pViewContext, null);
|
|
173
|
+
this.filterExperienceSelection = null;
|
|
174
|
+
this.handleSelectionButtonStates(null);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Toggles the filter persistence UI for a given record set and view context
|
|
180
|
+
* @param {string} pRecordSet - The identifier of the record set.
|
|
181
|
+
* @param {string} pViewContext - The context of the view.
|
|
182
|
+
* @param {function} pCallback - A callback function to be executed after toggling the UI.
|
|
183
|
+
* @returns {boolean} - Returns true when the UI has been toggled.
|
|
184
|
+
*/
|
|
185
|
+
openFilterPersistenceUI(pRecordSet, pViewContext, pCallback)
|
|
186
|
+
{
|
|
187
|
+
// hide the button that was just clicked on (will use a different button to close the UI)
|
|
188
|
+
if (document.getElementById('PRSP_Filter_Button_Manage'))
|
|
189
|
+
{
|
|
190
|
+
document.getElementById('PRSP_Filter_Button_Manage').style.display = 'none';
|
|
191
|
+
}
|
|
192
|
+
// render the UI for managing filter persistence settings
|
|
193
|
+
this.initializeFilterPersistenceViewUI(pRecordSet, pViewContext, pCallback);
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Handles the state of the filter experience when it has been modified from the URL hash instead of through the UI, which can lead to an invalid state for saving if the user tries to save without realizing the current experience was modified outside of the UI.
|
|
199
|
+
* This method will show a warning message and disable the save/set as default/remove as default/delete buttons to prevent unintended consequences of saving in that state, and will prompt the user to load a filter experience through the UI or refresh the page to reset the state before they can save. It will also disable the current filter name input and set a warning message in it to indicate that the user needs to apply or reset filters changes to be able to save settings. If the filter experience is not in that modified state, it will ensure the buttons are enabled and the current filter name input is enabled and populated with the current filter experience name for better visibility when saving.
|
|
200
|
+
*/
|
|
201
|
+
handleModifiedFiltersState()
|
|
202
|
+
{
|
|
203
|
+
// if the current filter experience was modified from the URL hash, show a warning toast to the user that they need to load a filter experience through the UI or refresh the page to reset the state before they can save, since saving in that state could lead to unintended consequences of saving an unintended filter experience as the default or overwriting an existing filter experience without realizing it
|
|
204
|
+
if (this.pict.providers.FilterDataProvider.filterExperienceModifiedFromURLHash)
|
|
205
|
+
{
|
|
206
|
+
// disable the save and set as default buttons to prevent saving in this state
|
|
207
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-SaveFilterButton', 'disabled', 'disabled');
|
|
208
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-SetAsDefaultButton', 'disabled', 'disabled');
|
|
209
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-RemoveAsDefaultButton', 'disabled', 'disabled');
|
|
210
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-DeleteFilterButton', 'disabled', 'disabled');
|
|
211
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-CurrentFilterNameInput-ValidationMessage', 'Please apply or reset filter changes to enable saving settings.');
|
|
212
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-CurrentFilterNameInput', 'title', 'The current filter experience has been modified. Please apply or reset filter changes to enable saving settings and set a default filter experience.');
|
|
213
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-CurrentFilterNameInput', 'disabled', 'disabled');
|
|
214
|
+
}
|
|
215
|
+
else
|
|
216
|
+
{
|
|
217
|
+
// re-enable the buttons in case they were disabled from being in a modified state, to allow saving and setting default again
|
|
218
|
+
this.pict.ContentAssignment.removeAttribute('#FilterPersistenceView-SaveFilterButton', 'disabled');
|
|
219
|
+
this.pict.ContentAssignment.removeAttribute('#FilterPersistenceView-SetAsDefaultButton', 'disabled');
|
|
220
|
+
this.pict.ContentAssignment.removeAttribute('#FilterPersistenceView-RemoveAsDefaultButton', 'disabled');
|
|
221
|
+
this.pict.ContentAssignment.removeAttribute('#FilterPersistenceView-DeleteFilterButton', 'disabled');
|
|
222
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-CurrentFilterNameInput-ValidationMessage', '');
|
|
223
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-CurrentFilterNameInput', 'title', '');
|
|
224
|
+
this.pict.ContentAssignment.removeAttribute('#FilterPersistenceView-CurrentFilterNameInput', 'disabled');
|
|
225
|
+
}
|
|
226
|
+
// regardless of the modified state, update the current filter name input to match the current filter experience for better visibility when saving and to ensure it reflects any changes that may have happened to the filter experience from the URL hash or elsewhere
|
|
227
|
+
this.updateDisplayNameInputWithCurrentFilterExperience(this.currentRecordSet, this.currentViewContext, this.pict.providers.FilterDataProvider.filterExperienceModifiedFromURLHash);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Updates the filter experience settings for a given record set and view context.
|
|
232
|
+
* @param {string} pRecordSet - The identifier of the record set.
|
|
233
|
+
* @param {string} pViewContext - The context of the view.
|
|
234
|
+
* @param {object} pSettings - The settings to update.
|
|
235
|
+
* @returns {boolean} - Returns true when the settings have been updated.
|
|
236
|
+
*/
|
|
237
|
+
updateFilterExperienceSettings(pRecordSet, pViewContext, pSettings)
|
|
238
|
+
{
|
|
239
|
+
if (pRecordSet && pViewContext)
|
|
240
|
+
{
|
|
241
|
+
this.pict.providers.FilterDataProvider.initializeFilterExperienceSettings(pRecordSet, pViewContext);
|
|
242
|
+
this.currentRecordSet = pRecordSet;
|
|
243
|
+
this.currentViewContext = pViewContext;
|
|
244
|
+
// for any settings that may have changed, update those without replacing the whole settings object
|
|
245
|
+
this.pict.providers.FilterDataProvider.updateFilterExperienceSettingsFromStorage(pRecordSet, pViewContext, pSettings);
|
|
246
|
+
// build the select options for available filter experiences
|
|
247
|
+
this.buildSelectOptionsForAvailableFilterExperiences();
|
|
248
|
+
}
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Sets the filter experience to load based on user selection.
|
|
254
|
+
* @param {Event} event - The event object.
|
|
255
|
+
* @returns {boolean} - Returns true when the filter experience has been set.
|
|
256
|
+
*/
|
|
257
|
+
setFilterExperienceToSelection(event)
|
|
258
|
+
{
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
event.stopPropagation();
|
|
261
|
+
|
|
262
|
+
this.filterExperienceSelection = this.pict.ContentAssignment.readContent('#FilterPersistenceView-StoredFiltersSelect');
|
|
263
|
+
// check if the selected filter experience is set as default on load, so we can set the button states accordingly
|
|
264
|
+
const isDefault = this.pict.providers.FilterDataProvider.isDefaultFilterExperience(this.currentRecordSet, this.currentViewContext, this.filterExperienceSelection);
|
|
265
|
+
this.handleSelectionButtonStates(isDefault);
|
|
266
|
+
// set the current filter name in the provider to match the selection
|
|
267
|
+
const tmpSelectedFilterExperience = this.pict.providers.FilterDataProvider.getFilterExperienceByHash(this.currentRecordSet, this.currentViewContext, this.filterExperienceSelection);
|
|
268
|
+
let tmpBackupDisplayName = '';
|
|
269
|
+
if (!tmpSelectedFilterExperience)
|
|
270
|
+
{
|
|
271
|
+
tmpBackupDisplayName = `New ${this.currentRecordSet} ${this.currentViewContext} Filter`;
|
|
272
|
+
}
|
|
273
|
+
this.pict.providers.FilterDataProvider.setCurrentFilterName(tmpSelectedFilterExperience, this.currentRecordSet, this.currentViewContext, tmpBackupDisplayName);
|
|
274
|
+
// update the save button to text to be "Update" instead of "Save" if the selected filter experience is the current one, to indicate that clicking it will update the existing filter experience instead of creating a new one
|
|
275
|
+
if (this.filterExperienceSelection && this.pict.providers.FilterDataProvider.isCurrentFilterExperience(this.currentRecordSet, this.currentViewContext, this.filterExperienceSelection))
|
|
276
|
+
{
|
|
277
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-SaveFilterButtonTextText', 'Update');
|
|
278
|
+
}
|
|
279
|
+
else
|
|
280
|
+
{
|
|
281
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-SaveFilterButtonTextText', 'Save');
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Closes the filter persistence UI.
|
|
288
|
+
* @returns {boolean} - Returns true when the UI has been closed.
|
|
289
|
+
*/
|
|
290
|
+
closeFilterPersistenceUI()
|
|
291
|
+
{
|
|
292
|
+
this.currentRecordSet = null;
|
|
293
|
+
this.currentViewContext = null;
|
|
294
|
+
this.filterExperienceSelection = null;
|
|
295
|
+
this.handleSelectionButtonStates(null);
|
|
296
|
+
// show the button that was hidden when opening the UI
|
|
297
|
+
if (document.getElementById('PRSP_Filter_Button_Manage'))
|
|
298
|
+
{
|
|
299
|
+
document.getElementById('PRSP_Filter_Button_Manage').style.display = 'inline-block';
|
|
300
|
+
}
|
|
301
|
+
// Clear the content of the Filter Persistence View (if it's still on the DOM - it will re-render next time it's opened either way, but this is to ensure we don't have stale content if the view is still around in the DOM)
|
|
302
|
+
if (document.getElementById('FilterPersistenceView-Content'))
|
|
303
|
+
{
|
|
304
|
+
document.getElementById('FilterPersistenceView-Content').innerHTML = '';
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Builds the select options for available filter experiences. Sets the current filter as selected and indicates it in the option text.
|
|
311
|
+
* @returns {boolean} - Returns true when the options have been built.
|
|
312
|
+
*/
|
|
313
|
+
buildSelectOptionsForAvailableFilterExperiences()
|
|
314
|
+
{
|
|
315
|
+
let optionList = []
|
|
316
|
+
const filterExperienceList = this.pict.providers.FilterDataProvider.getAllFiltersExperiencesForRecordSet(this.currentRecordSet, this.currentViewContext);
|
|
317
|
+
// add a default option at the top
|
|
318
|
+
optionList.push('<option value="">-- Select a stored Filter Experience --</option>');
|
|
319
|
+
// iterate through the filter experiences and build the option elements
|
|
320
|
+
for (const key in filterExperienceList)
|
|
321
|
+
{
|
|
322
|
+
// skip excluded ones (if needed for hidden/internal use)
|
|
323
|
+
if (filterExperienceList[key].ExcludedFromSelection)
|
|
324
|
+
{
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
// if the current filter is the active/default one, mention that in the option text for clarity
|
|
328
|
+
const isCurrent = this.pict.providers.FilterDataProvider.isCurrentFilterExperience(this.currentRecordSet, this.currentViewContext, filterExperienceList[key].FilterExperienceHash);
|
|
329
|
+
const isDefault = this.pict.providers.FilterDataProvider.isDefaultFilterExperience(this.currentRecordSet, this.currentViewContext, filterExperienceList[key].FilterExperienceHash);
|
|
330
|
+
let addOnText = '';
|
|
331
|
+
if (isCurrent)
|
|
332
|
+
{
|
|
333
|
+
addOnText += ' (Current)';
|
|
334
|
+
}
|
|
335
|
+
if (isDefault)
|
|
336
|
+
{
|
|
337
|
+
addOnText += ' (Default)';
|
|
338
|
+
}
|
|
339
|
+
const optionElement = `<option ${ isCurrent ? 'selected' : ''} value="${filterExperienceList[key].FilterExperienceHash}">${filterExperienceList[key].FilterDisplayName || filterExperienceList[key].FilterExperienceHash}${addOnText}</option>`;
|
|
340
|
+
optionList.push(optionElement);
|
|
341
|
+
}
|
|
342
|
+
/* @type {HTMLSelectElement} */
|
|
343
|
+
const storedFiltersSelect = document.getElementById('FilterPersistenceView-StoredFiltersSelect');
|
|
344
|
+
if (storedFiltersSelect)
|
|
345
|
+
{
|
|
346
|
+
storedFiltersSelect.innerHTML = optionList.join('\n');
|
|
347
|
+
}
|
|
348
|
+
// after rebuilding the options, if there is a current selection, ensure the save button text is correct based on whether the current selection is the active filter experience or not
|
|
349
|
+
if (this.filterExperienceSelection && this.pict.providers.FilterDataProvider.isCurrentFilterExperience(this.currentRecordSet, this.currentViewContext, this.filterExperienceSelection))
|
|
350
|
+
{
|
|
351
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-SaveFilterButtonText', 'Update');
|
|
352
|
+
}
|
|
353
|
+
else
|
|
354
|
+
{
|
|
355
|
+
this.pict.ContentAssignment.assignContent('#FilterPersistenceView-SaveFilterButtonText', 'Save');
|
|
356
|
+
}
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Toggles the "Remember Last Used Filter Experience" setting in the Filter Data Provider.
|
|
362
|
+
* @param {Event} event - The event object.
|
|
363
|
+
* @returns {boolean} - Returns true when the setting has been toggled.
|
|
364
|
+
*/
|
|
365
|
+
toggleRememberLastUsedFilterExperience(event)
|
|
366
|
+
{
|
|
367
|
+
event.preventDefault();
|
|
368
|
+
event.stopPropagation();
|
|
369
|
+
|
|
370
|
+
const checkboxElement = document.getElementById('OptionalSettings-RememberLastUsed');
|
|
371
|
+
// @ts-ignore
|
|
372
|
+
const rememberLastUsed = checkboxElement ? checkboxElement.checked : false;
|
|
373
|
+
|
|
374
|
+
this.pict.providers.FilterDataProvider.setRememberLastUsedFilterExperience(this.currentRecordSet, this.currentViewContext, rememberLastUsed);
|
|
375
|
+
this.pict.log.info(`Remember Last Used Filter Experience has been ${rememberLastUsed ? 'enabled' : 'disabled'}.`);
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Loads the filter persistence settings for the current selection of filter experiences.
|
|
381
|
+
* @param {Event} event - The event object.
|
|
382
|
+
* @returns {boolean} - Returns true when the settings have been loaded.
|
|
383
|
+
*/
|
|
384
|
+
loadFilterPersistenceSettings(event, pCallback)
|
|
385
|
+
{
|
|
386
|
+
event.preventDefault();
|
|
387
|
+
event.stopPropagation();
|
|
388
|
+
const selectedFilterExperienceHash = this.filterExperienceSelection;
|
|
389
|
+
if (!selectedFilterExperienceHash)
|
|
390
|
+
{
|
|
391
|
+
this.pict.log.warn('No filter experience selected to load.');
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
this.pict.providers.FilterDataProvider.loadFilterMeta(this.currentRecordSet, this.currentViewContext, selectedFilterExperienceHash);
|
|
395
|
+
this.pict.log.info(`Filter persistence settings have been loaded for filter: ${selectedFilterExperienceHash}`);
|
|
396
|
+
this.pict.providers.FilterDataProvider.filterExperienceModifiedFromURLHash = false;
|
|
397
|
+
// if a callback function was provided, execute it after loading the settings (toasts, etc.)
|
|
398
|
+
if (pCallback && typeof pCallback === 'function')
|
|
399
|
+
{
|
|
400
|
+
pCallback();
|
|
401
|
+
}
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Saves the filter persistence settings for the current selection of filter experiences.
|
|
407
|
+
* @param {Event} event - The event object.
|
|
408
|
+
* @param {function} [pCallback] - A callback function to be executed after saving the settings.
|
|
409
|
+
* @returns {boolean} - Returns true when the settings have been saved.
|
|
410
|
+
*/
|
|
411
|
+
saveFilterPersistenceSettings(event, pCallback)
|
|
412
|
+
{
|
|
413
|
+
event.preventDefault();
|
|
414
|
+
event.stopPropagation();
|
|
415
|
+
|
|
416
|
+
if (!this.currentRecordSet || !this.currentViewContext)
|
|
417
|
+
{
|
|
418
|
+
this.pict.log.warn('Missing a record set or view context to save filter persistence settings. Skipping save. CurrentRecordSet: ' + this.currentRecordSet + ', CurrentViewContext: ' + this.currentViewContext + ')');
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (this.pict.providers.FilterDataProvider.filterExperienceModifiedFromURLHash)
|
|
423
|
+
{
|
|
424
|
+
this.pict.log.warn('The current filter experience has been modified from the URL hash and not through the UI, so it may not be in a valid state to save. Please load a filter experience through the UI or refresh the page to reset the state before saving.');
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.pict.providers.FilterDataProvider.saveFilterMeta(this.currentRecordSet, this.currentViewContext, false);
|
|
429
|
+
this.buildSelectOptionsForAvailableFilterExperiences();
|
|
430
|
+
this.pict.log.info('Filter persistence settings have been saved.');
|
|
431
|
+
// if a callback function was provided, execute it after saving the settings (toasts, etc.)
|
|
432
|
+
if (pCallback && typeof pCallback === 'function')
|
|
433
|
+
{
|
|
434
|
+
pCallback();
|
|
435
|
+
}
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Sets the filter experience as the default for the current record set and view context.
|
|
441
|
+
* @param {Event} event - The event object.
|
|
442
|
+
* @param {boolean} isDefault - Whether to set as default or not.
|
|
443
|
+
* @param {function} [pCallback] - A callback function to be executed after toggling the default setting.
|
|
444
|
+
* @returns {boolean} - Returns true when the settings have been set as default.
|
|
445
|
+
*/
|
|
446
|
+
toggleFilterExperienceAsTheDefault(event, isDefault, pCallback)
|
|
447
|
+
{
|
|
448
|
+
event.preventDefault();
|
|
449
|
+
event.stopPropagation();
|
|
450
|
+
|
|
451
|
+
const selectedFilterExperienceHash = this.filterExperienceSelection;
|
|
452
|
+
if (!selectedFilterExperienceHash)
|
|
453
|
+
{
|
|
454
|
+
this.pict.log.warn('No filter experience selected to set as default.');
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
// set or unset the default filter experience on load in the provider
|
|
458
|
+
this.pict.providers.FilterDataProvider.setDefaultFilterExperience(this.currentRecordSet, this.currentViewContext, selectedFilterExperienceHash, isDefault);
|
|
459
|
+
this.handleSelectionButtonStates(isDefault);
|
|
460
|
+
|
|
461
|
+
this.buildSelectOptionsForAvailableFilterExperiences();
|
|
462
|
+
this.pict.log.info(`Filter experience ${selectedFilterExperienceHash} has been ${isDefault ? 'set' : 'unset'} as the default on load.`);
|
|
463
|
+
// if a callback function was provided, execute it after setting the default (toasts, etc.)
|
|
464
|
+
if (pCallback && typeof pCallback === 'function')
|
|
465
|
+
{
|
|
466
|
+
pCallback();
|
|
467
|
+
}
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Handles the button states for the filter experience selection.
|
|
473
|
+
* @param {boolean} isDefault - Whether the filter experience is set as default or not.
|
|
474
|
+
*/
|
|
475
|
+
handleSelectionButtonStates(isDefault)
|
|
476
|
+
{
|
|
477
|
+
if (!this.filterExperienceSelection)
|
|
478
|
+
{
|
|
479
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-LoadFilterButton', 'style', 'display: none;');
|
|
480
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-SetAsDefaultButton', 'style', 'display: none;');
|
|
481
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-RemoveAsDefaultButton', 'style', 'display: none;');
|
|
482
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-DeleteFilterButton', 'style', 'display: none;');
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
else
|
|
486
|
+
{
|
|
487
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-LoadFilterButton', 'style', 'display: inline-block;');
|
|
488
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-DeleteFilterButton', 'style', 'display: inline-block;');
|
|
489
|
+
}
|
|
490
|
+
// handle the set/remove default buttons separately when we have a selection
|
|
491
|
+
if (isDefault)
|
|
492
|
+
{
|
|
493
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-SetAsDefaultButton', 'style', 'display: none;');
|
|
494
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-RemoveAsDefaultButton', 'style', 'display: inline-block;');
|
|
495
|
+
}
|
|
496
|
+
else
|
|
497
|
+
{
|
|
498
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-SetAsDefaultButton', 'style', 'display: inline-block;');
|
|
499
|
+
this.pict.ContentAssignment.setAttribute('#FilterPersistenceView-RemoveAsDefaultButton', 'style', 'display: none;');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Deletes the filter persistence settings for the current selection of filter experiences.
|
|
505
|
+
* @param {Event} event - The event object.
|
|
506
|
+
* @param {function} [pCallback] - A callback function to be executed after deleting the settings.
|
|
507
|
+
* @returns {boolean} - Returns true when the settings have been deleted.
|
|
508
|
+
*/
|
|
509
|
+
deleteFilterPersistenceSettings(event, pCallback)
|
|
510
|
+
{
|
|
511
|
+
event.preventDefault();
|
|
512
|
+
event.stopPropagation();
|
|
513
|
+
|
|
514
|
+
const selectedFilterExperienceHash = this.filterExperienceSelection;
|
|
515
|
+
if (!selectedFilterExperienceHash)
|
|
516
|
+
{
|
|
517
|
+
this.pict.log.warn('No filter experience selected to delete.');
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
this.pict.providers.FilterDataProvider.removeFilterMeta(this.currentRecordSet, this.currentViewContext, selectedFilterExperienceHash);
|
|
521
|
+
this.buildSelectOptionsForAvailableFilterExperiences();
|
|
522
|
+
this.pict.log.info(`Filter persistence settings have been deleted for filter: ${selectedFilterExperienceHash}`);
|
|
523
|
+
// if a callback function was provided, execute it after deleting the settings (toasts, etc.)
|
|
524
|
+
if (pCallback && typeof pCallback === 'function')
|
|
525
|
+
{
|
|
526
|
+
pCallback();
|
|
527
|
+
}
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
module.exports = viewFilterPersistenceView;
|
|
533
|
+
|
|
534
|
+
module.exports.default_configuration = _DEFAULT_CONFIGURATION_FilterPersistenceView;
|