Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/components/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@labkey/components",
"version": "6.63.2",
"version": "6.64.0",
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
"sideEffects": false,
"files": [
Expand Down
5 changes: 5 additions & 0 deletions packages/components/releaseNotes/components.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# @labkey/components
Components, models, actions, and utility functions for LabKey applications and pages

### version 6.64.0
*Released*: 9 October 2025
- AssayDefinitionModel: add plateEnabled flag
- Fix circular dependency caused by IQueryColumn interface

### version 6.63.2
*Released*: 8 October 2025
- Issue 53324: LKSM: Custom Grid View Column Limit
Expand Down
26 changes: 16 additions & 10 deletions packages/components/src/internal/AssayDefinitionModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class AssayDefinitionModel extends ImmutableRecord({
importController: undefined,
links: Map<AssayLink, string>(),
name: undefined,
plateEnabled: undefined,
projectLevel: undefined,
protocolSchemaName: undefined,
requireCommentOnQCStateChange: undefined,
Expand All @@ -64,6 +65,7 @@ export class AssayDefinitionModel extends ImmutableRecord({
declare importController: string;
declare links: Map<AssayLink, string>;
declare name: string;
declare plateEnabled: boolean;
declare projectLevel: boolean;
declare protocolSchemaName: string;
declare requireCommentOnQCStateChange: boolean;
Expand Down Expand Up @@ -230,11 +232,18 @@ export class AssayDefinitionModel extends ImmutableRecord({
return this.getSampleColumns(domainType)[0];
}

private isWellLsidColumn(domain: AssayDomainTypes, col: QueryColumn): boolean {
return this.plateEnabled && domain === AssayDomainTypes.RESULT && col.fieldKey.toLowerCase() === 'welllsid';
}

/**
* returns the FieldKey string of the sample column relative from the assay Results table.
*/
sampleColumnFieldKey(sampleCol: ScopedSampleColumn): string {
if (sampleCol.domain === AssayDomainTypes.RESULT) {
// Note: The Results Domain will never have the Well column on it, only WellLsid and WellLocation, but this
// column is present when querying the data, so this does work when used to create filters on a grid.
if (this.isWellLsidColumn(sampleCol.domain, sampleCol.column)) return `Well/SampleId`;
return sampleCol.column.fieldKey;
} else if (sampleCol.domain === AssayDomainTypes.RUN) {
return `Run/${sampleCol.column.fieldKey}`;
Expand All @@ -248,7 +257,7 @@ export class AssayDefinitionModel extends ImmutableRecord({
* returns the FieldKey string of the sample columns relative from the assay Results table.
*/
getSampleColumnFieldKeys(domainType?: AssayDomainTypes): string[] {
return this.getSampleColumns(domainType).map(this.sampleColumnFieldKey);
return this.getSampleColumns(domainType).map(scopedCol => this.sampleColumnFieldKey(scopedCol));
}

getDomainColumns(type: AssayDomainTypes): ExtendedMap<string, QueryColumn> {
Expand All @@ -267,16 +276,13 @@ export class AssayDefinitionModel extends ImmutableRecord({
return this.getDomainColumns(type).filter(col => col.isFileInput).valueArray;
}

private getSampleColumnsByDomain(domainType: AssayDomainTypes): ScopedSampleColumn[] {
const columns: ScopedSampleColumn[] = [];
private getSampleColumnsByDomain(domain: AssayDomainTypes): ScopedSampleColumn[] {
const columns = this.getDomainByType(domain)
?.filter(column => column.isSampleLookup() || this.isWellLsidColumn(domain, column))
.map(column => ({ column, domain }))
.toArray();

this.getDomainByType(domainType)?.forEach(column => {
if (column.isSampleLookup()) {
columns.push({ column, domain: domainType });
}
});

return columns;
return columns ?? [];
}

isSampleColInResults(column: QueryColumn, domain: AssayDomainTypes): boolean {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/internal/ViewInfo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Filter } from '@labkey/api';
import { IQueryColumn } from '../public/QueryColumn';
import { IQueryColumn } from '../public/IQueryColumn';

import { QuerySort, QuerySortJson } from '../public/QuerySort';
import { QueryInfo } from '../public/QueryInfo';
Expand Down
77 changes: 77 additions & 0 deletions packages/components/src/public/IQueryColumn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Note: it is necessary to put IQueryColumn in its own file in order to get rid of circular dependencies between
// ViewInfo and QueryColumn via the schemas.ts

export interface IQueryColumn {
addToSystemView: boolean;
align: string;
// autoIncrement: boolean;
// calculated: boolean;
caption: string;
conceptSubtree: string;
conceptURI: string;
defaultValue: any;
derivationDataScope: string;
description: string;
dimension: boolean;
displayAsLookup: boolean;
// defaultScale: string;
displayField?: string;
displayFieldJsonType?: string;
displayFieldSqlType?: string;
// excludeFromShifting: boolean;
// ext: any;
facetingBehaviorType: string;
fieldKey: string;
fieldKeyArray: string[];
fieldKeyPath: string;
filterable: boolean;
format: string;
// friendlyType: string;
hasSortKey: boolean;
hidden: boolean;
inputType: string;
// isAutoIncrement: boolean; // DUPLICATE
// isHidden: boolean; // DUPLICATE
isKeyField: boolean;
// isMvEnabled: boolean;
// isNullable: boolean;
// isReadOnly: boolean;
// isSelectable: boolean; // DUPLICATE
// isUserEditable: boolean; // DUPLICATE
// isVersionField: boolean;
jsonType: string;
// keyField: boolean;
lookup: Record<string, any>;
measure: boolean;
multiValue: boolean;
// mvEnabled: boolean;
name: string;
nameExpression: string;
// nullable: boolean;
phiProtected: boolean;
protected: boolean;
rangeURI: string;
readOnly: boolean;
removeFromViewCustomization: boolean;
removeFromViews: boolean; // strips this column from all ViewInfo definitions
// recommendedVariable: boolean;
required: boolean;
scale: number;
selectable: boolean;
shortCaption: string;
shownInDetailsView: boolean;
shownInInsertView: boolean;
shownInLookupView: boolean;
shownInUpdateView: boolean;
sortable: boolean;
// versionField: boolean;
sorts: '+' | '-';
sourceOntology: string;
// sqlType: string;
tableCell: boolean;
type: string;
units: string;
userEditable: boolean;
validValues: string[];
width: number;
}
76 changes: 1 addition & 75 deletions packages/components/src/public/QueryColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { isAllSamplesSchema } from '../internal/components/samples/utils';
import { SAMPLES_WITH_TYPES_FILTER } from '../internal/components/samples/constants';

import { SchemaQuery } from './SchemaQuery';
import { IQueryColumn } from './IQueryColumn';

export enum Operation {
insert = 'insert',
Expand Down Expand Up @@ -113,81 +114,6 @@ const defaultQueryColumn = {
removeFromViews: false,
};

export interface IQueryColumn {
addToSystemView: boolean;
align: string;
// autoIncrement: boolean;
// calculated: boolean;
caption: string;
conceptSubtree: string;
conceptURI: string;
defaultValue: any;
derivationDataScope: string;
description: string;
dimension: boolean;
displayAsLookup: boolean;
// defaultScale: string;
displayField?: string;
displayFieldJsonType?: string;
displayFieldSqlType?: string;
// excludeFromShifting: boolean;
// ext: any;
facetingBehaviorType: string;
fieldKey: string;
fieldKeyArray: string[];
fieldKeyPath: string;
filterable: boolean;
format: string;
// friendlyType: string;
hasSortKey: boolean;
hidden: boolean;
inputType: string;
// isAutoIncrement: boolean; // DUPLICATE
// isHidden: boolean; // DUPLICATE
isKeyField: boolean;
// isMvEnabled: boolean;
// isNullable: boolean;
// isReadOnly: boolean;
// isSelectable: boolean; // DUPLICATE
// isUserEditable: boolean; // DUPLICATE
// isVersionField: boolean;
jsonType: string;
// keyField: boolean;
lookup: Record<string, any>;
measure: boolean;
multiValue: boolean;
// mvEnabled: boolean;
name: string;
nameExpression: string;
// nullable: boolean;
phiProtected: boolean;
protected: boolean;
rangeURI: string;
readOnly: boolean;
removeFromViewCustomization: boolean;
removeFromViews: boolean; // strips this column from all ViewInfo definitions
// recommendedVariable: boolean;
required: boolean;
scale: number;
selectable: boolean;
shortCaption: string;
shownInDetailsView: boolean;
shownInInsertView: boolean;
shownInLookupView: boolean;
shownInUpdateView: boolean;
sortable: boolean;
// versionField: boolean;
sorts: '+' | '-';
sourceOntology: string;
// sqlType: string;
tableCell: boolean;
type: string;
units: string;
userEditable: boolean;
validValues: string[];
width: number;
}

export class QueryColumn implements IQueryColumn {
declare align: string;
// declare autoIncrement: boolean;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/public/QueryModel/TabbedGridPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const GridTab: FC<GridTabProps> = memo(({ isActive, model, onSelect, pullRight,
</li>
);
});
GridTab.displayName = 'GridTab';

export interface TabbedGridPanelProps<T = {}> extends GridPanelProps<T> {
/**
Expand Down Expand Up @@ -326,3 +327,4 @@ export const TabbedGridPanel: FC<TabbedGridPanelProps & InjectedQueryModels> = m
</>
);
});
TabbedGridPanel.displayName = 'TabbedGridPanel';