pict-section-recordset 1.0.43 → 1.0.45

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.
Files changed (39) hide show
  1. package/example_applications/simple_entity/Simple-RecordSet-Application.js +199 -3
  2. package/example_applications/simple_entity/html/index.html +6 -0
  3. package/package.json +2 -2
  4. package/source/providers/Filter-Data-Provider.js +371 -0
  5. package/source/providers/RecordSet-Link-Manager.js +9 -1
  6. package/source/providers/RecordSet-RecordProvider-Base.js +1 -1
  7. package/source/providers/RecordSet-RecordProvider-MeadowEndpoints.js +76 -43
  8. package/source/services/RecordsSet-MetaController.js +48 -1
  9. package/source/templates/Pict-Template-FilterInstanceViews.js +11 -7
  10. package/source/views/RecordSet-Filters.js +78 -45
  11. package/source/views/filters/RecordSet-Filter-Base.js +19 -1
  12. package/source/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.js +270 -0
  13. package/source/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.js +277 -0
  14. package/source/views/filters/RecordSet-Filter-InternalJoinSelectedValue.js +270 -0
  15. package/source/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.js +277 -0
  16. package/source/views/filters/index.js +4 -0
  17. package/types/providers/Filter-Data-Provider.d.ts +120 -0
  18. package/types/providers/Filter-Data-Provider.d.ts.map +1 -0
  19. package/types/providers/RecordSet-Link-Manager.d.ts +10 -5
  20. package/types/providers/RecordSet-Link-Manager.d.ts.map +1 -1
  21. package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts +1 -1
  22. package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts.map +1 -1
  23. package/types/services/RecordsSet-MetaController.d.ts +36 -7
  24. package/types/services/RecordsSet-MetaController.d.ts.map +1 -1
  25. package/types/templates/Pict-Template-FilterInstanceViews.d.ts +1 -1
  26. package/types/templates/Pict-Template-FilterInstanceViews.d.ts.map +1 -1
  27. package/types/views/RecordSet-Filters.d.ts +10 -0
  28. package/types/views/RecordSet-Filters.d.ts.map +1 -1
  29. package/types/views/filters/RecordSet-Filter-Base.d.ts +10 -0
  30. package/types/views/filters/RecordSet-Filter-Base.d.ts.map +1 -1
  31. package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.d.ts +24 -0
  32. package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.d.ts.map +1 -0
  33. package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.d.ts +24 -0
  34. package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.d.ts.map +1 -0
  35. package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValue.d.ts +24 -0
  36. package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValue.d.ts.map +1 -0
  37. package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.d.ts +24 -0
  38. package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.d.ts.map +1 -0
  39. package/types/views/filters/index.d.ts +4 -0
