From 33647f998230d8e11e42ddb5873f9f7ab3675c6e Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Sat, 7 Feb 2026 15:47:30 -0800 Subject: [PATCH 1/7] QuerySort: be explicit in request sort direction --- packages/components/src/public/QuerySort.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/public/QuerySort.ts b/packages/components/src/public/QuerySort.ts index 2ad0e1150b..950aefabfd 100644 --- a/packages/components/src/public/QuerySort.ts +++ b/packages/components/src/public/QuerySort.ts @@ -13,6 +13,6 @@ export class QuerySort implements QuerySortJson { toRequestString(): string { const { dir, fieldKey } = this; - return dir === '-' ? '-' + fieldKey : fieldKey; + return (dir === '-' ? '-' : '+') + fieldKey; } } From 8e784083949014e30de45ed3ad50ab3306be5df9 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Sat, 7 Feb 2026 15:47:42 -0800 Subject: [PATCH 2/7] 7.16.1-fb-sort-plus-442.0 --- packages/components/package-lock.json | 4 ++-- packages/components/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/package-lock.json b/packages/components/package-lock.json index 2c61aa4abf..b1e1f6a4bd 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.16.0", + "version": "7.16.1-fb-sort-plus-442.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.16.0", + "version": "7.16.1-fb-sort-plus-442.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 5cbd32fb2e..1cd83ecd26 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.16.0", + "version": "7.16.1-fb-sort-plus-442.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From da25f931b6502a7a0dc608d60991ed7491a11123 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Sat, 7 Feb 2026 15:48:30 -0800 Subject: [PATCH 3/7] Update test --- packages/components/src/public/QueryModel/QueryModel.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/public/QueryModel/QueryModel.test.ts b/packages/components/src/public/QueryModel/QueryModel.test.ts index e6c827646b..996246116e 100644 --- a/packages/components/src/public/QueryModel/QueryModel.test.ts +++ b/packages/components/src/public/QueryModel/QueryModel.test.ts @@ -140,7 +140,7 @@ describe('QueryModel', () => { let model = new QueryModel({ schemaQuery: SCHEMA_QUERY, sorts }); expect(() => model.sortString).toThrow('Cannot construct sort string, no QueryInfo available'); model = model.mutate({ queryInfo: QUERY_INFO }); - expect(model.sortString).toEqual('-RowId,Data'); + expect(model.sortString).toEqual('-RowId,+Data'); }); test('Columns', () => { From ef90c7955f449e21333373478d84bfad062c8af9 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Sun, 8 Feb 2026 10:06:32 -0800 Subject: [PATCH 4/7] QuerySort: always specify "dir" --- .../components/src/internal/renderers.tsx | 26 +++++++++--------- packages/components/src/public/QueryColumn.ts | 3 ++- .../src/public/QueryModel/GridPanel.tsx | 11 ++++---- .../src/public/QueryModel/QueryModel.ts | 12 ++------- packages/components/src/public/QuerySort.ts | 27 ++++++++++++++----- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/packages/components/src/internal/renderers.tsx b/packages/components/src/internal/renderers.tsx index 091713a66c..2aa40d0064 100644 --- a/packages/components/src/internal/renderers.tsx +++ b/packages/components/src/internal/renderers.tsx @@ -47,6 +47,7 @@ import { usePortalRef } from './hooks'; import { MenuDivider, MenuItem } from './dropdowns'; import { LabelOverlay } from './components/forms/LabelOverlay'; import { DOMAIN_FIELD } from './components/forms/DomainFieldHelpTipContents'; +import { SORT_ASC, SORT_DESC } from '../public/QuerySort'; export function isFilterColumnNameMatch(filter: Filter.IFilter, col: QueryColumn): boolean { return filter.getColumnName() === col.name || filter.getColumnName() === col.resolveFieldKey(); @@ -108,11 +109,11 @@ export const EditableColumnTitle: FC = memo(props => { return ( ); } @@ -318,8 +319,8 @@ const HeaderCellDropdownMenu: FC = memo(props => { )} Hide Column @@ -397,18 +398,19 @@ export const HeaderCellDropdown: FC = memo(props => { const colQuerySortDir = model?.sorts?.find(sort => sort.fieldKey === queryColumn.resolveFieldKey())?.dir ?? view?.sorts?.find(sort => sort.fieldKey === queryColumn.resolveFieldKey())?.dir; - const isSortAsc = queryColumn.sorts === '+' || colQuerySortDir === '+' || colQuerySortDir === ''; - const isSortDesc = queryColumn.sorts === '-' || colQuerySortDir === '-'; + const sortDir = queryColumn.sorts || colQuerySortDir; + const isSortAsc = sortDir === SORT_ASC; + const isSortDesc = sortDir === SORT_DESC; return (
{!editingTitle && colFilters?.length > 0 && ( @@ -426,10 +428,10 @@ export const HeaderCellDropdown: FC = memo(props => { {!editingTitle && column.helpTipRenderer && ( - + )}
@@ -445,8 +447,8 @@ export const HeaderCellDropdown: FC = memo(props => { isSortAsc={isSortAsc} isSortDesc={isSortDesc} model={model} - open={open} onEditTitleClicked={editTitle} + open={open} queryColumn={queryColumn} setOpen={setOpen} /> @@ -476,8 +478,8 @@ export const HeaderSelectionCell: FC = memo(props => { return ( extends PureComponent, State> { this.setState({ showFilterModalFieldKey: undefined }); }; - sortColumn = (column: QueryColumn, direction?: string): void => { + sortColumn = (column: QueryColumn, direction?: SortDirection): void => { const fieldKey = column.resolveFieldKey(); // resolveFieldKey because of Issue 34627 if (direction) { - const dir = direction === '+' ? '' : '-'; // Sort Action only uses '-' and '' - const sort = new QuerySort({ fieldKey, dir }); + const sort = new QuerySort({ dir: direction, fieldKey }); this.handleSortChange({ type: ChangeType.add }, sort); } else { const actionIndex = this.state.actionValues.findIndex( diff --git a/packages/components/src/public/QueryModel/QueryModel.ts b/packages/components/src/public/QueryModel/QueryModel.ts index b9afb8b221..a8e6808a71 100644 --- a/packages/components/src/public/QueryModel/QueryModel.ts +++ b/packages/components/src/public/QueryModel/QueryModel.ts @@ -59,16 +59,8 @@ function offsetFromString(rowsPerPage: number, pageStr: string): number { return offset >= 0 ? offset : 0; } -export function querySortFromString(sortStr: string): QuerySort { - if (sortStr.startsWith('-')) { - return new QuerySort({ dir: '-', fieldKey: sortStr.slice(1) }); - } else { - return new QuerySort({ fieldKey: sortStr }); - } -} - function querySortsFromString(sortsStr: string): QuerySort[] { - return sortsStr?.split(',').map(querySortFromString); + return sortsStr?.split(',').map(QuerySort.fromString); } function searchFiltersFromString(searchStr: string): Filter.IFilter[] { @@ -1281,7 +1273,7 @@ export function getSettingsFromLocalStorage(id: string, containerPath: string): const filterArray = savedSettings.filterArray?.map(f => Filter.create(f.columnName, f.value, Filter.getFilterTypeForURLSuffix(f.type)) ); - const sorts = savedSettings.sorts?.map(s => querySortFromString(s)); + const sorts = savedSettings.sorts?.map(QuerySort.fromString); return { filterArray: filterArray ?? [], diff --git a/packages/components/src/public/QuerySort.ts b/packages/components/src/public/QuerySort.ts index 950aefabfd..897a38bdc9 100644 --- a/packages/components/src/public/QuerySort.ts +++ b/packages/components/src/public/QuerySort.ts @@ -1,18 +1,33 @@ +export const SORT_ASC = '+'; +export const SORT_DESC = '-'; + +export type SortDirection = typeof SORT_ASC | typeof SORT_DESC; + export interface QuerySortJson { - dir: string; + dir?: SortDirection; fieldKey: string; } export class QuerySort implements QuerySortJson { - declare dir: string; - declare fieldKey: string; + public dir?: SortDirection; + public fieldKey: string; + + static fromString(sortStr: string): QuerySort { + if (sortStr.startsWith(SORT_DESC)) { + return new QuerySort({ dir: SORT_DESC, fieldKey: sortStr.slice(1) }); + } else if (sortStr.startsWith(SORT_ASC)) { + return new QuerySort({ dir: SORT_ASC, fieldKey: sortStr.slice(1) }); + } + + return new QuerySort({ fieldKey: sortStr }); + } constructor(props: Partial) { - Object.assign(this, { dir: '' }, props); + this.dir = props.dir === SORT_DESC ? SORT_DESC : SORT_ASC; + this.fieldKey = props.fieldKey; } toRequestString(): string { - const { dir, fieldKey } = this; - return (dir === '-' ? '-' : '+') + fieldKey; + return `${this.dir}${this.fieldKey}`; } } From dbbf9a36f855f3cdbf08c96d8d1bfbe892fd174e Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Sun, 8 Feb 2026 10:06:42 -0800 Subject: [PATCH 5/7] 7.16.1-fb-sort-plus-442.1 --- packages/components/package-lock.json | 4 ++-- packages/components/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/package-lock.json b/packages/components/package-lock.json index b1e1f6a4bd..9b8e6587b0 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.0", + "version": "7.16.1-fb-sort-plus-442.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.0", + "version": "7.16.1-fb-sort-plus-442.1", "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 1cd83ecd26..a8b868da97 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.0", + "version": "7.16.1-fb-sort-plus-442.1", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From 5dcbbd40caac54d0655c019b83fd96cee371f485 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Wed, 11 Feb 2026 08:53:03 -0800 Subject: [PATCH 6/7] Prepare release notes --- packages/components/releaseNotes/components.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index 01a4c29d42..d26204dc06 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,6 +1,10 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages +### version 7.16.1 +*Released*: 11 February 2026 +- Query: sort columns where name starts with '+' + ### version 7.16.0 *Released*: 5 February 2026 - File import warnings for cross type sample import case From 6de492474f1e91729bce68380f75f579f47f8b3a Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Wed, 11 Feb 2026 08:53:30 -0800 Subject: [PATCH 7/7] 7.16.1 --- packages/components/package-lock.json | 4 ++-- packages/components/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/package-lock.json b/packages/components/package-lock.json index 9b8e6587b0..664aae4422 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.1", + "version": "7.16.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.1", + "version": "7.16.1", "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 a8b868da97..cefed355fc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.16.1-fb-sort-plus-442.1", + "version": "7.16.1", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [