pict-section-recordset 1.8.1 → 1.9.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pict-section-recordset",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Pict dynamic record set management views",
|
|
5
5
|
"main": "source/Pict-Section-RecordSet.js",
|
|
6
6
|
"files": [
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"browser-env": "^3.3.0",
|
|
38
38
|
"eslint": "^9.28.0",
|
|
39
39
|
"jquery": "^3.7.1",
|
|
40
|
-
"pict": "^1.0.
|
|
40
|
+
"pict": "^1.0.372",
|
|
41
41
|
"pict-application": "^1.0.34",
|
|
42
|
-
"pict-docuserve": "^1.4.
|
|
42
|
+
"pict-docuserve": "^1.4.4",
|
|
43
43
|
"pict-service-commandlineutility": "^1.0.19",
|
|
44
44
|
"quackage": "^1.3.0",
|
|
45
45
|
"typescript": "^5.9.3"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"fable-serviceproviderbase": "^3.0.19",
|
|
49
49
|
"pict-provider": "^1.0.13",
|
|
50
50
|
"pict-router": "^1.0.10",
|
|
51
|
-
"pict-section-form": "^1.
|
|
51
|
+
"pict-section-form": "^1.0.196",
|
|
52
52
|
"pict-template": "^1.0.15",
|
|
53
53
|
"pict-view": "^1.0.68",
|
|
54
54
|
"sinon": "^21.0.1"
|
|
@@ -477,6 +477,43 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
477
477
|
return pRecord;
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
/**
|
|
481
|
+
* The "list entry" display template for an entity — how one of its records should read as a single line
|
|
482
|
+
* in a picker option / selected chip. Returns a pict template string (rendered against the raw record by
|
|
483
|
+
* the picker's TextTemplate), or null to fall back to a single display field.
|
|
484
|
+
*
|
|
485
|
+
* This is deliberately a small, overridable seam: today it hard-knows `User` (whose name lives across
|
|
486
|
+
* NameFull / NameFirst+NameLast and needs an Email/LoginID disambiguator), but the intent is that this
|
|
487
|
+
* eventually reads a per-entity template off the Stricture schema instead of branching here.
|
|
488
|
+
*
|
|
489
|
+
* @param {string} pEntityName - The entity (e.g. 'User').
|
|
490
|
+
* @return {string|null}
|
|
491
|
+
*/
|
|
492
|
+
getEntityListEntryTemplate(pEntityName)
|
|
493
|
+
{
|
|
494
|
+
// Register the User branching fall-backs once. addTemplate is idempotent (keyed by hash), so the
|
|
495
|
+
// guard is just to avoid the churn of re-registering on every descriptor build.
|
|
496
|
+
if (!this._entityListEntryTemplatesRegistered)
|
|
497
|
+
{
|
|
498
|
+
this._entityListEntryTemplatesRegistered = true;
|
|
499
|
+
// Name fallback: when NameFull is empty, compose it from the parts.
|
|
500
|
+
this.pict.TemplateProvider.addTemplate('RSP-EntityListEntry-User-NameParts', '{~D:Record.NameFirst~} {~D:Record.NameLast~}');
|
|
501
|
+
// Disambiguator fallback: when Email is empty, use the LoginID.
|
|
502
|
+
this.pict.TemplateProvider.addTemplate('RSP-EntityListEntry-User-Login', '{~D:Record.LoginID~}');
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
switch (pEntityName)
|
|
506
|
+
{
|
|
507
|
+
case 'User':
|
|
508
|
+
// "<name> (<email>)" — name is NameFull, else NameFirst+NameLast; the parenthetical is Email,
|
|
509
|
+
// else LoginID. Stable across the three name-field variations and unique enough to tell apart
|
|
510
|
+
// many same-named users.
|
|
511
|
+
return '{~DWTF:Record.NameFull:RSP-EntityListEntry-User-NameParts~} ({~DWTF:Record.Email:RSP-EntityListEntry-User-Login~})';
|
|
512
|
+
default:
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
480
517
|
/**
|
|
481
518
|
* @param {string} pSchemaField - The schema field name.
|
|
482
519
|
* @param {Record<string, any>} pColumn - The full column definition from the schema.
|
|
@@ -498,29 +535,23 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
498
535
|
const tmpFieldHumanName = this.getHumanReadableFieldName(pSchemaField);
|
|
499
536
|
const isUserAuditField = ['CreatingIDUser', 'DeletingIDUser', 'UpdatingIDUser'].includes(pSchemaField);
|
|
500
537
|
const customFilterClauses = this.options.Filters?.[pSchemaField];
|
|
501
|
-
|
|
502
|
-
const isOwnIdentityField = pMeadowSchemaField && (pMeadowSchemaField.Type === 'AutoIdentity' || pMeadowSchemaField.Type === 'AutoGUID');
|
|
503
|
-
const isForeignKeyLike = pSchemaField.startsWith('ID') || pSchemaField.startsWith('ParentID') || isUserAuditField || customFilterClauses;
|
|
504
|
-
if (isForeignKeyLike)
|
|
538
|
+
if (pSchemaField.startsWith('ID') || pSchemaField.startsWith('ParentID') || isUserAuditField || customFilterClauses)
|
|
505
539
|
{
|
|
506
540
|
for (const customField of Array.isArray(customFilterClauses) ? customFilterClauses : [customFilterClauses])
|
|
507
541
|
{
|
|
508
|
-
|
|
509
|
-
// recordset's declared Entity when the column is our own primary key (the PK
|
|
510
|
-
// references our own records), else the name peeled from the column for a
|
|
511
|
-
// plain foreign key. Peeling alone is the defect — a lake PK like
|
|
512
|
-
// `IDC182_HMA_MixDesign` peels to a table name that is not the entity name.
|
|
513
|
-
const remoteTableName = customField?.RemoteTable || (isOwnIdentityField ? this.options.Entity : pSchemaField.split('ID')[1]);
|
|
542
|
+
const remoteTableName = customField?.RemoteTable || pSchemaField.split('ID')[1];
|
|
514
543
|
const fieldName = this.getHumanReadableFieldName(pSchemaField);
|
|
515
544
|
tmpFieldFilterClauses.push(Object.assign(
|
|
516
545
|
{
|
|
517
546
|
"Label": `${ fieldName }`,
|
|
518
547
|
"Type": "InternalJoinSelectedValueList",
|
|
519
|
-
"ExternalFilterByColumns": remoteTableName === 'User' ? [ 'NameFirst', 'NameLast' ] : [ 'Name' ],
|
|
548
|
+
"ExternalFilterByColumns": remoteTableName === 'User' ? [ 'NameFirst', 'NameLast', 'Email', 'LoginID' ] : [ 'Name' ],
|
|
520
549
|
"ExternalRecordDisplayTemplate": remoteTableName === 'User' ? '{~D:Record.Data.NameFirst~} {~D:Record.Data.NameLast~}' : '{~D:Record.Name~}',
|
|
550
|
+
// The picker's option/selected display: a per-entity "list entry" template (the seam that
|
|
551
|
+
// will eventually live on the Stricture schema). Disambiguates beyond a single column.
|
|
552
|
+
"EntityListEntryTemplate": this.getEntityListEntryTemplate(remoteTableName),
|
|
521
553
|
"CoreConnectionColumn": pSchemaField,
|
|
522
554
|
"RemoteTable": `${ remoteTableName }`,
|
|
523
|
-
"URLPrefix": this.options.URLPrefix,
|
|
524
555
|
"JoinExternalConnectionColumn": `ID${ remoteTableName }`,
|
|
525
556
|
"JoinInternalConnectionColumn": pSchemaField,
|
|
526
557
|
'DisplayName': `Selected Records`,
|
|
@@ -530,10 +561,7 @@ class MeadowEndpointsRecordSetProvider extends libRecordSetProviderBase
|
|
|
530
561
|
}, customField));
|
|
531
562
|
}
|
|
532
563
|
}
|
|
533
|
-
|
|
534
|
-
// Exact / In Range clauses below. A real foreign key gets only the picker; ordinary
|
|
535
|
-
// columns are matched by type.
|
|
536
|
-
if (!isForeignKeyLike || isOwnIdentityField)
|
|
564
|
+
else
|
|
537
565
|
{
|
|
538
566
|
switch (tmpFieldType)
|
|
539
567
|
{
|
|
@@ -683,6 +683,9 @@ class ViewRecordSetSUBSETFilters extends libPictView
|
|
|
683
683
|
ValueField: tmpDescriptor.JoinExternalConnectionColumn || `ID${tmpDescriptor.RemoteTable}`,
|
|
684
684
|
SearchFields: tmpSearchFields,
|
|
685
685
|
TextField: tmpSearchFields[0],
|
|
686
|
+
// Composed, disambiguated option/chip label (e.g. "Brian Smith (brian@…)") — falls back to
|
|
687
|
+
// TextField when the entity has no list-entry template.
|
|
688
|
+
TextTemplate: tmpDescriptor.EntityListEntryTemplate || undefined,
|
|
686
689
|
Placeholder: `Select ${pMount.Label}…`,
|
|
687
690
|
OnChange: (pValue) => this.applyQuickFilterEntity(pRecordSet, pViewContext, pMount.Field, pMount.ClauseKey, pValue),
|
|
688
691
|
});
|
|
@@ -156,6 +156,9 @@ class ViewRecordSetSUBSETFilterEntityReferenceBase extends ViewRecordSetSUBSETFi
|
|
|
156
156
|
pRecord.ClauseDescriptor.PictForm.Multiple = this.isMultiSelect();
|
|
157
157
|
pRecord.ClauseDescriptor.PictForm.SearchFields = pRecord.ClauseDescriptor.PictForm.SearchFields
|
|
158
158
|
|| pRecord.ExternalFilterByColumns || (pRecord.ExternalFilterByColumn ? [ pRecord.ExternalFilterByColumn ] : [ 'Name' ]);
|
|
159
|
+
// Composed, disambiguated option/chip label (the entity's "list entry" template); falls back to a
|
|
160
|
+
// single display field when unset.
|
|
161
|
+
pRecord.ClauseDescriptor.PictForm.TextTemplate = pRecord.ClauseDescriptor.PictForm.TextTemplate || pRecord.EntityListEntryTemplate;
|
|
159
162
|
pRecord.ClauseDescriptor.PictForm.ValueArrayAddress = pRecord.ClauseValuesAddress;
|
|
160
163
|
pRecord.ClauseDescriptor.PictForm.GetContextScopeFilter = () => this.getContextScopeFilter(this.getInformaryScopedValue(pRecord.ClauseAddress) || pRecord);
|
|
161
164
|
// JoinEntity compound display (host opt-in on the clause): show each searched row joined to a
|
|
@@ -230,7 +233,6 @@ class ViewRecordSetSUBSETFilterEntityReferenceBase extends ViewRecordSetSUBSETFi
|
|
|
230
233
|
Destination: pOffset > 0 ? `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResultsAppend` : `${this.getInformaryAddressPrefix()}${pClauseInformaryAddress}.SearchResults`,
|
|
231
234
|
RecordStartCursor: pOffset,
|
|
232
235
|
PageSize: this.options.PageSize,
|
|
233
|
-
URLPrefix: tmpClause.URLPrefix,
|
|
234
236
|
}
|
|
235
237
|
],
|
|
236
238
|
() =>
|