@@ -0,0 +1,270 @@
1
+
2
+ const ViewRecordSetSUBSETFilterBase = require('./RecordSet-Filter-Base');
3
+
4
+ const _DEFAULT_CONFIGURATION_Filter_InternalJoin_SelectedValue =
5
+ {
6
+ ViewIdentifier: 'PRSP-FilterType-InternalJoinSelectedValue',
7
+
8
+ Templates:
9
+ [
10
+ {
11
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValue-Template',
12
+ Template: /*html*/`
13
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValue-Template] -->
14
+ <table>
15
+ <tbody>
16
+ <td valign="top">{~T:PRSP-Filter-InternalJoin-SelectedValue-SearchResults~}</td><td valign="top">{~T:PRSP-Filter-InternalJoin-SelectedValue-SelectedValues~}</td>
17
+ </tbody>
18
+ </table>
19
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValue-Template] -->
20
+ `
21
+ },
22
+ {
23
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValue-SearchResults',
24
+ Template: /*html*/`
25
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValue-SearchResults] -->
26
+ <form id="PRSP_Filter_{~D:Record.Hash~}_Search_Form" onsubmit="_Pict.views['{~D:Context[0].Hash~}'].performSearch(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}'); return false;">
27
+ <input id="PRSP_Filter_{~D:Record.Hash~}_Search_Value" type="text" placeholder="Search..." value="{~D:Record.SearchInputValue~}" />
28
+ <button type="submit" id="PRSP_Filter_{~D:Record.Hash~}_Button_Search" onclick="_Pict.views['{~D:Context[0].Hash~}'].performSearch(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}')">Search</button>
29
+ </form>
30
+ <table>
31
+ <thead>
32
+ <tr><th colspan="2">{~D:Record.Label~}</th></tr>
33
+ </thead>
34
+ <tbody>
35
+ {~TSWP:PRSP-Filter-InternalJoin-SelectedValue-SearchResults-Entry:Record.SearchResults:Record~}
36
+ </tbody>
37
+ </table>
38
+ <button type="button" id="PRSP_Filter_{~D:Record.Hash~}_Button_LoadMore" class="is-hidden" onclick="_Pict.views['{~D:Context[0].Hash~}'].loadMore(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}', {~D:Record.SearchResultsOffset:0~})">Load More</button>
39
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValue-SearchResults] -->
40
+ `
41
+ },
42
+ {
43
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValue-SelectedValues',
44
+ Template: /*html*/`
45
+ <!-- DefaultPackage view template: [PRSP-Filter-InternalJoin-SelectedValue-SelectedValues] -->
46
+ <table>
47
+ <thead>
48
+ <tr><th colspan="2">Selection</th></tr>
49
+ </thead>
50
+ <tbody>
51
+ {~TSWP:PRSP-Filter-InternalJoin-SelectedValue-SelectedValues-Entry:Record.SelectedValues:Record~}
52
+ </tbody>
53
+ </table>
54
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValue-SelectedValues] -->
55
+ `
56
+ },
57
+ {
58
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValue-SearchResults-Entry',
59
+ Template: /*html*/`
60
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValue-Template] -->
61
+ <tr><td><button onclick="_Pict.views['{~D:Context[0].Hash~}'].handleSelect(event, {~DVBK:Record.Data:Record.Payload.ExternalFilterTableLookupColumn~}, '{~D:Record.Payload.ClauseAddress~}', '{~D:Record.Payload.Hash~}')">Select</button></td><td>{~TFA:Record.Payload.ExternalRecordDisplayTemplate:Record~}</td></tr>
62
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValue-Template] -->
63
+ `
64
+ },
65
+ {
66
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValue-SelectedValues-Entry',
67
+ Template: /*html*/`
68
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValue-SelectedValues-Entry] -->
69
+ <tr><td><button onclick="_Pict.views['{~D:Context[0].Hash~}'].handleRemove(event, {~DVBK:Record.Data:Record.Payload.ExternalFilterTableLookupColumn~}, '{~D:Record.Payload.ClauseAddress~}', '{~D:Record.Payload.Hash~}')">Remove</button></td><td>{~TFA:Record.Payload.ExternalRecordDisplayTemplate:Record~}</td></tr>
70
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValue-SelectedValues-Entry] -->
71
+ `
72
+ }
73
+ ],
74
+ };
75
+
76
+ class ViewRecordSetSUBSETFilterInternalJoinSelectedValue extends ViewRecordSetSUBSETFilterBase
77
+ {
78
+ constructor(pFable, pOptions, pServiceHash)
79
+ {
80
+ if (!pOptions.PageSize)
81
+ {
82
+ pOptions.PageSize = 15; // default page size for search results
83
+ }
84
+ super(pFable, pOptions, pServiceHash);
85
+ /*
86
+ * show / hide the complex editor since it'll be large ?
87
+ * selected record lookup values
88
+ * using bundle to load those records (if any)
89
+ * templating out the selection
90
+ * templating out the search results
91
+ * controls to add search result values to selection
92
+ */
93
+ }
94
+
95
+ /**
96
+ * @param {Record<string, any>} pRecord
97
+ */
98
+ prepareRecord(pRecord)
99
+ {
100
+ super.prepareRecord(pRecord);
101
+
102
+ pRecord.ClauseDescriptor.DataType = 'Number';
103
+ if (!pRecord.ExternalFilterTableLookupColumn)
104
+ {
105
+ pRecord.ExternalFilterTableLookupColumn = `ID${pRecord.RemoteTable}`;
106
+ }
107
+ if (!pRecord.SearchResults)
108
+ {
109
+ pRecord.SearchResults = [];
110
+ }
111
+ if (!pRecord.SelectedValues)
112
+ {
113
+ pRecord.SelectedValues = [];
114
+ }
115
+ }
116
+
117
+ getFilterFormTemplate()
118
+ {
119
+ return 'PRSP-Filter-InternalJoin-SelectedValue-Template';
120
+ }
121
+
122
+ /**
123
+ * @param {UIEvent} pEvent
124
+ * @param {string} pClauseInformaryAddress
125
+ * @param {string} pClauseHash
126
+ */
127
+ loadMore(pEvent, pClauseInformaryAddress, pClauseHash, pCurrentOffset = 0)
128
+ {
129
+ this.performSearch(pEvent, pClauseInformaryAddress, pClauseHash, pCurrentOffset + this.options.PageSize);
130
+ }
131
+
132
+ /**
133
+ * @param {UIEvent} pEvent
134
+ * @param {string} pClauseInformaryAddress
135
+ * @param {string} pClauseHash
136
+ * @param {number} [pOffset=0] - The offset for the search results, defaults to 0
137
+ */
138
+ performSearch(pEvent, pClauseInformaryAddress, pClauseHash, pOffset = 0)
139
+ {
140
+ pEvent.preventDefault();
141
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
142
+ if (!tmpClause)
143
+ {
144
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No clause found for address: ${pClauseInformaryAddress}`);
145
+ return;
146
+ }
147
+ tmpClause.SearchResultsOffset = pOffset;
148
+ // get the input value (search box)
149
+ const tmpSearchInputValue = pOffset > 0 ? tmpClause.SearchInputValue : this.pict.ContentAssignment.readContent(`#PRSP_Filter_${tmpClause.Hash}_Search_Value`);
150
+ tmpClause.SearchInputValue = tmpSearchInputValue;
151
+ if (!tmpSearchInputValue)
152
+ {
153
+ tmpClause.SearchResults = [];
154
+ tmpClause.LoadMoreEnabled = false;
155
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
156
+ this.prepareRecord(tmpRecord);
157
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
158
+ this.render(null, tmpDestinationAddress, tmpRecord);
159
+ return;
160
+ }
161
+ const tmpFilterByColumns = tmpClause.ExternalFilterByColumns || (tmpClause.ExternalFilterByColumn ? [ tmpClause.ExternalFilterByColumn ] : [ 'Name' ]);
162
+ const tmpMeadowFilter = tmpFilterByColumns.map((pColumn) => `FBVOR~${pColumn}~LK~${encodeURIComponent(`%${tmpSearchInputValue}%`)}`).join('~');
163
+ // bundle load the remote records and put them in the clause
164
+ this.pict.EntityProvider.gatherDataFromServer(
165
+ [
166
+ {
167
+ Entity: tmpClause.RemoteTable,
168
+ Filter: tmpMeadowFilter,
169
+ Destination: pOffset > 0 ? `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResultsAppend` : `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResults`,
170
+ RecordStartCursor: pOffset,
171
+ PageSize: this.options.PageSize,
172
+ }
173
+ ],
174
+ (pError, pResult) =>
175
+ {
176
+ if (pOffset > 0 && tmpClause.SearchResultsAppend?.length > 0)
177
+ {
178
+ tmpClause.SearchResults = tmpClause.SearchResults.concat(tmpClause.SearchResultsAppend);
179
+ }
180
+ delete tmpClause.SearchResultsAppend;
181
+ tmpClause.SearchResultsOffset = pOffset;
182
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
183
+ this.prepareRecord(tmpRecord);
184
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
185
+ this.render(null, tmpDestinationAddress, tmpRecord);
186
+ const tmpLoadedRecords = pOffset > 0 ? tmpClause.SearchResultsAppend : tmpClause.SearchResults;
187
+ const tmpLoadMoreEnabled = tmpLoadedRecords && tmpLoadedRecords.length >= this.options.PageSize;
188
+ tmpClause.LoadMoreEnabled = tmpLoadMoreEnabled;
189
+ if (tmpClause.LoadMoreEnabled)
190
+ {
191
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
192
+ }
193
+ });
194
+ }
195
+
196
+ handleSelect(pEvent, pRecordLookupValue, pClauseInformaryAddress, pClauseHash)
197
+ {
198
+ pEvent.preventDefault();
199
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
200
+ if (!tmpClause)
201
+ {
202
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No clause found for address: ${pClauseInformaryAddress}`);
203
+ return;
204
+ }
205
+ const tmpRecordLookupColumn = tmpClause.ExternalFilterTableLookupColumn || `ID${tmpClause.RemoteTable}`;
206
+ const tmpRecordToSelect = tmpClause.SearchResults.find((r) => r[tmpRecordLookupColumn] == pRecordLookupValue);
207
+ if (!tmpRecordToSelect)
208
+ {
209
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No record found to add for value: ${pRecordLookupValue}`);
210
+ return;
211
+ }
212
+ if (!tmpClause.SelectedValues)
213
+ {
214
+ tmpClause.SelectedValues = [];
215
+ }
216
+ if (tmpClause.SelectedValues.some((pSV) => pSV[tmpRecordLookupColumn] == pRecordLookupValue))
217
+ {
218
+ return;
219
+ }
220
+ const tmpValue = tmpRecordToSelect[tmpRecordLookupColumn];
221
+ if (tmpValue == null)
222
+ {
223
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No value found in record to add: ${JSON.stringify(tmpRecordToSelect)}`);
224
+ return;
225
+ }
226
+ tmpClause.SelectedValues = [ tmpRecordToSelect ];
227
+ tmpClause.Values = [ tmpValue ];
228
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
229
+ this.prepareRecord(tmpRecord);
230
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
231
+ this.render(null, tmpDestinationAddress, tmpRecord);
232
+ if (tmpClause.LoadMoreEnabled)
233
+ {
234
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
235
+ }
236
+ }
237
+
238
+ handleRemove(pEvent, pRecordLookupValue, pClauseInformaryAddress, pClauseHash)
239
+ {
240
+ pEvent.preventDefault();
241
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
242
+ if (!tmpClause)
243
+ {
244
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No clause found for address: ${pClauseInformaryAddress}`);
245
+ return;
246
+ }
247
+ const tmpRecordLookupColumn = tmpClause.ExternalFilterTableLookupColumn || `ID${tmpClause.RemoteTable}`;
248
+ const tmpRecordIndexToRemove = tmpClause.SelectedValues.findIndex((r) => r[tmpRecordLookupColumn] == pRecordLookupValue);
249
+ if (tmpRecordIndexToRemove < 0)
250
+ {
251
+ this.pict.log.error(`[Filter-InternalJoinSelectedValue] No record found to remove for value: ${pRecordLookupValue}`);
252
+ return;
253
+ }
254
+ const tmpRecordToRemove = tmpClause.SelectedValues.splice(tmpRecordIndexToRemove, 1)[0];
255
+ const tmpValue = tmpRecordToRemove[tmpRecordLookupColumn];
256
+ tmpClause.Values = tmpClause.Values.filter((pV) => pV !== tmpValue);
257
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
258
+ this.prepareRecord(tmpRecord);
259
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
260
+ this.render(null, tmpDestinationAddress, tmpRecord);
261
+ if (tmpClause.LoadMoreEnabled)
262
+ {
263
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
264
+ }
265
+ }
266
+ }
267
+
268
+ module.exports = ViewRecordSetSUBSETFilterInternalJoinSelectedValue;
269
+
270
+ module.exports.default_configuration = Object.assign({}, ViewRecordSetSUBSETFilterInternalJoinSelectedValue.default_configuration, _DEFAULT_CONFIGURATION_Filter_InternalJoin_SelectedValue);
@@ -0,0 +1,277 @@
1
+
2
+ const ViewRecordSetSUBSETFilterBase = require('./RecordSet-Filter-Base');
3
+
4
+ const _DEFAULT_CONFIGURATION_Filter_InternalJoin_SelectedValueList =
5
+ {
6
+ ViewIdentifier: 'PRSP-FilterType-InternalJoinSelectedValueList',
7
+
8
+ Templates:
9
+ [
10
+ {
11
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValueList-Template',
12
+ Template: /*html*/`
13
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValueList-Template] -->
14
+ <table>
15
+ <tbody>
16
+ <td valign="top">{~T:PRSP-Filter-InternalJoin-SelectedValueList-SearchResults~}</td><td valign="top">{~T:PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues~}</td>
17
+ </tbody>
18
+ </table>
19
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValueList-Template] -->
20
+ `
21
+ },
22
+ {
23
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValueList-SearchResults',
24
+ Template: /*html*/`
25
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SearchResults] -->
26
+ <form id="PRSP_Filter_{~D:Record.Hash~}_Search_Form" onsubmit="_Pict.views['{~D:Context[0].Hash~}'].performSearch(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}'); return false;">
27
+ <input id="PRSP_Filter_{~D:Record.Hash~}_Search_Value" type="text" placeholder="Search..." value="{~D:Record.SearchInputValue~}" />
28
+ <button type="submit" id="PRSP_Filter_{~D:Record.Hash~}_Button_Search" onclick="_Pict.views['{~D:Context[0].Hash~}'].performSearch(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}')">Search</button>
29
+ </form>
30
+ <table>
31
+ <thead>
32
+ <tr><th colspan="2">{~D:Record.Label~}</th></tr>
33
+ </thead>
34
+ <tbody>
35
+ {~TSWP:PRSP-Filter-InternalJoin-SelectedValueList-SearchResults-Entry:Record.SearchResults:Record~}
36
+ </tbody>
37
+ </table>
38
+ <button type="button" id="PRSP_Filter_{~D:Record.Hash~}_Button_LoadMore" class="is-hidden" onclick="_Pict.views['{~D:Context[0].Hash~}'].loadMore(event, '{~D:Record.ClauseAddress~}', '{~D:Record.Hash~}', {~D:Record.SearchResultsOffset:0~})">Load More</button>
39
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SearchResults] -->
40
+ `
41
+ },
42
+ {
43
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues',
44
+ Template: /*html*/`
45
+ <!-- DefaultPackage view template: [PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues] -->
46
+ <table>
47
+ <thead>
48
+ <tr><th colspan="2">Selection</th></tr>
49
+ </thead>
50
+ <tbody>
51
+ {~TSWP:PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues-Entry:Record.SelectedValues:Record~}
52
+ </tbody>
53
+ </table>
54
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues] -->
55
+ `
56
+ },
57
+ {
58
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValueList-SearchResults-Entry',
59
+ Template: /*html*/`
60
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValueList-Template] -->
61
+ <tr><td><button onclick="_Pict.views['{~D:Context[0].Hash~}'].handleAdd(event, {~DVBK:Record.Data:Record.Payload.ExternalFilterTableLookupColumn~}, '{~D:Record.Payload.ClauseAddress~}', '{~D:Record.Payload.Hash~}')">Add</button></td><td>{~TFA:Record.Payload.ExternalRecordDisplayTemplate:Record~}</td></tr>
62
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValueList-Template] -->
63
+ `
64
+ },
65
+ {
66
+ Hash: 'PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues-Entry',
67
+ Template: /*html*/`
68
+ <!-- DefaultPackage pict view template: [PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues-Entry] -->
69
+ <tr><td><button onclick="_Pict.views['{~D:Context[0].Hash~}'].handleRemove(event, {~DVBK:Record.Data:Record.Payload.ExternalFilterTableLookupColumn~}, '{~D:Record.Payload.ClauseAddress~}', '{~D:Record.Payload.Hash~}')">Remove</button></td><td>{~TFA:Record.Payload.ExternalRecordDisplayTemplate:Record~}</td></tr>
70
+ <!-- DefaultPackage end view template: [PRSP-Filter-InternalJoin-SelectedValueList-SelectedValues-Entry] -->
71
+ `
72
+ }
73
+ ],
74
+ };
75
+
76
+ class ViewRecordSetSUBSETFilterInternalJoinSelectedValueList extends ViewRecordSetSUBSETFilterBase
77
+ {
78
+ constructor(pFable, pOptions, pServiceHash)
79
+ {
80
+ if (!pOptions.PageSize)
81
+ {
82
+ pOptions.PageSize = 15; // default page size for search results
83
+ }
84
+ super(pFable, pOptions, pServiceHash);
85
+ /*
86
+ * show / hide the complex editor since it'll be large ?
87
+ * selected record lookup values
88
+ * using bundle to load those records (if any)
89
+ * templating out the selection
90
+ * templating out the search results
91
+ * controls to add search result values to selection
92
+ */
93
+ }
94
+
95
+ /**
96
+ * @param {Record<string, any>} pRecord
97
+ */
98
+ prepareRecord(pRecord)
99
+ {
100
+ super.prepareRecord(pRecord);
101
+
102
+ pRecord.ClauseDescriptor.DataType = 'Number';
103
+ if (!pRecord.ExternalFilterTableLookupColumn)
104
+ {
105
+ pRecord.ExternalFilterTableLookupColumn = `ID${pRecord.RemoteTable}`;
106
+ }
107
+ if (!pRecord.SearchResults)
108
+ {
109
+ pRecord.SearchResults = [];
110
+ }
111
+ if (!pRecord.SelectedValues)
112
+ {
113
+ pRecord.SelectedValues = [];
114
+ }
115
+ }
116
+
117
+ getFilterFormTemplate()
118
+ {
119
+ return 'PRSP-Filter-InternalJoin-SelectedValueList-Template';
120
+ }
121
+
122
+ /**
123
+ * @param {UIEvent} pEvent
124
+ * @param {string} pClauseInformaryAddress
125
+ * @param {string} pClauseHash
126
+ */
127
+ loadMore(pEvent, pClauseInformaryAddress, pClauseHash, pCurrentOffset = 0)
128
+ {
129
+ this.performSearch(pEvent, pClauseInformaryAddress, pClauseHash, pCurrentOffset + this.options.PageSize);
130
+ }
131
+
132
+ /**
133
+ * @param {UIEvent} pEvent
134
+ * @param {string} pClauseInformaryAddress
135
+ * @param {string} pClauseHash
136
+ * @param {number} [pOffset=0] - The offset for the search results, defaults to 0
137
+ */
138
+ performSearch(pEvent, pClauseInformaryAddress, pClauseHash, pOffset = 0)
139
+ {
140
+ pEvent.preventDefault();
141
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
142
+ if (!tmpClause)
143
+ {
144
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No clause found for address: ${pClauseInformaryAddress}`);
145
+ return;
146
+ }
147
+ tmpClause.SearchResultsOffset = pOffset;
148
+ // get the input value (search box)
149
+ const tmpSearchInputValue = pOffset > 0 ? tmpClause.SearchInputValue : this.pict.ContentAssignment.readContent(`#PRSP_Filter_${tmpClause.Hash}_Search_Value`);
150
+ tmpClause.SearchInputValue = tmpSearchInputValue;
151
+ if (!tmpSearchInputValue)
152
+ {
153
+ tmpClause.SearchResults = [];
154
+ tmpClause.LoadMoreEnabled = false;
155
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
156
+ this.prepareRecord(tmpRecord);
157
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
158
+ this.render(null, tmpDestinationAddress, tmpRecord);
159
+ return;
160
+ }
161
+ const tmpFilterByColumns = tmpClause.ExternalFilterByColumns || (tmpClause.ExternalFilterByColumn ? [ tmpClause.ExternalFilterByColumn ] : [ 'Name' ]);
162
+ const tmpMeadowFilter = tmpFilterByColumns.map((pColumn) => `FBVOR~${pColumn}~LK~${encodeURIComponent(`%${tmpSearchInputValue}%`)}`).join('~');
163
+ // bundle load the remote records and put them in the clause
164
+ this.pict.EntityProvider.gatherDataFromServer(
165
+ [
166
+ {
167
+ Entity: tmpClause.RemoteTable,
168
+ Filter: tmpMeadowFilter,
169
+ Destination: pOffset > 0 ? `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResultsAppend` : `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResults`,
170
+ RecordStartCursor: pOffset,
171
+ PageSize: this.options.PageSize,
172
+ }
173
+ ],
174
+ (pError, pResult) =>
175
+ {
176
+ if (pOffset > 0 && tmpClause.SearchResultsAppend?.length > 0)
177
+ {
178
+ tmpClause.SearchResults = tmpClause.SearchResults.concat(tmpClause.SearchResultsAppend);
179
+ }
180
+ delete tmpClause.SearchResultsAppend;
181
+ tmpClause.SearchResultsOffset = pOffset;
182
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
183
+ this.prepareRecord(tmpRecord);
184
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
185
+ this.render(null, tmpDestinationAddress, tmpRecord);
186
+ const tmpLoadedRecords = pOffset > 0 ? tmpClause.SearchResultsAppend : tmpClause.SearchResults;
187
+ const tmpLoadMoreEnabled = tmpLoadedRecords && tmpLoadedRecords.length >= this.options.PageSize;
188
+ tmpClause.LoadMoreEnabled = tmpLoadMoreEnabled;
189
+ if (tmpClause.LoadMoreEnabled)
190
+ {
191
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
192
+ }
193
+ });
194
+ }
195
+
196
+ handleAdd(pEvent, pRecordLookupValue, pClauseInformaryAddress, pClauseHash)
197
+ {
198
+ pEvent.preventDefault();
199
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
200
+ if (!tmpClause)
201
+ {
202
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No clause found for address: ${pClauseInformaryAddress}`);
203
+ return;
204
+ }
205
+ const tmpRecordLookupColumn = tmpClause.ExternalFilterTableLookupColumn || `ID${tmpClause.RemoteTable}`;
206
+ const tmpRecordToAdd = tmpClause.SearchResults.find((r) => r[tmpRecordLookupColumn] == pRecordLookupValue);
207
+ if (!tmpRecordToAdd)
208
+ {
209
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No record found to add for value: ${pRecordLookupValue}`);
210
+ return;
211
+ }
212
+ if (!tmpClause.SelectedValues)
213
+ {
214
+ tmpClause.SelectedValues = [];
215
+ }
216
+ if (tmpClause.SelectedValues.some((pSV) => pSV[tmpRecordLookupColumn] == pRecordLookupValue))
217
+ {
218
+ return;
219
+ }
220
+ const tmpValue = tmpRecordToAdd[tmpRecordLookupColumn];
221
+ if (tmpValue == null)
222
+ {
223
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No value found in record to add: ${JSON.stringify(tmpRecordToAdd)}`);
224
+ return;
225
+ }
226
+ tmpClause.SelectedValues.push(tmpRecordToAdd);
227
+ if (!tmpClause.Values)
228
+ {
229
+ tmpClause.Values = [];
230
+ }
231
+ if (!tmpClause.Values.some((pV) => pV == tmpValue))
232
+ {
233
+ tmpClause.Values.push(tmpValue);
234
+ }
235
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
236
+ this.prepareRecord(tmpRecord);
237
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
238
+ this.render(null, tmpDestinationAddress, tmpRecord);
239
+ if (tmpClause.LoadMoreEnabled)
240
+ {
241
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
242
+ }
243
+ }
244
+
245
+ handleRemove(pEvent, pRecordLookupValue, pClauseInformaryAddress, pClauseHash)
246
+ {
247
+ pEvent.preventDefault();
248
+ const tmpClause = this.getInformaryScopedValue(pClauseInformaryAddress);
249
+ if (!tmpClause)
250
+ {
251
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No clause found for address: ${pClauseInformaryAddress}`);
252
+ return;
253
+ }
254
+ const tmpRecordLookupColumn = tmpClause.ExternalFilterTableLookupColumn || `ID${tmpClause.RemoteTable}`;
255
+ const tmpRecordIndexToRemove = tmpClause.SelectedValues.findIndex((r) => r[tmpRecordLookupColumn] == pRecordLookupValue);
256
+ if (tmpRecordIndexToRemove < 0)
257
+ {
258
+ this.pict.log.error(`[Filter-InternalJoinSelectedValueList] No record found to remove for value: ${pRecordLookupValue}`);
259
+ return;
260
+ }
261
+ const tmpRecordToRemove = tmpClause.SelectedValues.splice(tmpRecordIndexToRemove, 1)[0];
262
+ const tmpValue = tmpRecordToRemove[tmpRecordLookupColumn];
263
+ tmpClause.Values = tmpClause.Values.filter((pV) => pV !== tmpValue);
264
+ const tmpRecord = Object.assign({ ClauseAddress: pClauseInformaryAddress }, tmpClause);
265
+ this.prepareRecord(tmpRecord);
266
+ const tmpDestinationAddress = `#PRSP_Filter_Container_${pClauseHash}`;
267
+ this.render(null, tmpDestinationAddress, tmpRecord);
268
+ if (tmpClause.LoadMoreEnabled)
269
+ {
270
+ this.pict.ContentAssignment.removeClass(`#PRSP_Filter_${tmpClause.Hash}_Button_LoadMore`, 'is-hidden');
271
+ }
272
+ }
273
+ }
274
+
275
+ module.exports = ViewRecordSetSUBSETFilterInternalJoinSelectedValueList;
276
+
277
+ module.exports.default_configuration = Object.assign({}, ViewRecordSetSUBSETFilterInternalJoinSelectedValueList.default_configuration, _DEFAULT_CONFIGURATION_Filter_InternalJoin_SelectedValueList);
@@ -16,6 +16,8 @@ module.exports =
16
16
  InternalJoinNumericRange: require('./RecordSet-Filter-InternalJoinNumericRange.js'),
