Skip to content

Commit 88b4442

Browse files
authored
Issue 53328: AssayDefinitionModel.hasLookup to only consider the first sample lookup column for assay import cases (#1859)
### version 6.62.8 *Released*: 3 October 2025 - Issue 53328: AssayDefinitionModel.hasLookup to only consider the first sample lookup column for assay import cases
1 parent ead1ad1 commit 88b4442

5 files changed

Lines changed: 37 additions & 11 deletions

File tree

packages/components/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@labkey/components",
3-
"version": "6.62.7",
3+
"version": "6.62.8",
44
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
55
"sideEffects": false,
66
"files": [

packages/components/releaseNotes/components.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# @labkey/components
22
Components, models, actions, and utility functions for LabKey applications and pages
33

4+
### version 6.62.8
5+
*Released*: 3 October 2025
6+
- Issue 53328: AssayDefinitionModel.hasLookup to only consider the first sample lookup column for assay import cases
7+
48
### version 6.62.7
59
*Released*: 29 September 2025
610
- Enumerate plate, plate set auditing events

packages/components/src/internal/AssayDefinitionModel.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,27 @@ describe('AssayDefinitionModel', () => {
3737
expect(sampleColumn.column.fieldKey).toBe('SampleID');
3838
});
3939

40-
test('hasLookup()', () => {
40+
test('hasLookup() with sample lookup', () => {
4141
const modelWithSampleId = AssayDefinitionModel.create(assayDefJSON);
4242
expect(modelWithSampleId.hasLookup(new SchemaQuery('samples', 'Samples'))).toBeTruthy();
43+
expect(modelWithSampleId.hasLookup(new SchemaQuery('samples', 'Samples'), true)).toBeTruthy();
44+
expect(modelWithSampleId.hasLookup(new SchemaQuery('samples', 'Samples'), false, true)).toBeTruthy();
4345
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Study'))).toBeTruthy();
46+
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Study'), true)).toBeTruthy();
47+
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Study'), false, true)).toBeFalsy();
4448
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Other'))).toBeFalsy();
49+
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Other'), true)).toBeFalsy();
50+
expect(modelWithSampleId.hasLookup(new SchemaQuery('study', 'Other'), false, true)).toBeFalsy();
51+
});
52+
53+
test('hasLookup() without sample lookup', () => {
54+
const modelWithout = AssayDefinitionModel.create(assayDefNoSampleIdJSON);
55+
expect(modelWithout.hasLookup(new SchemaQuery('samples', 'Samples'))).toBeFalsy();
56+
expect(modelWithout.hasLookup(new SchemaQuery('samples', 'Samples'), true)).toBeFalsy();
57+
expect(modelWithout.hasLookup(new SchemaQuery('samples', 'Samples'), false, true)).toBeFalsy();
58+
expect(modelWithout.hasLookup(new SchemaQuery('study', 'Study'))).toBeTruthy();
59+
expect(modelWithout.hasLookup(new SchemaQuery('study', 'Study'), true)).toBeTruthy();
60+
expect(modelWithout.hasLookup(new SchemaQuery('study', 'Study'), false, true)).toBeFalsy();
4561
});
4662

4763
test('getSampleColumnFieldKeys()', () => {

packages/components/src/internal/AssayDefinitionModel.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { fromJS, List, Map, Record as ImmutableRecord } from 'immutable';
1+
import { fromJS, Record as ImmutableRecord, List, Map } from 'immutable';
22
import { Filter } from '@labkey/api';
33

44
import { ExtendedMap } from '../public/ExtendedMap';
@@ -14,6 +14,7 @@ import { AppURL } from './url/AppURL';
1414
import { SCHEMAS } from './schemas';
1515
import { ASSAYS_KEY } from './app/constants';
1616
import { ComponentsAPIWrapper } from './APIWrapper';
17+
import { isAllSamplesSchema } from './components/samples/utils';
1718

1819
export enum AssayDomainTypes {
1920
BATCH = 'Batch',
@@ -125,7 +126,7 @@ export class AssayDefinitionModel extends ImmutableRecord({
125126
selectionKey?: string,
126127
filters?: Filter.IFilter[],
127128
containerPath?: string,
128-
params?: Record<string, string | number | boolean>
129+
params?: Record<string, boolean | number | string>
129130
): string {
130131
let url: string;
131132
// Note, will need to handle the re-import run case separately. Possibly introduce another URL via links
@@ -162,7 +163,7 @@ export class AssayDefinitionModel extends ImmutableRecord({
162163
return AppURL.create(ASSAYS_KEY, this.type, this.name, 'runs');
163164
}
164165

165-
hasLookup(targetSQ: SchemaQuery, isPicklist?: boolean): boolean {
166+
hasLookup(targetSQ: SchemaQuery, isPicklist?: boolean, forImport = false): boolean {
166167
const isSampleSet = targetSQ.hasSchema(SCHEMAS.SAMPLE_SETS.SCHEMA);
167168

168169
// 44339: the SourceSamples custom query is backed by exp.materials
@@ -173,13 +174,12 @@ export class AssayDefinitionModel extends ImmutableRecord({
173174
const findLookup = (col: QueryColumn): boolean => {
174175
if (col.isLookup()) {
175176
const lookupSQ = col.lookup.schemaQuery;
176-
const isMatch =
177-
targetSQ.isEqual(lookupSQ) ||
178-
(isTargetAllSamples && SCHEMAS.EXP_TABLES.MATERIALS.isEqual(lookupSQ));
177+
const isAllSamplesLookup = isAllSamplesSchema(lookupSQ);
178+
const isMatch = targetSQ.isEqual(lookupSQ) || (isTargetAllSamples && isAllSamplesLookup);
179179

180180
// 35881: If targetSQ is a Sample Set then allow targeting exp.materials table as well
181181
if (isSampleSet) {
182-
return isMatch || SCHEMAS.EXP_TABLES.MATERIALS.isEqual(lookupSQ);
182+
return isMatch || isAllSamplesLookup;
183183
}
184184

185185
return isMatch;
@@ -188,6 +188,12 @@ export class AssayDefinitionModel extends ImmutableRecord({
188188
return false;
189189
};
190190

191+
// Issue 53328: only consider the first sample lookup column here since it will be used on the assay import page
192+
if (forImport) {
193+
const sampleLookupCol = this.getSampleColumn();
194+
return sampleLookupCol ? findLookup(sampleLookupCol.column) : false;
195+
}
196+
191197
// Traditional for loop so we can short circuit.
192198
for (const k of Object.keys(AssayDomainTypes)) {
193199
const domainType = AssayDomainTypes[k];

0 commit comments

Comments
 (0)