diff --git a/packages/components/package-lock.json b/packages/components/package-lock.json index 380226a46e..27e4b39fd0 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "6.47.0", + "version": "6.48.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "6.47.0", + "version": "6.48.0", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", diff --git a/packages/components/package.json b/packages/components/package.json index 1fe3adc843..6278ab06f5 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "6.47.0", + "version": "6.48.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index 63701fbb48..cc061bcb08 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,6 +1,13 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages +### version 6.48.0 +*Released*: 9 June 2025 +- Issue 52556: Add data-fieldkey attribute to grid header elements and input elements (part 2) + - FileInput: drop the "-fileUpload" suffix from inputId + - EntityParentType model not to use capitalizeFirstChar() in generateFieldKey() + - EntityParentType model to set fieldKeyPath in generateColumn() + ### version 6.47.0 *Released*: 6 June 2025 - Issue 52595: Storage editor check in fails if user doesn't have perm to update sample amount/units diff --git a/packages/components/src/internal/components/entities/actions.ts b/packages/components/src/internal/components/entities/actions.ts index 88f95d943a..85ab08f28f 100644 --- a/packages/components/src/internal/components/entities/actions.ts +++ b/packages/components/src/internal/components/entities/actions.ts @@ -300,7 +300,7 @@ function resolveSampleParentTypes( EntityParentType.create({ index, schema: 'samples', - query: sampleType?.toLowerCase(), + query: sampleType, label: sampleType, value: orderedRowIds ? List(data.sort(_getEntitySort(orderedRowIds))) @@ -364,7 +364,7 @@ async function initParents( return getSelectedParents(schemaQuery, filterArray, isAliquotParent, selectionResponse.selected); } else if (initialParents?.length > 0) { const [parent] = initialParents; - const [schema, query, value] = parseEntityParentKey(parent.toLowerCase()); + const [schema, query, value] = parseEntityParentKey(parent); // if the parent key doesn't have a value, we don't need to make the request to getSelectedParents if (value === undefined) { @@ -431,7 +431,7 @@ function resolveEntityParentTypeFromIds( EntityParentType.create({ index: 1, schema: schemaQuery.schemaName, - query: schemaQuery.queryName, + query: dataClass ?? schemaQuery.queryName, label: dataClass, value: List(data), isAliquotParent, @@ -945,16 +945,15 @@ export const getOriginalParentsFromLineage = async ( // filter out additional parent alias columns that's already added const additionalParentTypeSchemaQueryKeys = []; additionalParentTypes?.forEach(parentType => { - additionalParentTypeSchemaQueryKeys.push( - parentType.toString().toLowerCase() - ); + additionalParentTypeSchemaQueryKeys.push(parentType.toString().toLowerCase()); }); parentTypeOptions = parentTypeOptions.set( dataType.typeListingSchemaQuery.queryName, validParentTypeOptions .filter(option => { - const schemaQueryKey = - new SchemaQuery(option.entityDataType.instanceSchemaName, option.query).toString().toLowerCase(); + const schemaQueryKey = new SchemaQuery(option.entityDataType.instanceSchemaName, option.query) + .toString() + .toLowerCase(); return ( originalParentTypeLsids.indexOf(option.lsid) === -1 && additionalParentTypeSchemaQueryKeys.indexOf(schemaQueryKey) === -1 diff --git a/packages/components/src/internal/components/entities/models.test.ts b/packages/components/src/internal/components/entities/models.test.ts index 7fd09eb2b7..4edd0f503c 100644 --- a/packages/components/src/internal/components/entities/models.test.ts +++ b/packages/components/src/internal/components/entities/models.test.ts @@ -70,7 +70,7 @@ describe('EntityParentType', () => { }); test('generateColumn parentColName', () => { - let col = EntityParentType.create({ query: 'sampletype' }).generateColumn( + let col = EntityParentType.create({ query: 'Sampletype' }).generateColumn( 'Display Column', SCHEMAS.SAMPLE_SETS.SCHEMA ); @@ -102,17 +102,21 @@ describe('EntityParentType', () => { }); test('generateFieldKey', () => { - expect(EntityParentType.create({ query: 'test' }).generateFieldKey()).toBe('MaterialInputs/Test'); + expect(EntityParentType.create({ query: 'test' }).generateFieldKey()).toBe('MaterialInputs/test'); + expect(EntityParentType.create({ query: 'test,./' }).generateFieldKey()).toBe('MaterialInputs/test$C$P$S'); + expect(EntityParentType.create({ query: 'Test', label: 'TEST' }).generateFieldKey()).toBe( + 'MaterialInputs/Test' + ); expect(EntityParentType.create({ query: 'test', isAliquotParent: true }).generateFieldKey()).toBe( 'AliquotedFrom' ); - expect(EntityParentType.create({ schema: SCHEMAS.DATA_CLASSES.SCHEMA, query: 'test' }).generateFieldKey()).toBe( + expect(EntityParentType.create({ schema: SCHEMAS.DATA_CLASSES.SCHEMA, query: 'Test' }).generateFieldKey()).toBe( 'DataInputs/Test' ); expect( EntityParentType.create({ schema: SCHEMAS.DATA_CLASSES.SCHEMA, - query: 'test', + query: 'Test', isAliquotParent: true, }).generateFieldKey() ).toBe('AliquotedFrom'); diff --git a/packages/components/src/internal/components/entities/models.ts b/packages/components/src/internal/components/entities/models.ts index bbaccb71ef..7167658821 100644 --- a/packages/components/src/internal/components/entities/models.ts +++ b/packages/components/src/internal/components/entities/models.ts @@ -99,19 +99,15 @@ export class EntityParentType extends Record({ } generateFieldKey(): string { - const parentInputType = this.getInputType(); - const formattedQueryName = capitalizeFirstChar(this.query); - // Issue 33653: query name is case-sensitive for some data inputs (sample parents), so leave it // capitalized here and we lower it where needed return this.isAliquotParent ? QueryColumn.ALIQUOTED_FROM - : [encodePart(parentInputType), encodePart(formattedQueryName)].join('/'); + : [encodePart(this.getInputType()), encodePart(this.query)].join('/'); } - // TODO: We should stop generating this on the client and retrieve the actual ColumnInfo from the server generateColumn(displayColumn: string, targetSchema: string): QueryColumn { - const formattedQueryName = this.label ?? capitalizeFirstChar(this.query); + const label_ = this.label ?? capitalizeFirstChar(this.query); const parentColName = this.generateFieldKey(); // Issue 40233: SM app allows for two types of parents, sources and samples, and its confusing if both use @@ -130,12 +126,13 @@ export class EntityParentType extends Record({ } return new QueryColumn({ - caption: this.isAliquotParent ? QueryColumn.ALIQUOTED_FROM_CAPTION : formattedQueryName + captionSuffix, + caption: this.isAliquotParent ? QueryColumn.ALIQUOTED_FROM_CAPTION : label_ + captionSuffix, description: this.isAliquotParent ? 'The parent sample of the aliquot' - : 'Contains ' + formattedQueryName + ' parent entities.', + : 'Contains ' + label_ + ' parent entities.', fieldKeyArray: [parentColName], fieldKey: parentColName, + fieldKeyPath: parentColName, // Issue 52556 lookup: new QueryLookup({ displayColumn, isPublic: true, @@ -230,12 +227,12 @@ export class EntityIdCreationModel extends Record({ static revertParentInputSchema(inputColumn: QueryColumn): SchemaQuery { if (inputColumn.isExpInput()) { - const fieldKey = inputColumn.fieldKey.toLowerCase().split('/'); + const fieldKey = inputColumn.fieldKey.split('/'); if (fieldKey.length === 2) { let schemaName: string; - if (fieldKey[0] === QueryColumn.DATA_INPUTS.toLowerCase()) { + if (fieldKey[0] === QueryColumn.DATA_INPUTS) { schemaName = SCHEMAS.DATA_CLASSES.SCHEMA; - } else if (fieldKey[0] === QueryColumn.MATERIAL_INPUTS.toLowerCase()) { + } else if (fieldKey[0] === QueryColumn.MATERIAL_INPUTS) { schemaName = SCHEMAS.SAMPLE_SETS.SCHEMA; } else { throw new Error('Invalid inputColumn fieldKey. "' + fieldKey[0] + '"'); @@ -385,7 +382,11 @@ export class EntityIdCreationModel extends Record({ selected = this.entityParents.reduce((found, parentList) => { return ( found || - parentList.find(parent => parent.schema === sq.schemaName && parent.query === sq.queryName) + parentList.find( + parent => + parent.schema === sq.schemaName && + parent.query.toLowerCase() === sq.queryName.toLowerCase() + ) ); }, undefined); } else if (col.isAliquotParent() && this.creationType === EntityCreationType.Aliquots) { diff --git a/packages/components/src/internal/components/forms/input/FileInput.tsx b/packages/components/src/internal/components/forms/input/FileInput.tsx index 381c8ee794..a3374914d1 100644 --- a/packages/components/src/internal/components/forms/input/FileInput.tsx +++ b/packages/components/src/internal/components/forms/input/FileInput.tsx @@ -199,8 +199,7 @@ class FileInputImpl extends DisableableInput { } = this.props; const { data, file, isDisabled, isHover } = this.state; - const name = this.getInputName(); - const inputId = `${name}-fileUpload`; + const inputId = this.getInputName(); let body; if (file) { @@ -236,7 +235,7 @@ class FileInputImpl extends DisableableInput { disabled={this.state.isDisabled} type="file" className="file-upload__input" // This class makes the file input hidden - name={name} + name={inputId} id={inputId} multiple={false} onChange={this.onChange}