pict-section-recordset 1.0.24 → 1.0.26
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/example_applications/simple_entity/Simple-RecordSet-Application.js +170 -110
- package/package.json +7 -7
- package/source/application/Pict-Application-RecordSet.js +8 -0
- package/source/providers/RecordSet-Link-Manager.js +2 -2
- package/source/providers/RecordSet-RecordProvider-Base.js +9 -2
- package/source/providers/RecordSet-RecordProvider-MeadowEndpoints.js +116 -14
- package/source/services/RecordsSet-MetaController.js +41 -19
- package/source/templates/Pict-Template-FilterInstanceViews.js +222 -0
- package/source/templates/Pict-Template-FilterView.js +4 -2
- package/source/views/RecordSet-Filters.js +449 -0
- package/source/views/dashboard/RecordSet-Dashboard.js +65 -8
- package/source/views/filters/RecordSet-Filter-Base-Range.js +38 -0
- package/source/views/filters/RecordSet-Filter-Base.js +88 -0
- package/source/views/filters/RecordSet-Filter-DateMatch.js +56 -0
- package/source/views/filters/RecordSet-Filter-DateRange.js +75 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinDateMatch.js +55 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinDateRange.js +57 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinNumericMatch.js +54 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinNumericRange.js +57 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinStringMatch.js +45 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinStringRange.js +46 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinDateMatch.js +55 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinDateRange.js +57 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinNumericMatch.js +55 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinNumericRange.js +57 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinStringMatch.js +45 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinStringRange.js +46 -0
- package/source/views/filters/RecordSet-Filter-NumericMatch.js +55 -0
- package/source/views/filters/RecordSet-Filter-NumericRange.js +57 -0
- package/source/views/filters/RecordSet-Filter-StringMatch.js +45 -0
- package/source/views/filters/RecordSet-Filter-StringRange.js +46 -0
- package/source/views/filters/index.js +27 -0
- package/source/views/list/RecordSet-List.js +44 -6
- package/test/PictSectionRecordSet-RecordProvider-Meadow_tests.js +11 -0
- package/types/application/Pict-Application-RecordSet.d.ts.map +1 -1
- package/types/providers/RecordSet-DynamicRecordsetSolver.d.ts +6 -6
- package/types/providers/RecordSet-DynamicRecordsetSolver.d.ts.map +1 -1
- package/types/providers/RecordSet-Link-Manager.d.ts +3 -3
- package/types/providers/RecordSet-RecordProvider-Base.d.ts +9 -0
- package/types/providers/RecordSet-RecordProvider-Base.d.ts.map +1 -1
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts +30 -4
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts.map +1 -1
- package/types/services/RecordsSet-MetaController.d.ts +2 -2
- package/types/services/RecordsSet-MetaController.d.ts.map +1 -1
- package/types/templates/Pict-Template-FilterInstanceViews.d.ts +19 -0
- package/types/templates/Pict-Template-FilterInstanceViews.d.ts.map +1 -0
- package/types/templates/Pict-Template-FilterView.d.ts.map +1 -1
- package/types/views/RecordSet-Filters.d.ts +84 -0
- package/types/views/RecordSet-Filters.d.ts.map +1 -0
- package/types/views/dashboard/RecordSet-Dashboard.d.ts +4 -2
- package/types/views/dashboard/RecordSet-Dashboard.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-Base-Range.d.ts +5 -0
- package/types/views/filters/RecordSet-Filter-Base-Range.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-Base.d.ts +29 -0
- package/types/views/filters/RecordSet-Filter-Base.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-DateMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-DateMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-DateRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-DateRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinDateRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinNumericRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinStringMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinStringMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinStringRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinStringRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinDateMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinDateMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinDateRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinDateRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinNumericRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinStringMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinStringMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinStringRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinStringRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-NumericMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-NumericMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-NumericRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-NumericRange.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-StringMatch.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-StringMatch.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-StringRange.d.ts +9 -0
- package/types/views/filters/RecordSet-Filter-StringRange.d.ts.map +1 -0
- package/types/views/filters/index.d.ts +20 -0
- package/types/views/filters/index.d.ts.map +1 -0
- package/types/views/list/RecordSet-List.d.ts +12 -2
- package/types/views/list/RecordSet-List.d.ts.map +1 -1
- package/source/views/RecordSet-Filter.js +0 -159
- package/types/views/RecordSet-Filter.d.ts +0 -39
- package/types/views/RecordSet-Filter.d.ts.map +0 -1
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
/** @type {Record<string, any>} */
|
|
4
|
+
const _DEFAULT_CONFIGURATION_SUBSET_Filter =
|
|
5
|
+
{
|
|
6
|
+
ViewIdentifier: 'PRSP-SUBSET-Filters',
|
|
7
|
+
|
|
8
|
+
DefaultRenderable: 'PRSP_Renderable_Filters',
|
|
9
|
+
DefaultDestinationAddress: '#PRSP_Filters_Container',
|
|
10
|
+
DefaultTemplateRecordAddress: false,
|
|
11
|
+
|
|
12
|
+
// If this is set to true, when the App initializes this will.
|
|
13
|
+
// While the App initializes, initialize will be called.
|
|
14
|
+
AutoInitialize: false,
|
|
15
|
+
AutoInitializeOrdinal: 0,
|
|
16
|
+
|
|
17
|
+
// If this is set to true, when the App autorenders (on load) this will.
|
|
18
|
+
// After the App initializes, render will be called.
|
|
19
|
+
AutoRender: false,
|
|
20
|
+
AutoRenderOrdinal: 0,
|
|
21
|
+
|
|
22
|
+
AutoSolveWithApp: false,
|
|
23
|
+
AutoSolveOrdinal: 0,
|
|
24
|
+
|
|
25
|
+
CSS: false,
|
|
26
|
+
CSSPriority: 500,
|
|
27
|
+
|
|
28
|
+
Templates:
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
Hash: 'PRSP-SUBSET-Filters-Template',
|
|
32
|
+
Template: /*html*/`
|
|
33
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filters-Template] -->
|
|
34
|
+
<section id="PRSP_Filters_Container">
|
|
35
|
+
<form id="PRSP_Filter_Form" onsubmit="_Pict.views['PRSP-Filters'].handleSearch(event, '{~D:Record.RecordSet~}', '{~D:Record.ViewContext~}'); return false;">
|
|
36
|
+
{~T:PRSP-SUBSET-Filters-Template-Input-Fieldset~}
|
|
37
|
+
<div id="PRSP_Filter_Instances">
|
|
38
|
+
{~FIV:Record~}
|
|
39
|
+
</div>
|
|
40
|
+
{~T:PRSP-SUBSET-Filters-Template-Button-Fieldset~}
|
|
41
|
+
</form>
|
|
42
|
+
</section>
|
|
43
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filters-Template] -->
|
|
44
|
+
`
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
Hash: 'PRSP-SUBSET-Filters-Template-Input-Fieldset',
|
|
48
|
+
Template: /*html*/`
|
|
49
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filters-Template-Input-Fieldset] -->
|
|
50
|
+
<fieldset>
|
|
51
|
+
<label for="filter">Filter:</label>
|
|
52
|
+
<input type="text" name="filter">
|
|
53
|
+
</fieldset>
|
|
54
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filters-Template-Input-Fieldset] -->
|
|
55
|
+
`
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
Hash: 'PRSP-SUBSET-Filters-Template-Button-Fieldset',
|
|
59
|
+
Template: /*html*/`
|
|
60
|
+
<!-- DefaultPackage pict view template: [PRSP-SUBSET-Filters-Template-Button-Fieldset] -->
|
|
61
|
+
<fieldset>
|
|
62
|
+
<button type="button" id="PRSP_Filter_Button_Reset" onclick="_Pict.views['PRSP-Filters'].handleReset(event, '{~D:Record.RecordSet~}', '{~D:Record.ViewContext~}')">Reset</button>
|
|
63
|
+
<button type="submit" id="PRSP_Filter_Button_Apply">Apply</button>
|
|
64
|
+
</fieldset>
|
|
65
|
+
<!-- DefaultPackage end view template: [PRSP-SUBSET-Filters-Template-Button-Fieldset] -->
|
|
66
|
+
`
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
|
|
70
|
+
Renderables:
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
RenderableHash: 'PRSP_Renderable_Filters',
|
|
74
|
+
TemplateHash: 'PRSP-SUBSET-Filters-Template',
|
|
75
|
+
DestinationAddress: '#PRSP_Filters_Container',
|
|
76
|
+
RenderMethod: 'replace'
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
|
|
80
|
+
Manifests: {},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//FIXME: export this from PSF?
|
|
84
|
+
const libPictViewDynamicForm = require('pict-section-form/source/views/Pict-View-DynamicForm.js');
|
|
85
|
+
|
|
86
|
+
class ViewRecordSetSUBSETFilters extends libPictView
|
|
87
|
+
{
|
|
88
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
89
|
+
{
|
|
90
|
+
let tmpOptions = Object.assign({}, _DEFAULT_CONFIGURATION_SUBSET_Filter, pOptions);
|
|
91
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
92
|
+
/** @type {import('fable') & import('pict') & { PictSectionRecordSet: import('../Pict-Section-RecordSet.js') }} */
|
|
93
|
+
this.pict;
|
|
94
|
+
|
|
95
|
+
const tmpDynamicInputViewSection = (
|
|
96
|
+
{
|
|
97
|
+
"Hash": "PSRSDynamicInputs",
|
|
98
|
+
"Name": "Custom Dynamic Inputs",
|
|
99
|
+
"ViewHash": "PSRSFilterProxyView",
|
|
100
|
+
|
|
101
|
+
"AutoMarshalDataOnSolve": true,
|
|
102
|
+
"IncludeInMetatemplateSectionGeneration": false,
|
|
103
|
+
|
|
104
|
+
"Manifests":
|
|
105
|
+
{
|
|
106
|
+
"Section":
|
|
107
|
+
{
|
|
108
|
+
"Scope": "PSRSDynamic",
|
|
109
|
+
"Sections":
|
|
110
|
+
[
|
|
111
|
+
{
|
|
112
|
+
"Hash": "PSRSDynamicInputs",
|
|
113
|
+
"Name": "Dynamic Inputs"
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"Descriptors":
|
|
117
|
+
{
|
|
118
|
+
"PSRS.DynamicInputPlaceholder":
|
|
119
|
+
{
|
|
120
|
+
"Name": "DynamicInputPlaceholder",
|
|
121
|
+
"Hash": "DynamicInputPlaceholder",
|
|
122
|
+
"DataType": "String",
|
|
123
|
+
"Macro":
|
|
124
|
+
{
|
|
125
|
+
"HTMLSelector": ""
|
|
126
|
+
},
|
|
127
|
+
"PictForm":
|
|
128
|
+
{
|
|
129
|
+
"Section": "PSRSDynamicInputs"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (!this.pict.views[tmpDynamicInputViewSection.ViewHash])
|
|
137
|
+
{
|
|
138
|
+
const tmpViewConfiguration = Object.assign({}, tmpDynamicInputViewSection);
|
|
139
|
+
this.pict.addView(tmpViewConfiguration.ViewHash, tmpViewConfiguration, libPictViewDynamicForm);
|
|
140
|
+
this.pict.views[tmpDynamicInputViewSection.ViewHash].viewMarshalDestination = 'Bundle';
|
|
141
|
+
}
|
|
142
|
+
this.chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
143
|
+
|
|
144
|
+
// Use a lookup table to find the index.
|
|
145
|
+
this.lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
|
|
146
|
+
for (let i = 0; i < this.chars.length; i++)
|
|
147
|
+
{
|
|
148
|
+
this.lookup[this.chars.charCodeAt(i)] = i;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
//NOTE: two methods below copied from the pict-section-form metacontroller
|
|
153
|
+
//TODO: consider subclassing the dynamic view to somehow mark these as filter views so we can only operate on those views
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Marshals data from the view to the model, usually AppData (or configured data store).
|
|
157
|
+
*
|
|
158
|
+
* @returns {any} The result of the superclass's onMarshalFromView method.
|
|
159
|
+
*/
|
|
160
|
+
onMarshalFromView()
|
|
161
|
+
{
|
|
162
|
+
let tmpViewList = Object.keys(this.fable.views);
|
|
163
|
+
for (let i = 0; i < tmpViewList.length; i++)
|
|
164
|
+
{
|
|
165
|
+
if (this.fable.views[tmpViewList[i]].isPictSectionForm)
|
|
166
|
+
{
|
|
167
|
+
this.fable.views[tmpViewList[i]].marshalFromView();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return super.onMarshalFromView();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Marshals the data to the view from the model, usually AppData (or configured data store).
|
|
175
|
+
*
|
|
176
|
+
* @returns {any} The result of the super.onMarshalToView() method.
|
|
177
|
+
*/
|
|
178
|
+
onMarshalToView()
|
|
179
|
+
{
|
|
180
|
+
let tmpViewList = Object.keys(this.fable.views);
|
|
181
|
+
for (let i = 0; i < tmpViewList.length; i++)
|
|
182
|
+
{
|
|
183
|
+
if (this.fable.views[tmpViewList[i]].isPictSectionForm)
|
|
184
|
+
{
|
|
185
|
+
this.fable.views[tmpViewList[i]].marshalToView();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return super.onMarshalToView();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @param {Event} pEvent - The DOM event that triggered the search
|
|
193
|
+
* @param {string} pRecordSet - The record set being filtered
|
|
194
|
+
* @param {string} pViewContext - The view context for the filter (ex. List, Dashboard)
|
|
195
|
+
*/
|
|
196
|
+
handleSearch(pEvent, pRecordSet, pViewContext)
|
|
197
|
+
{
|
|
198
|
+
pEvent.preventDefault(); // don't submit the form
|
|
199
|
+
pEvent.stopPropagation();
|
|
200
|
+
//FIXME: store this filter string in the bundle so we can re-apply it on re-render
|
|
201
|
+
const tmpSearchString = this.pict.ContentAssignment.readContent(`input[name="filter"]`);
|
|
202
|
+
this.performSearch(pRecordSet, pViewContext, tmpSearchString ? String(tmpSearchString) : '');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {string} pRecordSet - The record set being filtered
|
|
207
|
+
* @param {string} pViewContext - The view context for the filter (ex. List, Dashboard)
|
|
208
|
+
* @param {string} [pFilterString] - The filter string to apply, defaults to a single space if not provided
|
|
209
|
+
*/
|
|
210
|
+
performSearch(pRecordSet, pViewContext, pFilterString)
|
|
211
|
+
{
|
|
212
|
+
const tmpPictRouter = this.pict.providers.PictRouter;
|
|
213
|
+
const tmpProviderConfiguration = this.pict.PictSectionRecordSet.recordSetProviderConfigurations[pRecordSet];
|
|
214
|
+
let filterExpr = '';
|
|
215
|
+
if (pFilterString)
|
|
216
|
+
{
|
|
217
|
+
/** @type {Array<string>} */
|
|
218
|
+
const searchFields = tmpProviderConfiguration?.SearchFields ?? [ 'Name' ];
|
|
219
|
+
filterExpr = searchFields.map((filterField) => `FBVOR~${filterField}~LK~${encodeURIComponent(`%${pFilterString}%`)}`).join('~');
|
|
220
|
+
}
|
|
221
|
+
let tmpURLTemplate = tmpProviderConfiguration[`RecordSetFilterURLTemplate-${pViewContext}`] || tmpProviderConfiguration[`RecordSetFilterURLTemplate-Default`];
|
|
222
|
+
if (!tmpURLTemplate)
|
|
223
|
+
{
|
|
224
|
+
if (pViewContext === 'Dashboard' || pViewContext === 'List')
|
|
225
|
+
{
|
|
226
|
+
tmpURLTemplate = `/PSRS/${pRecordSet}/${pViewContext}/FilteredTo/{~D:Record.FilterString~}`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
let tmpURL;
|
|
230
|
+
if (tmpURLTemplate)
|
|
231
|
+
{
|
|
232
|
+
tmpURL = this.pict.parseTemplate(tmpURLTemplate,
|
|
233
|
+
{
|
|
234
|
+
RecordSet: pRecordSet,
|
|
235
|
+
FilterString: filterExpr,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
{
|
|
240
|
+
tmpURL = `/PSRS/${pRecordSet}/List/FilteredTo/${filterExpr}`;
|
|
241
|
+
}
|
|
242
|
+
if (tmpURL.endsWith('FilteredTo/') || tmpURL.includes('FilteredTo//'))
|
|
243
|
+
{
|
|
244
|
+
tmpURL = tmpURL.replace(/\/FilteredTo\//, '');
|
|
245
|
+
}
|
|
246
|
+
this.serializeFilterExperience(this.pict.Bundle._ActiveFilterState[pRecordSet]?.FilterClauses).then((pFilterExperienceSerialized) =>
|
|
247
|
+
{
|
|
248
|
+
if (pFilterExperienceSerialized)
|
|
249
|
+
{
|
|
250
|
+
tmpURL += `/FilterExperience/${encodeURIComponent(pFilterExperienceSerialized)}`;
|
|
251
|
+
}
|
|
252
|
+
//FIXME: this doesn't force a re-render if other filters have changes, but aren't in the URL - so we either need to put them in the URL, or force a re-render based on the filter states
|
|
253
|
+
tmpPictRouter.router.navigate(tmpURL);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @param {Event} pEvent - The DOM event that triggered the search
|
|
259
|
+
* @param {string} pRecordSet - The record set being filtered
|
|
260
|
+
* @param {string} pViewContext - The view context for the filter (ex. List, Dashboard)
|
|
261
|
+
*/
|
|
262
|
+
handleReset(pEvent, pRecordSet, pViewContext)
|
|
263
|
+
{
|
|
264
|
+
pEvent.preventDefault();
|
|
265
|
+
this.pict.ContentAssignment.assignContent('input[name="filter"]', '');
|
|
266
|
+
const tmpFilterExperienceClauses = this.pict.Bundle._ActiveFilterState[pRecordSet]?.FilterClauses;
|
|
267
|
+
if (Array.isArray(tmpFilterExperienceClauses))
|
|
268
|
+
{
|
|
269
|
+
for (const tmpClause of tmpFilterExperienceClauses)
|
|
270
|
+
{
|
|
271
|
+
delete tmpClause.Value;
|
|
272
|
+
delete tmpClause.Values;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
this.performSearch(pRecordSet, pViewContext);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Lifecycle hook that triggers after the view is rendered.
|
|
280
|
+
*
|
|
281
|
+
* @param {import('pict-view').Renderable} pRenderable - The renderable that was rendered.
|
|
282
|
+
* @param {string} pRenderDestinationAddress - The address where the renderable was rendered.
|
|
283
|
+
* @param {any} pRecord - The record (data) that was used by the renderable.
|
|
284
|
+
* @param {string} pContent - The content that was rendered.
|
|
285
|
+
*/
|
|
286
|
+
onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
|
|
287
|
+
{
|
|
288
|
+
//FIXME: since this is rendering to the DOM indirectly, can't marshal right after render; need to fix this better, if this even works
|
|
289
|
+
setTimeout(() =>
|
|
290
|
+
{
|
|
291
|
+
this.onMarshalToView();
|
|
292
|
+
}, 1);
|
|
293
|
+
return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Lifecycle hook that triggers after the view is rendered (async flow).
|
|
298
|
+
*
|
|
299
|
+
* @param {import('pict-view').ErrorCallback} fCallback - The callback to call when the async operation is complete.
|
|
300
|
+
*/
|
|
301
|
+
onAfterRenderAsync(fCallback)
|
|
302
|
+
{
|
|
303
|
+
return super.onAfterRenderAsync((pError) =>
|
|
304
|
+
{
|
|
305
|
+
//FIXME: since this is rendering to the DOM indirectly, can't marshal right after render; need to fix this better, if this even works
|
|
306
|
+
setTimeout(() =>
|
|
307
|
+
{
|
|
308
|
+
this.onMarshalToView();
|
|
309
|
+
}, 1);
|
|
310
|
+
fCallback(pError);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async serializeFilterExperience(pExperience)
|
|
315
|
+
{
|
|
316
|
+
if (!pExperience || typeof pExperience !== 'object')
|
|
317
|
+
{
|
|
318
|
+
return '';
|
|
319
|
+
}
|
|
320
|
+
return this.encode(await this.compress(JSON.stringify(pExperience)));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* @param {string} pExperience - The serialized filter experience as a string.
|
|
325
|
+
*
|
|
326
|
+
* @return {Promise<Record<string, any>>} - The serialized filter experience as a string.
|
|
327
|
+
*/
|
|
328
|
+
async deserializeFilterExperience(pExperience)
|
|
329
|
+
{
|
|
330
|
+
if (!pExperience || typeof pExperience !== 'string')
|
|
331
|
+
{
|
|
332
|
+
//TODO: if the default filters expand, how we wanna handle that?
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
return JSON.parse(await this.decompress(new Uint8Array(this.decode(pExperience))));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* @param {string} string - The string to compress.
|
|
340
|
+
* @param {CompressionFormat} [encoding='gzip'] - The encoding to use for compression, defaults to 'gzip'.
|
|
341
|
+
*
|
|
342
|
+
* @return {Promise<ArrayBuffer>} - The compressed byte array.
|
|
343
|
+
*/
|
|
344
|
+
async compress(string, encoding = 'gzip')
|
|
345
|
+
{
|
|
346
|
+
const byteArray = new TextEncoder().encode(string);
|
|
347
|
+
const cs = new CompressionStream(encoding);
|
|
348
|
+
const writer = cs.writable.getWriter();
|
|
349
|
+
writer.write(byteArray);
|
|
350
|
+
writer.close();
|
|
351
|
+
return new Response(cs.readable).arrayBuffer();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* @param {Uint8Array} byteArray - The byte array to decompress.
|
|
356
|
+
* @param {CompressionFormat} [encoding='gzip'] - The encoding to use for compression, defaults to 'gzip'.
|
|
357
|
+
*/
|
|
358
|
+
async decompress(byteArray, encoding = 'gzip')
|
|
359
|
+
{
|
|
360
|
+
const cs = new DecompressionStream(encoding);
|
|
361
|
+
const writer = cs.writable.getWriter();
|
|
362
|
+
writer.write(byteArray);
|
|
363
|
+
writer.close();
|
|
364
|
+
return new Response(cs.readable).arrayBuffer().then((arrayBuffer) =>
|
|
365
|
+
{
|
|
366
|
+
return new TextDecoder().decode(arrayBuffer);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @param {ArrayBuffer} arraybuffer - The ArrayBuffer to encode to Base64.
|
|
372
|
+
*
|
|
373
|
+
* @return {string} - The Base64 encoded string.
|
|
374
|
+
*/
|
|
375
|
+
encode(arraybuffer)
|
|
376
|
+
{
|
|
377
|
+
let bytes = new Uint8Array(arraybuffer),
|
|
378
|
+
i,
|
|
379
|
+
len = bytes.length,
|
|
380
|
+
base64 = '';
|
|
381
|
+
|
|
382
|
+
for (i = 0; i < len; i += 3)
|
|
383
|
+
{
|
|
384
|
+
base64 += this.chars[bytes[i] >> 2];
|
|
385
|
+
base64 += this.chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
|
386
|
+
base64 += this.chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
|
387
|
+
base64 += this.chars[bytes[i + 2] & 63];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (len % 3 === 2)
|
|
391
|
+
{
|
|
392
|
+
base64 = base64.substring(0, base64.length - 1) + '=';
|
|
393
|
+
}
|
|
394
|
+
else if (len % 3 === 1)
|
|
395
|
+
{
|
|
396
|
+
base64 = base64.substring(0, base64.length - 2) + '==';
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return base64;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @param {string} base64 - The Base64 encoded string to decode to an ArrayBuffer.
|
|
404
|
+
*
|
|
405
|
+
* @return {ArrayBuffer} - The decoded ArrayBuffer.
|
|
406
|
+
*/
|
|
407
|
+
decode(base64)
|
|
408
|
+
{
|
|
409
|
+
let bufferLength = base64.length * 0.75,
|
|
410
|
+
len = base64.length,
|
|
411
|
+
i,
|
|
412
|
+
p = 0,
|
|
413
|
+
encoded1,
|
|
414
|
+
encoded2,
|
|
415
|
+
encoded3,
|
|
416
|
+
encoded4;
|
|
417
|
+
|
|
418
|
+
if (base64[base64.length - 1] === '=')
|
|
419
|
+
{
|
|
420
|
+
bufferLength--;
|
|
421
|
+
if (base64[base64.length - 2] === '=')
|
|
422
|
+
{
|
|
423
|
+
bufferLength--;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const arraybuffer = new ArrayBuffer(bufferLength),
|
|
428
|
+
bytes = new Uint8Array(arraybuffer);
|
|
429
|
+
|
|
430
|
+
for (i = 0; i < len; i += 4)
|
|
431
|
+
{
|
|
432
|
+
encoded1 = this.lookup[base64.charCodeAt(i)];
|
|
433
|
+
encoded2 = this.lookup[base64.charCodeAt(i + 1)];
|
|
434
|
+
encoded3 = this.lookup[base64.charCodeAt(i + 2)];
|
|
435
|
+
encoded4 = this.lookup[base64.charCodeAt(i + 3)];
|
|
436
|
+
|
|
437
|
+
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
|
438
|
+
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
|
439
|
+
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return arraybuffer;
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
module.exports = ViewRecordSetSUBSETFilters;
|
|
447
|
+
|
|
448
|
+
module.exports.default_configuration = _DEFAULT_CONFIGURATION_SUBSET_Filter;
|
|
449
|
+
|
|
@@ -2,7 +2,7 @@ const libPictRecordSetRecordView = require('../RecordSet-RecordBaseView.js');
|
|
|
2
2
|
|
|
3
3
|
const viewHeaderDashboard = require('./RecordSet-Dashboard-HeaderDashboard.js');
|
|
4
4
|
const viewTitle = require('./RecordSet-Dashboard-Title.js');
|
|
5
|
-
const viewFilters = require('../RecordSet-
|
|
5
|
+
const viewFilters = require('../RecordSet-Filters.js');
|
|
6
6
|
const viewPaginationTop = require('./RecordSet-Dashboard-PaginationTop.js');
|
|
7
7
|
const viewRecordList = require('./RecordSet-Dashboard-RecordList.js');
|
|
8
8
|
const viewRecordListHeader = require('./RecordSet-Dashboard-RecordListHeader.js');
|
|
@@ -119,15 +119,16 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
119
119
|
const tmpProviderHash = `RSP-Provider-${pRoutePayload.data.RecordSet}`;
|
|
120
120
|
|
|
121
121
|
const tmpFilterString = pRoutePayload.data.FilterString || '';
|
|
122
|
+
const tmpSerializedFilterExperience = pRoutePayload.data.FilterExperience || '';
|
|
122
123
|
|
|
123
124
|
const tmpOffset = pRoutePayload.data.Offset ? pRoutePayload.data.Offset : 0;
|
|
124
125
|
const tmpPageSize = pRoutePayload.data.PageSize ? pRoutePayload.data.PageSize : 100;
|
|
125
126
|
|
|
126
127
|
if (pRoutePayload.data.DashboardHash)
|
|
127
128
|
{
|
|
128
|
-
return this.renderSpecificDashboard(pRoutePayload.data.DashboardHash, tmpProviderConfiguration, tmpProviderHash, tmpFilterString, tmpOffset, tmpPageSize);
|
|
129
|
+
return this.renderSpecificDashboard(pRoutePayload.data.DashboardHash, tmpProviderConfiguration, tmpProviderHash, tmpFilterString, tmpSerializedFilterExperience, tmpOffset, tmpPageSize);
|
|
129
130
|
}
|
|
130
|
-
return this.renderDashboard(tmpProviderConfiguration, tmpProviderHash, tmpFilterString, tmpOffset, tmpPageSize);
|
|
131
|
+
return this.renderDashboard(tmpProviderConfiguration, tmpProviderHash, tmpFilterString, tmpSerializedFilterExperience, tmpOffset, tmpPageSize);
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
/**
|
|
@@ -135,14 +136,22 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
135
136
|
*/
|
|
136
137
|
addRoutes(pPictRouter)
|
|
137
138
|
{
|
|
139
|
+
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
140
|
+
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/FilteredTo/:FilterString/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
141
|
+
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/FilteredTo/:FilterString/:Offset/:PageSize/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
138
142
|
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/FilteredTo/:FilterString/:Offset/:PageSize', this.handleRecordSetDashboardRoute.bind(this));
|
|
139
143
|
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/FilteredTo/:FilterString', this.handleRecordSetDashboardRoute.bind(this));
|
|
144
|
+
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/:Offset/:PageSize/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
140
145
|
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/:Offset/:PageSize', this.handleRecordSetDashboardRoute.bind(this));
|
|
141
146
|
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard/:Offset', this.handleRecordSetDashboardRoute.bind(this));
|
|
142
147
|
pPictRouter.router.on('/PSRS/:RecordSet/Dashboard', this.handleRecordSetDashboardRoute.bind(this));
|
|
143
148
|
|
|
149
|
+
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
150
|
+
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/FilteredTo/:FilterString/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
151
|
+
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/FilteredTo/:FilterString/:Offset/:PageSize/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
144
152
|
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/FilteredTo/:FilterString/:Offset/:PageSize', this.handleRecordSetDashboardRoute.bind(this));
|
|
145
153
|
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/FilteredTo/:FilterString', this.handleRecordSetDashboardRoute.bind(this));
|
|
154
|
+
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/:Offset/:PageSize/FilterExperience/:FilterExperience', this.handleRecordSetDashboardRoute.bind(this));
|
|
146
155
|
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/:Offset/:PageSize', this.handleRecordSetDashboardRoute.bind(this));
|
|
147
156
|
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash/:Offset', this.handleRecordSetDashboardRoute.bind(this));
|
|
148
157
|
pPictRouter.router.on('/PSRS/:RecordSet/SpecificDashboard/:DashboardHash', this.handleRecordSetDashboardRoute.bind(this));
|
|
@@ -201,12 +210,13 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
201
210
|
* @param {Record<string, any>} pRecordSetConfiguration
|
|
202
211
|
* @param {string} pProviderHash
|
|
203
212
|
* @param {string} pFilterString
|
|
213
|
+
* @param {string} pSerializedFilterExperience
|
|
204
214
|
* @param {number} pOffset
|
|
205
215
|
* @param {number} pPageSize
|
|
206
216
|
*
|
|
207
217
|
* @return {Promise<void>}
|
|
208
218
|
*/
|
|
209
|
-
async renderSpecificDashboard(pDashboardHash, pRecordSetConfiguration, pProviderHash, pFilterString, pOffset, pPageSize)
|
|
219
|
+
async renderSpecificDashboard(pDashboardHash, pRecordSetConfiguration, pProviderHash, pFilterString, pSerializedFilterExperience, pOffset, pPageSize)
|
|
210
220
|
{
|
|
211
221
|
if (!pRecordSetConfiguration)
|
|
212
222
|
{
|
|
@@ -231,6 +241,17 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
231
241
|
tmpTitle = this.pict.parseTemplate(tmpManifestDefinition.TitleTemplate, pRecordSetConfiguration);
|
|
232
242
|
}
|
|
233
243
|
|
|
244
|
+
const tmpEncodedFilterExperience = pSerializedFilterExperience && encodeURIComponent(pSerializedFilterExperience);
|
|
245
|
+
if (tmpEncodedFilterExperience)
|
|
246
|
+
{
|
|
247
|
+
// shove filter xp into the active filters for this recordset
|
|
248
|
+
const tmpExperienceFromURL = await this.pict.views['PRSP-Filters'].deserializeFilterExperience(pSerializedFilterExperience);
|
|
249
|
+
if (tmpExperienceFromURL)
|
|
250
|
+
{
|
|
251
|
+
this.pict.manifest.setValueByHash(this.pict.Bundle, `_ActiveFilterState[${pRecordSetConfiguration.RecordSet}].FilterClauses`, tmpExperienceFromURL);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
234
255
|
let tmpRecordDashboardData =
|
|
235
256
|
{
|
|
236
257
|
"Title": tmpTitle,
|
|
@@ -262,7 +283,7 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
262
283
|
tmpRecordDashboardData.GUIDAddress = `GUID${this.pict.providers[pProviderHash].options.Entity}`;
|
|
263
284
|
|
|
264
285
|
// Get the "page end record number" for the current page (e.g. for messaging like Record 700 to 800 of 75,000)
|
|
265
|
-
const tmpOffset =
|
|
286
|
+
const tmpOffset = Number(tmpRecordDashboardData.Offset);
|
|
266
287
|
tmpRecordDashboardData.PageEnd = tmpOffset + tmpRecordDashboardData.Records.Records.length;
|
|
267
288
|
|
|
268
289
|
// Compute the number of pages total
|
|
@@ -296,6 +317,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
296
317
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/SpecificDashboard/${pDashboardHash}/${i * tmpRecordDashboardData.PageSize}/${tmpRecordDashboardData.PageSize}`
|
|
297
318
|
});
|
|
298
319
|
}
|
|
320
|
+
if (tmpEncodedFilterExperience)
|
|
321
|
+
{
|
|
322
|
+
tmpRecordDashboardData.PageLinks[tmpRecordDashboardData.PageLinks.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
323
|
+
}
|
|
299
324
|
}
|
|
300
325
|
|
|
301
326
|
//FIXME: short-term workaround to not blow up the tempplate rendering with way too many links
|
|
@@ -322,6 +347,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
322
347
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/SpecificDashboard/${pDashboardHash}/0/${tmpRecordDashboardData.PageSize}`
|
|
323
348
|
});
|
|
324
349
|
}
|
|
350
|
+
if (tmpEncodedFilterExperience)
|
|
351
|
+
{
|
|
352
|
+
tmpRecordDashboardData.PageLinksLimited[tmpRecordDashboardData.PageLinksLimited.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
353
|
+
}
|
|
325
354
|
}
|
|
326
355
|
if (linkRangeEnd < tmpRecordDashboardData.PageLinks.length)
|
|
327
356
|
{
|
|
@@ -343,6 +372,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
343
372
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/SpecificDashboard/${pDashboardHash}/${(tmpRecordDashboardData.PageCount - 1) * tmpRecordDashboardData.PageSize}/${tmpRecordDashboardData.PageSize}`
|
|
344
373
|
});
|
|
345
374
|
}
|
|
375
|
+
if (tmpEncodedFilterExperience)
|
|
376
|
+
{
|
|
377
|
+
tmpRecordDashboardData.PageLinksLimited[tmpRecordDashboardData.PageLinksLimited.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
378
|
+
}
|
|
346
379
|
}
|
|
347
380
|
|
|
348
381
|
tmpRecordDashboardData.PageLinkBookmarks.Previous = tmpRecordDashboardData.PageLinkBookmarks.Current - 1;
|
|
@@ -458,12 +491,13 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
458
491
|
* @param {Record<string, any>} pRecordSetConfiguration
|
|
459
492
|
* @param {string} pProviderHash
|
|
460
493
|
* @param {string} pFilterString
|
|
494
|
+
* @param {string} pSerializedFilterExperience
|
|
461
495
|
* @param {number} pOffset
|
|
462
496
|
* @param {number} pPageSize
|
|
463
497
|
*
|
|
464
498
|
* @return {Promise<void>}
|
|
465
499
|
*/
|
|
466
|
-
async renderDashboard(pRecordSetConfiguration, pProviderHash, pFilterString, pOffset, pPageSize)
|
|
500
|
+
async renderDashboard(pRecordSetConfiguration, pProviderHash, pFilterString, pSerializedFilterExperience, pOffset, pPageSize)
|
|
467
501
|
{
|
|
468
502
|
if (!pRecordSetConfiguration)
|
|
469
503
|
{
|
|
@@ -486,7 +520,18 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
486
520
|
}
|
|
487
521
|
else
|
|
488
522
|
{
|
|
489
|
-
return this.renderSpecificDashboard(tmpManifestHash, pRecordSetConfiguration, pProviderHash, pFilterString, pOffset, pPageSize);
|
|
523
|
+
return this.renderSpecificDashboard(tmpManifestHash, pRecordSetConfiguration, pProviderHash, pFilterString, pSerializedFilterExperience, pOffset, pPageSize);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const tmpEncodedFilterExperience = pSerializedFilterExperience && encodeURIComponent(pSerializedFilterExperience);
|
|
528
|
+
if (tmpEncodedFilterExperience)
|
|
529
|
+
{
|
|
530
|
+
// shove filter xp into the active filters for this recordset
|
|
531
|
+
const tmpExperienceFromURL = await this.pict.views['PRSP-Filters'].deserializeFilterExperience(pSerializedFilterExperience);
|
|
532
|
+
if (tmpExperienceFromURL)
|
|
533
|
+
{
|
|
534
|
+
this.pict.manifest.setValueByHash(this.pict.Bundle, `_ActiveFilterState[${pRecordSetConfiguration.RecordSet}].FilterClauses`, tmpExperienceFromURL);
|
|
490
535
|
}
|
|
491
536
|
}
|
|
492
537
|
|
|
@@ -525,7 +570,7 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
525
570
|
tmpRecordDashboardData.GUIDAddress = `GUID${this.pict.providers[pProviderHash].options.Entity}`;
|
|
526
571
|
|
|
527
572
|
// Get the "page end record number" for the current page (e.g. for messaging like Record 700 to 800 of 75,000)
|
|
528
|
-
const tmpOffset =
|
|
573
|
+
const tmpOffset = Number(tmpRecordDashboardData.Offset);
|
|
529
574
|
tmpRecordDashboardData.PageEnd = tmpOffset + tmpRecordDashboardData.Records.Records.length;
|
|
530
575
|
|
|
531
576
|
// Compute the number of pages total
|
|
@@ -559,6 +604,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
559
604
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/Dashboard/${i * tmpRecordDashboardData.PageSize}/${tmpRecordDashboardData.PageSize}`
|
|
560
605
|
});
|
|
561
606
|
}
|
|
607
|
+
if (tmpEncodedFilterExperience)
|
|
608
|
+
{
|
|
609
|
+
tmpRecordDashboardData.PageLinks[tmpRecordDashboardData.PageLinks.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
610
|
+
}
|
|
562
611
|
}
|
|
563
612
|
|
|
564
613
|
//FIXME: short-term workaround to not blow up the tempplate rendering with way too many links
|
|
@@ -585,6 +634,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
585
634
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/Dashboard/${0}/${tmpRecordDashboardData.PageSize}`
|
|
586
635
|
});
|
|
587
636
|
}
|
|
637
|
+
if (tmpEncodedFilterExperience)
|
|
638
|
+
{
|
|
639
|
+
tmpRecordDashboardData.PageLinksLimited[tmpRecordDashboardData.PageLinksLimited.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
640
|
+
}
|
|
588
641
|
}
|
|
589
642
|
if (linkRangeEnd < tmpRecordDashboardData.PageLinks.length)
|
|
590
643
|
{
|
|
@@ -606,6 +659,10 @@ class viewRecordSetDashboard extends libPictRecordSetRecordView
|
|
|
606
659
|
URL: `#/PSRS/${tmpRecordDashboardData.RecordSet}/Dashboard/${(tmpRecordDashboardData.PageCount - 1) * tmpRecordDashboardData.PageSize}/${tmpRecordDashboardData.PageSize}`
|
|
607
660
|
});
|
|
608
661
|
}
|
|
662
|
+
if (tmpEncodedFilterExperience)
|
|
663
|
+
{
|
|
664
|
+
tmpRecordDashboardData.PageLinksLimited[tmpRecordDashboardData.PageLinksLimited.length - 1].URL += `/FilterExperience/${tmpEncodedFilterExperience}`;
|
|
665
|
+
}
|
|
609
666
|
}
|
|
610
667
|
|
|
611
668
|
tmpRecordDashboardData.PageLinkBookmarks.Previous = tmpRecordDashboardData.PageLinkBookmarks.Current - 1;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
const ViewRecordSetSUBSETFilterBase = require('./RecordSet-Filter-Base');
|
|
3
|
+
|
|
4
|
+
class ViewRecordSetSUBSETFilterBaseRange extends ViewRecordSetSUBSETFilterBase
|
|
5
|
+
{
|
|
6
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
7
|
+
{
|
|
8
|
+
super(pFable, pOptions, pServiceHash);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Record<string, any>} pRecord
|
|
13
|
+
*/
|
|
14
|
+
prepareRecord(pRecord)
|
|
15
|
+
{
|
|
16
|
+
super.prepareRecord(pRecord);
|
|
17
|
+
|
|
18
|
+
pRecord.StartClauseAddress = pRecord.ClauseValuesAddress + '.Start';
|
|
19
|
+
pRecord.EndClauseAddress = pRecord.ClauseValuesAddress + '.End';
|
|
20
|
+
|
|
21
|
+
pRecord.StartClauseDescriptor =
|
|
22
|
+
{
|
|
23
|
+
Address: pRecord.StartClauseAddress,
|
|
24
|
+
//TODO: figure out a nice pattern for extracting a name for the field from the filter - and allow the filter author to provide the label here
|
|
25
|
+
Name: pRecord.MinimumLabel || `Minimum ${pRecord.ExternalFilterByColumn || pRecord.ExternalFilterByColumns?.[0] || pRecord.FilterByColumn || pRecord.FilterByColumns?.[0] || 'Value'}`,
|
|
26
|
+
DataType: 'String',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
pRecord.EndClauseDescriptor =
|
|
30
|
+
{
|
|
31
|
+
Address: pRecord.EndClauseAddress,
|
|
32
|
+
Name: pRecord.MaximumLabel || `Maximum ${pRecord.ExternalFilterByColumn || pRecord.ExternalFilterByColumns?.[0] || pRecord.FilterByColumn || pRecord.FilterByColumns?.[0] || 'Value'}`,
|
|
33
|
+
DataType: 'String',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = ViewRecordSetSUBSETFilterBaseRange;
|