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.
- package/example_applications/simple_entity/Simple-RecordSet-Application.js +199 -3
- package/example_applications/simple_entity/html/index.html +6 -0
- package/package.json +2 -2
- package/source/providers/Filter-Data-Provider.js +371 -0
- package/source/providers/RecordSet-Link-Manager.js +9 -1
- package/source/providers/RecordSet-RecordProvider-Base.js +1 -1
- package/source/providers/RecordSet-RecordProvider-MeadowEndpoints.js +76 -43
- package/source/services/RecordsSet-MetaController.js +48 -1
- package/source/templates/Pict-Template-FilterInstanceViews.js +11 -7
- package/source/views/RecordSet-Filters.js +78 -45
- package/source/views/filters/RecordSet-Filter-Base.js +19 -1
- package/source/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.js +270 -0
- package/source/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.js +277 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinSelectedValue.js +270 -0
- package/source/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.js +277 -0
- package/source/views/filters/index.js +4 -0
- package/types/providers/Filter-Data-Provider.d.ts +120 -0
- package/types/providers/Filter-Data-Provider.d.ts.map +1 -0
- package/types/providers/RecordSet-Link-Manager.d.ts +10 -5
- package/types/providers/RecordSet-Link-Manager.d.ts.map +1 -1
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts +1 -1
- package/types/providers/RecordSet-RecordProvider-MeadowEndpoints.d.ts.map +1 -1
- package/types/services/RecordsSet-MetaController.d.ts +36 -7
- package/types/services/RecordsSet-MetaController.d.ts.map +1 -1
- package/types/templates/Pict-Template-FilterInstanceViews.d.ts +1 -1
- package/types/templates/Pict-Template-FilterInstanceViews.d.ts.map +1 -1
- package/types/views/RecordSet-Filters.d.ts +10 -0
- package/types/views/RecordSet-Filters.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-Base.d.ts +10 -0
- package/types/views/filters/RecordSet-Filter-Base.d.ts.map +1 -1
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.d.ts +24 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValue.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.d.ts +24 -0
- package/types/views/filters/RecordSet-Filter-ExternalJoinSelectedValueList.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValue.d.ts +24 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValue.d.ts.map +1 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.d.ts +24 -0
- package/types/views/filters/RecordSet-Filter-InternalJoinSelectedValueList.d.ts.map +1 -0
- package/types/views/filters/index.d.ts +4 -0
|
@@ -381,45 +381,76 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
381
381
|
}
|
|
382
382
|
tmpFieldFilterClauses = [];
|
|
383
383
|
const tmpFieldHumanName = this._getHumanReadableFieldName(pSchemaField);
|
|
384
|
-
|
|
384
|
+
const isUserAuditField = ['CreatingIDUser', 'DeletingIDUser', 'UpdatingIDUser'].includes(pSchemaField);
|
|
385
|
+
const customFilterClauses = this.options.Filters?.[pSchemaField];
|
|
386
|
+
if (pSchemaField.startsWith('ID') || isUserAuditField || customFilterClauses)
|
|
385
387
|
{
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
388
|
+
for (const customField of Array.isArray(customFilterClauses) ? customFilterClauses : [customFilterClauses])
|
|
389
|
+
{
|
|
390
|
+
const remoteTableName = customField?.RemoteTable || pSchemaField.split('ID')[1];
|
|
391
|
+
const fieldName = isUserAuditField ? this._getHumanReadableFieldName(pSchemaField) : this._getHumanReadableEntityName(remoteTableName);
|
|
392
|
+
tmpFieldFilterClauses.push(Object.assign(
|
|
393
|
+
{
|
|
394
|
+
"Label": `${ fieldName }`,
|
|
395
|
+
"Type": "InternalJoinSelectedValueList",
|
|
396
|
+
"ExternalFilterByColumns": remoteTableName === 'User' ? [ 'NameFirst', 'NameLast' ] : [ 'Name' ],
|
|
397
|
+
|
|
398
|
+
"ExternalRecordDisplayTemplate": remoteTableName === 'User' ? '{~D:Record.Data.NameFirst~} {~D:Record.Data.NameLast~}' : '{~D:Record.Name~}',
|
|
399
|
+
|
|
400
|
+
"CoreConnectionColumn": pSchemaField,
|
|
401
|
+
|
|
402
|
+
"RemoteTable": `${ remoteTableName }`,
|
|
403
|
+
"JoinExternalConnectionColumn": `ID${ remoteTableName }`,
|
|
404
|
+
"JoinInternalConnectionColumn": `ID${ remoteTableName }`,
|
|
405
|
+
'DisplayName': `Selected Records`,
|
|
406
|
+
'Ordinal': tmpFieldFilterClauses.length + 1,
|
|
407
|
+
'FilterKey': pSchemaField,
|
|
408
|
+
'ClauseKey': `${pSchemaField}_Selected`
|
|
409
|
+
}, customField));
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
else
|
|
413
|
+
{
|
|
414
|
+
switch (tmpFieldType)
|
|
415
|
+
{
|
|
416
|
+
case 'string':
|
|
417
|
+
case 'autoguid':
|
|
418
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Exact`, DisplayName: `Exact Match`, Type: 'StringMatch', FilterByColumn: pSchemaField, ExactMatch: true, Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
419
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Fuzzy`, DisplayName: `Partial Match`, Type: 'StringMatch', FilterByColumn: pSchemaField, ExactMatch: false , Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
420
|
+
tmpRangeClause = { FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Range`, DisplayName: `In Range`, Type: 'StringRange', FilterByColumn: pSchemaField , Ordinal: tmpFieldFilterClauses.length + 1 };
|
|
421
|
+
tmpRangeClause.MinimumLabel = `Minimum ${tmpFieldHumanName}`;
|
|
422
|
+
tmpRangeClause.MaximumLabel = `Maximum ${tmpFieldHumanName}`;
|
|
423
|
+
tmpFieldFilterClauses.push(tmpRangeClause);
|
|
424
|
+
break;
|
|
425
|
+
case 'date':
|
|
426
|
+
case 'datetime':
|
|
427
|
+
case 'createdate':
|
|
428
|
+
case 'updatedate':
|
|
429
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Exact`, DisplayName: `Exact Match`, Type: 'DateMatch', FilterByColumn: pSchemaField, ExactMatch: true , Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
430
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Fuzzy`, DisplayName: `Partial Match`, Type: 'DateMatch', FilterByColumn: pSchemaField, ExactMatch: false , Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
431
|
+
tmpRangeClause = { FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Range`, DisplayName: `In Range`, Type: 'DateRange', FilterByColumn: pSchemaField , Ordinal: tmpFieldFilterClauses.length + 1 };
|
|
432
|
+
tmpRangeClause.MinimumLabel = `Minimum ${tmpFieldHumanName}`;
|
|
433
|
+
tmpRangeClause.MaximumLabel = `Maximum ${tmpFieldHumanName}`;
|
|
434
|
+
tmpFieldFilterClauses.push(tmpRangeClause);
|
|
435
|
+
break;
|
|
436
|
+
case 'boolean': //TODO: we didn't add filters for this - they are just numeric but it's weird for the user, maybe we should add views for this that account for the difference
|
|
437
|
+
case 'deleted':
|
|
438
|
+
case 'integer':
|
|
439
|
+
case 'decimal':
|
|
440
|
+
case 'autoidentity':
|
|
441
|
+
case 'createiduser':
|
|
442
|
+
case 'updateiduser':
|
|
443
|
+
case 'deleteiduser':
|
|
444
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Exact`, DisplayName: `Exact Match`, Type: 'NumericMatch', FilterByColumn: pSchemaField, ExactMatch: true , Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
445
|
+
tmpFieldFilterClauses.push({ FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Match_Fuzzy`, DisplayName: `Partial Match`, Type: 'NumericMatch', FilterByColumn: pSchemaField, ExactMatch: false , Ordinal: tmpFieldFilterClauses.length + 1 });
|
|
446
|
+
tmpRangeClause = { FilterKey: pSchemaField, ClauseKey: `${pSchemaField}_Range`, DisplayName: `In Range`, Type: 'NumericRange', FilterByColumn: pSchemaField , Ordinal: tmpFieldFilterClauses.length + 1 };
|
|
447
|
+
tmpRangeClause.MinimumLabel = `Minimum ${tmpFieldHumanName}`;
|
|
448
|
+
tmpRangeClause.MaximumLabel = `Maximum ${tmpFieldHumanName}`;
|
|
449
|
+
tmpFieldFilterClauses.push(tmpRangeClause);
|
|
450
|
+
break;
|
|
451
|
+
default:
|
|
452
|
+
this.pict.log.warn(`Unsupported field type ${pColumn.type} for field ${pSchemaField}`, { Schema: pColumn });
|
|
453
|
+
}
|
|
423
454
|
}
|
|
424
455
|
}
|
|
425
456
|
return tmpFieldFilterClauses;
|
|
@@ -432,6 +463,8 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
432
463
|
{
|
|
433
464
|
super.onInitializeAsync((pError) =>
|
|
434
465
|
{
|
|
466
|
+
//FIXME: load the most recent experience from local storage using the other provider
|
|
467
|
+
// how do we control the initialization order of the providers?
|
|
435
468
|
if (this.options.FilterExperiences && typeof this.options.FilterExperiences === 'object' && !Array.isArray(this.options.FilterExperiences))
|
|
436
469
|
{
|
|
437
470
|
this.pict.Bundle._ActiveFilterState = this.pict.Bundle._ActiveFilterState || {};
|
|
@@ -521,7 +554,7 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
521
554
|
* @param {string} pEntity - The schema field name.
|
|
522
555
|
* @return {string} - The human-readable name for the entity.
|
|
523
556
|
*/
|
|
524
|
-
|
|
557
|
+
_getHumanReadableEntityName(pEntity)
|
|
525
558
|
{
|
|
526
559
|
return pEntity.replace(/([a-z])([A-Z])/g, '$1 $2'); // Add space before capital letters
|
|
527
560
|
}
|
|
@@ -538,11 +571,11 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
538
571
|
}
|
|
539
572
|
if (pSchemaField === `ID${this.options.Entity}`)
|
|
540
573
|
{
|
|
541
|
-
return `${this.
|
|
574
|
+
return `${this._getHumanReadableEntityName(this.options.Entity)} Unique Database ID`;
|
|
542
575
|
}
|
|
543
576
|
if (pSchemaField === `GUID${this.options.Entity}`)
|
|
544
577
|
{
|
|
545
|
-
return `${this.
|
|
578
|
+
return `${this._getHumanReadableEntityName(this.options.Entity)} Unique Identifier`;
|
|
546
579
|
}
|
|
547
580
|
if (pSchemaField === 'CreatingIDUser')
|
|
548
581
|
{
|
|
@@ -637,7 +670,7 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
637
670
|
}
|
|
638
671
|
if (!tmpFieldFilterSchema.HelpText)
|
|
639
672
|
{
|
|
640
|
-
tmpFieldFilterSchema.HelpText = `Filter by ${tmpFieldFilterSchema.DisplayName} for the ${this.
|
|
673
|
+
tmpFieldFilterSchema.HelpText = `Filter by ${tmpFieldFilterSchema.DisplayName} for the ${this._getHumanReadableEntityName(this.options.Entity)} entity.`;
|
|
641
674
|
}
|
|
642
675
|
if (tmpFieldFilterSchema.Ordinal == null)
|
|
643
676
|
{
|
|
@@ -694,7 +727,7 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
694
727
|
}
|
|
695
728
|
if (!tmpFieldFilterSchema.HelpText)
|
|
696
729
|
{
|
|
697
|
-
tmpFieldFilterSchema.HelpText = tmpFilterClause.HelpText || `Filter by ${tmpFieldFilterSchema.DisplayName} for the ${this.
|
|
730
|
+
tmpFieldFilterSchema.HelpText = tmpFilterClause.HelpText || `Filter by ${tmpFieldFilterSchema.DisplayName} for the ${this._getHumanReadableEntityName(this.options.Entity)} entity.`;
|
|
698
731
|
}
|
|
699
732
|
if (tmpFieldFilterSchema.Ordinal == null)
|
|
700
733
|
{
|
|
@@ -96,6 +96,8 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
96
96
|
*/
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
+
* @param {string} pRecordSet - The RecordSet name to get the configuration for.
|
|
100
|
+
*
|
|
99
101
|
* @return {Record<string, any>} - The registered configuration for the RecordSet
|
|
100
102
|
*/
|
|
101
103
|
getRecordSetConfiguration(pRecordSet)
|
|
@@ -103,6 +105,9 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
103
105
|
return this.recordSetProviderConfigurations[pRecordSet];
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @param {Record<string, any>} pRecordSetConfiguration - The RecordSet configuration to load.
|
|
110
|
+
*/
|
|
106
111
|
loadRecordSetConfiguration(pRecordSetConfiguration)
|
|
107
112
|
{
|
|
108
113
|
if (typeof pRecordSetConfiguration !== 'object')
|
|
@@ -208,6 +213,9 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
208
213
|
return tmpProvider;
|
|
209
214
|
}
|
|
210
215
|
|
|
216
|
+
/**
|
|
217
|
+
* @param {Array<Record<string, any>>} pRecordSetConfigurationArray - An array of RecordSet configurations to load.
|
|
218
|
+
*/
|
|
211
219
|
loadRecordSetConfigurationArray(pRecordSetConfigurationArray)
|
|
212
220
|
{
|
|
213
221
|
if (!Array.isArray(pRecordSetConfigurationArray))
|
|
@@ -229,6 +237,11 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
229
237
|
}
|
|
230
238
|
}
|
|
231
239
|
|
|
240
|
+
/**
|
|
241
|
+
* @param {Record<string, any> | string} pRecordSet - The RecordSet configuration or hash to load dynamically.
|
|
242
|
+
* @param {string} [pEntity] - (optional) The Entity type to use (defaults to the RecordSet name if not provided).
|
|
243
|
+
* @param {string} [pDefaultFilter] - (optional) The default filter to use.
|
|
244
|
+
*/
|
|
232
245
|
loadRecordSetDynamically(pRecordSet, pEntity, pDefaultFilter)
|
|
233
246
|
{
|
|
234
247
|
if (typeof(pRecordSet) === 'object')
|
|
@@ -238,6 +251,11 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
238
251
|
|
|
239
252
|
return this.fable.providers[tmpRecordSetProviderHash].initializeAsync((pError) =>
|
|
240
253
|
{
|
|
254
|
+
if (pError)
|
|
255
|
+
{
|
|
256
|
+
this.log.error(`RecordSet [${pRecordSet.RecordSet}] dynamically loaded with error: ${pError.message || pError}`, { Stack: pError.stack });
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
241
259
|
this.log.trace(`RecordSet [${pRecordSet.RecordSet} dynamically loaded.`);
|
|
242
260
|
})
|
|
243
261
|
}
|
|
@@ -264,6 +282,11 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
264
282
|
return this.fable.providers[tmpRecordSetProviderHash].initializeAsync(
|
|
265
283
|
(pError) =>
|
|
266
284
|
{
|
|
285
|
+
if (pError)
|
|
286
|
+
{
|
|
287
|
+
this.log.error(`RecordSet [${tmpRecordSet}] dynamically loaded with error: ${pError.message || pError}`, { Stack: pError.stack });
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
267
290
|
this.log.trace(`RecordSet [${tmpRecordSetConfiguration.RecordSet} dynamically loaded.`);
|
|
268
291
|
});
|
|
269
292
|
}
|
|
@@ -272,6 +295,9 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
272
295
|
return false;
|
|
273
296
|
}
|
|
274
297
|
|
|
298
|
+
/**
|
|
299
|
+
* @param {Record<string, any>} pRoutePayload - The route payload containing the RecordSet and optional Entity and DefaultFilter.
|
|
300
|
+
*/
|
|
275
301
|
handleLoadDynamicRecordSetRoute(pRoutePayload)
|
|
276
302
|
{
|
|
277
303
|
if (typeof(pRoutePayload) != 'object')
|
|
@@ -287,6 +313,9 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
287
313
|
return this.loadRecordSetDynamically(tmpRecordSet, tmpEntity, tmpDefaultFilter);
|
|
288
314
|
}
|
|
289
315
|
|
|
316
|
+
/**
|
|
317
|
+
* @param {import('pict-router')} pPictRouter - The Pict Router to add the routes to.
|
|
318
|
+
*/
|
|
290
319
|
addRoutes(pPictRouter)
|
|
291
320
|
{
|
|
292
321
|
pPictRouter.addRoute('/PSRS/:RecordSet/LoadDynamic', this.handleLoadDynamicRecordSetRoute.bind(this));
|
|
@@ -295,6 +324,9 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
295
324
|
return true;
|
|
296
325
|
}
|
|
297
326
|
|
|
327
|
+
/**
|
|
328
|
+
* @param {string} pCapability - The capability to check for.
|
|
329
|
+
*/
|
|
298
330
|
async checkSession(pCapability)
|
|
299
331
|
{
|
|
300
332
|
for (const sessionProvider of this.sessionProviders)
|
|
@@ -307,6 +339,13 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
307
339
|
return true;
|
|
308
340
|
}
|
|
309
341
|
|
|
342
|
+
/**
|
|
343
|
+
* @param {string} pNameTemplate - The name template for the record link.
|
|
344
|
+
* @param {string} pURLTemplate - The URL template for the record link.
|
|
345
|
+
* @param {boolean} pDefault - Whether this is a default link template.
|
|
346
|
+
*
|
|
347
|
+
* @return {Record<string, any>} - The link template object that was added.
|
|
348
|
+
*/
|
|
310
349
|
addRecordLinkTemplate(pNameTemplate, pURLTemplate, pDefault)
|
|
311
350
|
{
|
|
312
351
|
return this.fable.providers.RecordSetLinkManager.addRecordLinkTemplate(pNameTemplate, pURLTemplate, pDefault);
|
|
@@ -344,7 +383,15 @@ class RecordSetMetacontroller extends libFableServiceProviderBase
|
|
|
344
383
|
{
|
|
345
384
|
for (const tmpFilterKey of Object.keys(this.fable.settings.Filters))
|
|
346
385
|
{
|
|
347
|
-
this.
|
|
386
|
+
const filterArray = Array.isArray(this.fable.settings.Filters[tmpFilterKey]) ? this.fable.settings.Filters[tmpFilterKey] : [this.fable.settings.Filters[tmpFilterKey]];
|
|
387
|
+
for (let x = 0; x < filterArray.length; x++)
|
|
388
|
+
{
|
|
389
|
+
if (!filterArray[x].DisplayName)
|
|
390
|
+
{
|
|
391
|
+
filterArray[x].DisplayName = filterArray[x].Label || tmpFilterKey;
|
|
392
|
+
}
|
|
393
|
+
this.pict.providers.FilterManager.addFilter(filterArray[x].FilterKey || `${ tmpFilterKey }${ x ? `_${ x }` : '' }`, filterArray[x]);
|
|
394
|
+
}
|
|
348
395
|
}
|
|
349
396
|
}
|
|
350
397
|
|
|
@@ -30,17 +30,22 @@ class PictTemplateFilterInstanceViewInstruction extends libPictTemplate
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
_getViewForFilterClause(pClause)
|
|
34
34
|
{
|
|
35
|
-
|
|
35
|
+
let tmpViewHash = `PRSP-FilterType-${pClause.Type}`;
|
|
36
|
+
const tmpCustomViewHash = `${tmpViewHash}-${pClause.CustomFilterViewHash}`;
|
|
37
|
+
if (tmpCustomViewHash in this.pict.views)
|
|
38
|
+
{
|
|
39
|
+
tmpViewHash = tmpCustomViewHash;
|
|
40
|
+
}
|
|
36
41
|
/** @type {import('../views/filters/RecordSet-Filter-Base.js')} */
|
|
37
42
|
let tmpView = this.pict.views[tmpViewHash];
|
|
38
43
|
if (!tmpView)
|
|
39
44
|
{
|
|
40
|
-
const tmpViewPrototype = libFilterViews[
|
|
45
|
+
const tmpViewPrototype = libFilterViews[pClause.Type] || libFilterViews.Base;
|
|
41
46
|
if (!tmpViewPrototype)
|
|
42
47
|
{
|
|
43
|
-
this.pict.log.error(`Pict: Filter Instance Views Template Render: No view prototype found for filter type [${
|
|
48
|
+
this.pict.log.error(`Pict: Filter Instance Views Template Render: No view prototype found for filter type [${pClause.Type}]`);
|
|
44
49
|
return null;
|
|
45
50
|
}
|
|
46
51
|
//FIXME: is this safe? will this view get rendered at other times?
|
|
@@ -103,11 +108,10 @@ class PictTemplateFilterInstanceViewInstruction extends libPictTemplate
|
|
|
103
108
|
const tmpClauses = this.pict.Bundle._ActiveFilterState?.[pRecord.RecordSet]?.FilterClauses || [];
|
|
104
109
|
//FIXME: lookup by hash instead?
|
|
105
110
|
for (let i = 0; i < tmpClauses.length; i++)
|
|
106
|
-
//for (const tmpClauses of this.pict.Bundle._ActiveFilterState?.[pRecord.RecordSet]?.FilterClauses || [])
|
|
107
111
|
{
|
|
108
112
|
const tmpClause = tmpClauses[i];
|
|
109
113
|
/** @type {import('../views/filters/RecordSet-Filter-Base.js')} */
|
|
110
|
-
const tmpView = this.
|
|
114
|
+
const tmpView = this._getViewForFilterClause(tmpClause);
|
|
111
115
|
if (!tmpView)
|
|
112
116
|
{
|
|
113
117
|
continue;
|
|
@@ -182,7 +186,7 @@ class PictTemplateFilterInstanceViewInstruction extends libPictTemplate
|
|
|
182
186
|
{
|
|
183
187
|
const tmpClause = tmpClauses[i];
|
|
184
188
|
/** @type {import('../views/filters/RecordSet-Filter-Base.js')} */
|
|
185
|
-
const tmpView = this.
|
|
189
|
+
const tmpView = this._getViewForFilterClause(tmpClause);
|
|
186
190
|
if (!tmpView)
|
|
187
191
|
{
|
|
188
192
|
continue;
|
|
@@ -148,61 +148,61 @@ const _DEFAULT_CONFIGURATION_SUBSET_Filter =
|
|
|
148
148
|
//FIXME: export this from PSF?
|
|
149
149
|
const libPictViewDynamicForm = require('pict-section-form/source/views/Pict-View-DynamicForm.js');
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
const DynamicInputViewSectionDefinition = (
|
|
152
152
|
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
super(pFable, tmpOptions, pServiceHash);
|
|
157
|
-
/** @type {import('fable') & import('pict') & { PictSectionRecordSet: import('../Pict-Section-RecordSet.js') }} */
|
|
158
|
-
this.pict;
|
|
153
|
+
"Hash": "PSRSDynamicInputs",
|
|
154
|
+
"Name": "Custom Dynamic Inputs",
|
|
155
|
+
"ViewHash": "PSRSFilterProxyView",
|
|
159
156
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
"Hash": "PSRSDynamicInputs",
|
|
163
|
-
"Name": "Custom Dynamic Inputs",
|
|
164
|
-
"ViewHash": "PSRSFilterProxyView",
|
|
157
|
+
"AutoMarshalDataOnSolve": true,
|
|
158
|
+
"IncludeInMetatemplateSectionGeneration": false,
|
|
165
159
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
"Manifests":
|
|
161
|
+
{
|
|
162
|
+
"Section":
|
|
163
|
+
{
|
|
164
|
+
"Scope": "PSRSDynamic",
|
|
165
|
+
"Sections":
|
|
166
|
+
[
|
|
167
|
+
{
|
|
168
|
+
"Hash": "PSRSDynamicInputs",
|
|
169
|
+
"Name": "Dynamic Inputs"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"Descriptors":
|
|
170
173
|
{
|
|
171
|
-
"
|
|
174
|
+
"PSRS.DynamicInputPlaceholder":
|
|
172
175
|
{
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
"Hash": "PSRSDynamicInputs",
|
|
178
|
-
"Name": "Dynamic Inputs"
|
|
179
|
-
}
|
|
180
|
-
],
|
|
181
|
-
"Descriptors":
|
|
176
|
+
"Name": "DynamicInputPlaceholder",
|
|
177
|
+
"Hash": "DynamicInputPlaceholder",
|
|
178
|
+
"DataType": "String",
|
|
179
|
+
"Macro":
|
|
182
180
|
{
|
|
183
|
-
"
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
"Macro":
|
|
189
|
-
{
|
|
190
|
-
"HTMLSelector": ""
|
|
191
|
-
},
|
|
192
|
-
"PictForm":
|
|
193
|
-
{
|
|
194
|
-
"Section": "PSRSDynamicInputs"
|
|
195
|
-
}
|
|
196
|
-
}
|
|
181
|
+
"HTMLSelector": ""
|
|
182
|
+
},
|
|
183
|
+
"PictForm":
|
|
184
|
+
{
|
|
185
|
+
"Section": "PSRSDynamicInputs"
|
|
197
186
|
}
|
|
198
187
|
}
|
|
199
188
|
}
|
|
200
|
-
}
|
|
201
|
-
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
class ViewRecordSetSUBSETFilters extends libPictView
|
|
193
|
+
{
|
|
194
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
195
|
+
{
|
|
196
|
+
let tmpOptions = Object.assign({}, _DEFAULT_CONFIGURATION_SUBSET_Filter, pOptions);
|
|
197
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
198
|
+
/** @type {import('fable') & import('pict') & { PictSectionRecordSet: import('../Pict-Section-RecordSet.js') }} */
|
|
199
|
+
this.pict;
|
|
200
|
+
|
|
201
|
+
if (!this.pict.views[DynamicInputViewSectionDefinition.ViewHash])
|
|
202
202
|
{
|
|
203
|
-
const tmpViewConfiguration = Object.assign({},
|
|
203
|
+
const tmpViewConfiguration = Object.assign({}, DynamicInputViewSectionDefinition);
|
|
204
204
|
this.pict.addView(tmpViewConfiguration.ViewHash, tmpViewConfiguration, libPictViewDynamicForm);
|
|
205
|
-
this.pict.views[
|
|
205
|
+
this.pict.views[DynamicInputViewSectionDefinition.ViewHash].viewMarshalDestination = 'Bundle';
|
|
206
206
|
}
|
|
207
207
|
for (const tmpView of Object.values(require('./filters')))
|
|
208
208
|
{
|
|
@@ -221,6 +221,25 @@ class ViewRecordSetSUBSETFilters extends libPictView
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @return {string} - The marshalling prefix configured for filters. Usually 'Bundle.'
|
|
226
|
+
*/
|
|
227
|
+
getInformaryAddressPrefix()
|
|
228
|
+
{
|
|
229
|
+
return `${this.pict.views[DynamicInputViewSectionDefinition.ViewHash].viewMarshalDestination}.`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @param {string} pAddress - The address of the informary to get the value from.
|
|
234
|
+
*
|
|
235
|
+
* @return {any} - The value at the given address, using the informary marshalling prefix.
|
|
236
|
+
*/
|
|
237
|
+
getInformaryScopedValue(pAddress)
|
|
238
|
+
{
|
|
239
|
+
const tmpCompositeAddress = `${this.getInformaryAddressPrefix()}${pAddress}`;
|
|
240
|
+
return this.pict.resolveStateFromAddress(tmpCompositeAddress);
|
|
241
|
+
}
|
|
242
|
+
|
|
224
243
|
//NOTE: two methods below copied from the pict-section-form metacontroller
|
|
225
244
|
//TODO: consider subclassing the dynamic view to somehow mark these as filter views so we can only operate on those views
|
|
226
245
|
|
|
@@ -315,6 +334,7 @@ class ViewRecordSetSUBSETFilters extends libPictView
|
|
|
315
334
|
{
|
|
316
335
|
tmpURL = tmpURL.replace(/\/FilteredTo\//, '');
|
|
317
336
|
}
|
|
337
|
+
this.render(undefined, undefined, { RecordSet: pRecordSet, ViewContext: pViewContext });
|
|
318
338
|
this.serializeFilterExperience(this.pict.Bundle._ActiveFilterState[pRecordSet]?.FilterClauses).then((pFilterExperienceSerialized) =>
|
|
319
339
|
{
|
|
320
340
|
if (pFilterExperienceSerialized)
|
|
@@ -342,6 +362,11 @@ class ViewRecordSetSUBSETFilters extends libPictView
|
|
|
342
362
|
{
|
|
343
363
|
delete tmpClause.Value;
|
|
344
364
|
delete tmpClause.Values;
|
|
365
|
+
delete tmpClause.SearchInputValue;
|
|
366
|
+
delete tmpClause.SelectedValues;
|
|
367
|
+
delete tmpClause.SearchResults;
|
|
368
|
+
delete tmpClause.SearchResultsOffset;
|
|
369
|
+
delete tmpClause.LoadMoreEnabled;
|
|
345
370
|
}
|
|
346
371
|
}
|
|
347
372
|
this.performSearch(pRecordSet, pViewContext);
|
|
@@ -428,7 +453,15 @@ class ViewRecordSetSUBSETFilters extends libPictView
|
|
|
428
453
|
{
|
|
429
454
|
return '';
|
|
430
455
|
}
|
|
431
|
-
|
|
456
|
+
const tmpExperience = JSON.parse(JSON.stringify(pExperience));
|
|
457
|
+
for (const tmpClause of tmpExperience)
|
|
458
|
+
{
|
|
459
|
+
//FIXME: avoiding saving search results to the URL but this pattern isn't ideal
|
|
460
|
+
delete tmpClause.SearchResults;
|
|
461
|
+
delete tmpClause.SearchResultsOffset;
|
|
462
|
+
delete tmpClause.LoadMoreEnabled;
|
|
463
|
+
}
|
|
464
|
+
return this.encode(await this.compress(JSON.stringify(tmpExperience)));
|
|
432
465
|
}
|
|
433
466
|
|
|
434
467
|
/**
|
|
@@ -41,7 +41,7 @@ const _DEFAULT_CONFIGURATION_SUBSET_Filter =
|
|
|
41
41
|
Hash: 'PRSP-Filter-Base-Template',
|
|
42
42
|
Template: /*html*/`
|
|
43
43
|
<!-- DefaultPackage pict view template: [PRSP-Filter-Base-Template] -->
|
|
44
|
-
<div>
|
|
44
|
+
<div id="PRSP_Filter_Container_{~D:Record.Hash~}">
|
|
45
45
|
<button type="button"
|
|
46
46
|
onclick="_Pict.views['PRSP-Filters'].removeFilter(event, '{~D:Record.RecordSet~}', '{~D:Record.ViewContext~}', '{~D:Record.Hash~}');"
|
|
47
47
|
>
|
|
@@ -97,6 +97,24 @@ class ViewRecordSetSUBSETFilterBase extends libPictView
|
|
|
97
97
|
{
|
|
98
98
|
return 'PRSP-Filter-Base-Form';
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @return {string} - The prefix for the informary address.
|
|
103
|
+
*/
|
|
104
|
+
getInformaryAddressPrefix()
|
|
105
|
+
{
|
|
106
|
+
return this.pict.views['PRSP-Filters'].getInformaryAddressPrefix();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} pInformaryAddress - The address of the informary to get the value from.
|
|
111
|
+
*
|
|
112
|
+
* @return {any} - The value at the informary address.
|
|
113
|
+
*/
|
|
114
|
+
getInformaryScopedValue(pInformaryAddress)
|
|
115
|
+
{
|
|
116
|
+
return this.pict.views['PRSP-Filters'].getInformaryScopedValue(pInformaryAddress);
|
|
117
|
+
}
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
module.exports = ViewRecordSetSUBSETFilterBase;
|