17
17
  InternalJoinStringMatch: require('./RecordSet-Filter-InternalJoinStringMatch.js'),
18
18
  InternalJoinStringRange: require('./RecordSet-Filter-InternalJoinStringRange.js'),
19
+ InternalJoinSelectedValue: require('./RecordSet-Filter-InternalJoinSelectedValue.js'),
20
+ InternalJoinSelectedValueList: require('./RecordSet-Filter-InternalJoinSelectedValueList.js'),
19
21
 
20
22
  ExternalJoinDateMatch: require('./RecordSet-Filter-ExternalJoinDateMatch.js'),
21
23
  ExternalJoinDateRange: require('./RecordSet-Filter-ExternalJoinDateRange.js'),
@@ -23,5 +25,7 @@ module.exports =
23
25
  ExternalJoinNumericRange: require('./RecordSet-Filter-ExternalJoinNumericRange.js'),
24
26
  ExternalJoinStringMatch: require('./RecordSet-Filter-ExternalJoinStringMatch.js'),
25
27
  ExternalJoinStringRange: require('./RecordSet-Filter-ExternalJoinStringRange.js'),
28
+ ExternalJoinSelectedValue: require('./RecordSet-Filter-ExternalJoinSelectedValue.js'),
29
+ ExternalJoinSelectedValueList: require('./RecordSet-Filter-ExternalJoinSelectedValueList.js'),
26
30
  };
27
31
 
@@ -0,0 +1,120 @@
1
+ export = FilterDataProvider;
2
+ declare class FilterDataProvider extends libPictProvider {
3
+ /**
4
+ * @param {import('pict')} pFable - The Fable instance
5
+ * @param {Record<string, any>} [pOptions] - The options for the provider
6
+ * @param {string} [pServiceHash] - The service hash for the provider
7
+ */
8
+ constructor(pFable: import("pict"), pOptions?: Record<string, any>, pServiceHash?: string);
9
+ storageProvider: any;
10
+ keyCache: {};
11
+ filtersMap: {};
12
+ lastFilterExperienceHashMap: {};
13
+ /**
14
+ * @return {void}
15
+ */
16
+ loadFilters(): void;
17
+ /**
18
+ * List all available Filters (from the Filter Meta data)
19
+ *
20
+ * @param {string} pRecordSet - the record set to list the filters for
21
+ *
22
+ * @return Array<Record<string, any>> - a list of Filters as Index/FilterExperienceHash entries
23
+ */
24
+ listFilters(pRecordSet: string): any;
25
+ /**
26
+ * @param {string} pRecordSet - the record set to get the active filter experience for
27
+ *
28
+ * @return {Record<string, any>} - the active filter experience for the given record set
29
+ */
30
+ getActiveFilterExperience(pRecordSet: string): Record<string, any>;
31
+ /**
32
+ * Check if a particular scope is in use.
33
+ *
34
+ * @param {string} pRecordSet - the record set
35
+ * @param {string} pFilterExperienceHash - the manyfest scope to check the existence of
36
+ *
37
+ * @return {boolean}
38
+ */
39
+ checkFilterExists(pRecordSet: string, pFilterExperienceHash: string): boolean;
40
+ /**
41
+ * Resolve a key in the LocalStorage keyspace for a filter experience for a given record set.
42
+ *
43
+ * @param {string} pRecordSet - The record set to resolve a key for
44
+ * @param {string} pFilterExperienceHash - The scope to resolve a key for
45
+ *
46
+ * @return {string} A string that points to the record.
47
+ */
48
+ getFilterStorageKey(pRecordSet: string, pFilterExperienceHash: string): string;
49
+ /**
50
+ * Save the application metadata (list of Filters, last loaded FilterExperienceHash, etc.)
51
+ *
52
+ * @param {string} pRecordSet - The record set to save the filter for; TODO: should this have a default?
53
+ * @param {boolean} [pRender=false] - Whether or not to also render the list of Filters in the UI automatically
54
+ */
55
+ saveFilterMeta(pRecordSet: string, pRender?: boolean): boolean;
56
+ /**
57
+ * Save the application metadata (list of Filters, last loaded FilterExperienceHash, etc.)
58
+ *
59
+ * @param {string} pRecordSet - The record set to save the filter for; TODO: should this have a default?
60
+ * @param {boolean} [pRender=false] - Whether or not to also render the list of Filters in the UI automatically
61
+ *
62
+ * @return {Array<object>} The list of available Filters.
63
+ */
64
+ loadFilterMeta(pRecordSet: string, pRender?: boolean): Array<object>;
65
+ /**
66
+ * @param {string} pRecordSet - The record set to add the filter experience hash to
67
+ * @param {string} pFilterExperienceHash - The filter experience hash to add
68
+ * @param {boolean} [pRender=true] - Whether or not to also render the list of Filters in the UI automatically
69
+ *
70
+ * @return {boolean} True if the filter experience hash was added, false if it already exists.
71
+ */
72
+ addFilterExperienceHashToFilterList(pRecordSet: string, pFilterExperienceHash: string, pRender?: boolean): boolean;
73
+ /**
74
+ * @param {string} pRecordSet - The record set to remove the filter experience hash from
75
+ * @param {string} pFilterExperienceHash - The filter experience hash to remove
76
+ * @param {boolean} [pRender=true] - Whether or not to also render the list of Filters in the UI automatically
77
+ */
78
+ removeFilterExperienceHashFromFilterList(pRecordSet: string, pFilterExperienceHash: string, pRender?: boolean): boolean;
79
+ /**
80
+ * @param {string} pRecordSet - The record set to create a new filter for
81
+ * @param {string} [pFilterExperienceHash] - The filter experience hash to create a new filter for; if not provided, a new one will be generated
82
+ */
83
+ newFilter(pRecordSet: string, pFilterExperienceHash?: string): void;
84
+ /**
85
+ * @param {string} pRecordSet - The record set to save the filter for; TODO: should this have a default?
86
+ */
87
+ saveFilter(pRecordSet: string): void;
88
+ /**
89
+ * @param {string} pRecordSet - The record set to load the filter for
90
+ * @param {string} pFilterFilterExperienceHash - The filter experience hash to load; if not provided, the last used one will be loaded
91
+ */
92
+ loadFilter(pRecordSet: string, pFilterFilterExperienceHash: string): void;
93
+ /**
94
+ * @param {string} pKey - The key to get from the cache
95
+ *
96
+ * @return {any} - The value associated with the key, or false if not found
97
+ */
98
+ getItem(pKey: string): any;
99
+ /**
100
+ * @param {string} pKey - The key to set in the cache
101
+ * @param {any} pValue - The value to associate with the key
102
+ */
103
+ setItem(pKey: string, pValue: any): boolean;
104
+ /**
105
+ * @param {string} pKey - The key to remove from the cache
106
+ *
107
+ * @return {boolean} - True if the item was removed, false if it was not found
108
+ */
109
+ removeItem(pKey: string): boolean;
110
+ }
111
+ declare namespace FilterDataProvider {
112
+ export { _DEFAULT_PROVIDER_CONFIGURATION as default_configuration };
113
+ }
114
+ import libPictProvider = require("pict-provider");
115
+ declare namespace _DEFAULT_PROVIDER_CONFIGURATION {
116
+ let ProviderIdentifier: string;
117
+ let AutoInitialize: boolean;
118
+ let AutoInitializeOrdinal: number;
119
+ }
120
+ //# sourceMappingURL=Filter-Data-Provider.d.ts.map