Skip to content

Commit b75e679

Browse files
authored
Merge changes from release25.11-SNAPSHOT through v6.68.3 (#1886)
### version 6.69.0 *Released*: 5 November 2025 - Merge from release25.11-SNAPSHOT to develop - includes changes from 6.68.2 #1878 - includes changes from 6.68.3 #1884
1 parent 73719ac commit b75e679

12 files changed

Lines changed: 631 additions & 81 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.68.1",
3+
"version": "6.69.0",
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# @labkey/components
22
Components, models, actions, and utility functions for LabKey applications and pages
33

4+
### version 6.69.0
5+
*Released*: 5 November 2025
6+
- Merge from release25.11-SNAPSHOT to develop
7+
- includes changes from 6.68.2 #1878
8+
- includes changes from 6.68.3 #1884
9+
10+
### version 6.68.3
11+
*Released*: 4 November 2025
12+
- Issue 53983: Sort fields by caption
13+
- Issue 53927: Adjust column view layout to wrap
14+
15+
### version 6.68.2
16+
*Released*: 3 November 2025
17+
- SVGChart: render curve fit statistics when available
18+
419
### version 6.68.1
520
*Released* 2 November 2025
621
- Issue 52063: Domain designer to handle lookup to a query with a pipe character

packages/components/src/internal/components/ColumnSelectionModal.test.tsx

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { wrapDraggable } from '../test/testHelpers';
1010

1111
import {
1212
ColumnChoice,
13-
ColumnChoiceProps,
1413
ColumnChoiceGroup,
1514
ColumnChoiceGroupProps,
15+
ColumnChoiceProps,
1616
ColumnInView,
1717
ColumnInViewProps,
1818
ColumnSelectionModal,
@@ -52,7 +52,7 @@ describe('ColumnSelectionModal', () => {
5252

5353
test('isInView', () => {
5454
render(<ColumnChoice {...defaultProps()} isInView />);
55-
expect(document.querySelector('.field-caption').textContent).toBe('Test Column');
55+
expect(document.querySelector('.field-caption')).toHaveTextContent('Test Column');
5656
expect(document.querySelectorAll('.fa-check')).toHaveLength(1);
5757
expect(document.querySelectorAll('.fa-plus')).toHaveLength(0);
5858
expect(document.querySelectorAll('.field-expand-icon')).toHaveLength(1);
@@ -62,7 +62,7 @@ describe('ColumnSelectionModal', () => {
6262

6363
test('not isInView', () => {
6464
render(<ColumnChoice {...defaultProps()} isInView={false} />);
65-
expect(document.querySelector('.field-caption').textContent).toBe('Test Column');
65+
expect(document.querySelector('.field-caption')).toHaveTextContent('Test Column');
6666
expect(document.querySelectorAll('.fa-check')).toHaveLength(0);
6767
expect(document.querySelectorAll('.fa-plus')).toHaveLength(1);
6868
expect(document.querySelectorAll('.field-expand-icon')).toHaveLength(1);
@@ -72,7 +72,7 @@ describe('ColumnSelectionModal', () => {
7272

7373
test('lookup, collapsed', () => {
7474
render(<ColumnChoice {...defaultProps()} column={QUERY_COL_LOOKUP} isInView={false} />);
75-
expect(document.querySelector('.field-caption').textContent).toBe('Test Column');
75+
expect(document.querySelector('.field-caption')).toHaveTextContent('Test Column');
7676
expect(document.querySelectorAll('.fa-check')).toHaveLength(0);
7777
expect(document.querySelectorAll('.fa-plus')).toHaveLength(1);
7878
expect(document.querySelectorAll('.field-expand-icon')).toHaveLength(3);
@@ -82,7 +82,7 @@ describe('ColumnSelectionModal', () => {
8282

8383
test('lookup, expanded', () => {
8484
render(<ColumnChoice {...defaultProps()} column={QUERY_COL_LOOKUP} isExpanded isInView={false} />);
85-
expect(document.querySelector('.field-caption').textContent).toBe('Test Column');
85+
expect(document.querySelector('.field-caption')).toHaveTextContent('Test Column');
8686
expect(document.querySelectorAll('.fa-check')).toHaveLength(0);
8787
expect(document.querySelectorAll('.fa-plus')).toHaveLength(1);
8888
expect(document.querySelectorAll('.field-expand-icon')).toHaveLength(3);
@@ -116,7 +116,7 @@ describe('ColumnSelectionModal', () => {
116116
}
117117

118118
function validate(column: QueryColumn, deleteDisabled: boolean): void {
119-
expect(document.querySelector('.field-caption span').textContent).toBe(column.caption);
119+
expect(document.querySelector('.field-caption span')).toHaveTextContent(column.caption);
120120
const removeIcon = document.querySelector('.fa-times');
121121
if (deleteDisabled) {
122122
expect(removeIcon).toBeFalsy();
@@ -184,7 +184,7 @@ describe('ColumnSelectionModal', () => {
184184
describe('FieldLabelDisplay', () => {
185185
test('not lookup', () => {
186186
render(<FieldLabelDisplay column={QUERY_COL} includeFieldKey />);
187-
expect(document.querySelector('.field-caption span').textContent).toBe(QUERY_COL.caption);
187+
expect(document.querySelector('.field-caption span')).toHaveTextContent(QUERY_COL.caption);
188188
expect(document.querySelectorAll('.overlay-trigger')).toHaveLength(1);
189189
expect(document.querySelectorAll('input')).toHaveLength(0);
190190
});
@@ -266,8 +266,8 @@ describe('ColumnSelectionModal', () => {
266266
<ColumnChoiceGroup
267267
{...defaultProps()}
268268
column={QUERY_COL_LOOKUP}
269-
expandedColumns={{ [QUERY_COL_LOOKUP.index]: new QueryInfo({}) }}
270269
columnsInView={[QUERY_COL_LOOKUP]}
270+
expandedColumns={{ [QUERY_COL_LOOKUP.index]: new QueryInfo({}) }}
271271
/>
272272
);
273273
validate(true, true);
@@ -279,8 +279,8 @@ describe('ColumnSelectionModal', () => {
279279
<ColumnChoiceGroup
280280
{...defaultProps()}
281281
column={QUERY_COL_LOOKUP}
282-
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
283282
columnsInView={[QUERY_COL_LOOKUP]}
283+
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
284284
/>
285285
);
286286
validate(true, true, true);
@@ -292,8 +292,8 @@ describe('ColumnSelectionModal', () => {
292292
<ColumnChoiceGroup
293293
{...defaultProps()}
294294
column={QUERY_COL_LOOKUP}
295-
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
296295
columnsInView={[QUERY_COL_LOOKUP, QUERY_COL]}
296+
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
297297
/>
298298
);
299299
validate(true, true, true);
@@ -321,8 +321,8 @@ describe('ColumnSelectionModal', () => {
321321
<ColumnChoiceGroup
322322
{...defaultProps()}
323323
column={QUERY_COL_LOOKUP}
324-
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
325324
columnsInView={[QUERY_COL_LOOKUP, colHidden]}
325+
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
326326
showAllColumns
327327
/>
328328
);
@@ -336,9 +336,9 @@ describe('ColumnSelectionModal', () => {
336336
<ColumnChoiceGroup
337337
{...defaultProps()}
338338
column={QUERY_COL_LOOKUP}
339+
columnsInView={[QUERY_COL_LOOKUP]}
339340
expandedColumnFilter={jest.fn().mockImplementation(c => !c.removeFromViews)}
340341
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
341-
columnsInView={[QUERY_COL_LOOKUP]}
342342
/>
343343
);
344344
validate(true, true);
@@ -376,15 +376,67 @@ describe('ColumnSelectionModal', () => {
376376
<ColumnChoiceGroup
377377
{...defaultProps()}
378378
column={QUERY_COL_LOOKUP}
379+
columnsInView={[QUERY_COL_LOOKUP]}
379380
expandedColumnFilter={jest.fn().mockImplementation(c => !c.isJunctionLookup())}
380381
expandedColumns={{ [QUERY_COL_LOOKUP.index]: queryInfo }}
381-
columnsInView={[QUERY_COL_LOOKUP]}
382382
showAllColumns
383383
/>
384384
);
385385
validate(true, true, true);
386386
expect(document.querySelectorAll('.list-group-item')).toHaveLength(2);
387387
});
388+
389+
// Issue 53983
390+
test('Expanded lookup child fields are sorted by caption', () => {
391+
const parent = new QueryColumn({
392+
caption: 'Parent',
393+
name: 'parent',
394+
fieldKey: 'parent',
395+
fieldKeyArray: ['parent'],
396+
fieldKeyPath: 'parent',
397+
selectable: true,
398+
lookup: new QueryLookup({}),
399+
});
400+
const childZ = new QueryColumn({
401+
caption: 'zeta',
402+
name: 'z',
403+
fieldKey: 'z',
404+
fieldKeyArray: ['z'],
405+
fieldKeyPath: 'parent/z',
406+
selectable: true,
407+
});
408+
const childA = new QueryColumn({
409+
caption: 'Alpha',
410+
name: 'a',
411+
fieldKey: 'a',
412+
fieldKeyArray: ['a'],
413+
fieldKeyPath: 'parent/a',
414+
selectable: true,
415+
});
416+
417+
const expandedInfo = new QueryInfo({
418+
columns: new ExtendedMap({
419+
[childZ.fieldKey]: childZ,
420+
[childA.fieldKey]: childA,
421+
}),
422+
});
423+
424+
render(
425+
<ColumnChoiceGroup
426+
{...defaultProps()}
427+
column={parent}
428+
expandedColumns={{ [parent.index]: expandedInfo }}
429+
showAllColumns
430+
/>
431+
);
432+
433+
// Expect list to contain parent followed by children sorted by caption: Alpha, zeta
434+
const items = Array.from(document.querySelectorAll('.list-group-item .field-caption')).map(el =>
435+
el.textContent.trim()
436+
);
437+
438+
expect(items).toEqual(['Parent', 'Alpha', 'zeta']);
439+
});
388440
});
389441

390442
describe('ColumnSelectionModal', () => {
@@ -404,8 +456,8 @@ describe('ColumnSelectionModal', () => {
404456
expect(titles).toHaveLength(2);
405457

406458
expect(document.querySelectorAll('.list-group-item')).toHaveLength(2);
407-
expect(titles[0].textContent).toContain('Available Fields');
408-
expect(titles[1].textContent).toContain('Selected Fields');
459+
expect(titles[0]).toHaveTextContent('Available Fields');
460+
expect(titles[1]).toHaveTextContent('Selected Fields');
409461
expect(document.querySelector('.field-modal__footer')).toBeFalsy();
410462
});
411463

@@ -432,5 +484,60 @@ describe('ColumnSelectionModal', () => {
432484
// verify useEffect initialization of selectedIndex, selectedColumns
433485
expect(document.querySelectorAll('.list-group-item.active')).toHaveLength(1);
434486
});
487+
488+
// Issue 53983
489+
test('Available Fields list is sorted by caption', () => {
490+
const colB = new QueryColumn({
491+
caption: 'b Beta',
492+
name: 'b',
493+
fieldKey: 'b',
494+
fieldKeyArray: ['b'],
495+
fieldKeyPath: 'b',
496+
selectable: true,
497+
});
498+
const colA = new QueryColumn({
499+
caption: 'A Alpha',
500+
name: 'a',
501+
fieldKey: 'a',
502+
fieldKeyArray: ['a'],
503+
fieldKeyPath: 'a',
504+
selectable: true,
505+
});
506+
const col10 = new QueryColumn({
507+
caption: 'Item 10',
508+
name: 'item10',
509+
fieldKey: 'item10',
510+
fieldKeyArray: ['item10'],
511+
fieldKeyPath: 'item10',
512+
selectable: true,
513+
});
514+
const col2 = new QueryColumn({
515+
caption: 'Item 2',
516+
name: 'item2',
517+
fieldKey: 'item2',
518+
fieldKeyArray: ['item2'],
519+
fieldKeyPath: 'item2',
520+
selectable: true,
521+
});
522+
523+
const queryInfo = new QueryInfo({
524+
columns: new ExtendedMap({
525+
[colB.fieldKey]: colB,
526+
[colA.fieldKey]: colA,
527+
[col10.fieldKey]: col10,
528+
[col2.fieldKey]: col2,
529+
}),
530+
});
531+
532+
render(<ColumnSelectionModal {...defaultProps()} queryInfo={queryInfo} />);
533+
534+
// Available Fields (left column)
535+
const availableFields = document.querySelector('.field-modal__col-content');
536+
const captions = [...availableFields.querySelectorAll('.list-group-item .field-caption')].map(
537+
el => el.textContent?.trim() ?? ''
538+
);
539+
540+
expect(captions).toEqual(['A Alpha', 'b Beta', 'Item 2', 'Item 10']);
541+
});
435542
});
436543
});

0 commit comments

Comments
 (0)