From 2f7ab585290749b2d65b64dca751221e1a80df42 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 11:07:08 -0600 Subject: [PATCH 01/17] GitHub Issue 73: Field editor Advanced Settings to allow for non-unique constraint / index - update UI to allow for single field non-unique and unique constraints - update DomainField model to support nonUniqueConstraint in addition to uniqueConstraint --- .../components/releaseNotes/components.md | 6 ++ .../domainproperties/AdvancedSettings.tsx | 67 +++++++++++++++---- .../components/domainproperties/constants.ts | 1 + .../domainproperties/models.test.ts | 37 ++++++++-- .../components/domainproperties/models.tsx | 38 +++++++++-- 5 files changed, 126 insertions(+), 23 deletions(-) diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index 6e6ae577c2..c56be92979 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,6 +1,12 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages +### version TBD +*Released*: TBD +- GitHub Issue 73: Field editor Advanced Settings to allow for non-unique constraint / index + - update UI to allow for single field non-unique and unique constraints + - update DomainField model to support nonUniqueConstraint in addition to uniqueConstraint + ### version 7.7.0 *Released*: 29 December 2025 - Workflow Automation: Task action to filter samples for selected task diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx index 48ca9f30f7..14a9c5e81d 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx @@ -37,6 +37,7 @@ import { DOMAIN_FIELD_SHOWNININSERTVIEW, DOMAIN_FIELD_SHOWNINUPDATESVIEW, DOMAIN_FIELD_UNIQUECONSTRAINT, + DOMAIN_FIELD_NONUNIQUECONSTRAINT, DOMAIN_PHI_LEVELS, } from './constants'; @@ -74,6 +75,7 @@ interface AdvancedSettingsState { shownInInsertView?: boolean; shownInUpdateView?: boolean; uniqueConstraint?: boolean; + nonUniqueConstraint?: boolean; } export class AdvancedSettings extends React.PureComponent { @@ -117,6 +119,7 @@ export class AdvancedSettings extends React.PureComponent { + let value = getCheckedValue(evt); + const fieldName = getNameFromId(evt.target.id); + + if (fieldName === DOMAIN_FIELD_UNIQUECONSTRAINT) { + // only one of uniqueConstraint or nonUniqueConstraint can be true at a time, so we need to toggle + // the non-unique when the unique is changed + this.setState({ + uniqueConstraint: value, + nonUniqueConstraint: !value, + }); + } else if (fieldName === DOMAIN_FIELD_NONUNIQUECONSTRAINT && !value) { + // if non-unique is being unchecked, we need to also uncheck unique + this.setState({ + uniqueConstraint: false, + nonUniqueConstraint: false, + }); + } else { + this.setState({ + [fieldName]: value, + }); + } + }; + hasValidDomainId(): boolean { const { domainId } = this.props; return !(domainId === undefined || domainId === null || domainId === 0); @@ -364,10 +391,12 @@ export class AdvancedSettings extends React.PureComponent level.value === PHI) !== undefined; const disablePhiSelect = domainFormDisplayOptions.phiLevelDisabled || @@ -509,18 +538,32 @@ export class AdvancedSettings extends React.PureComponent )} {allowUniqueConstraintProperties && !field.isCalculatedField() && ( - - Require all values to be unique - -
Add a unique constraint via a database-level index for this field.
-
-
+ <> + + Add a single-field index / constraint for this field + +
Add a non-unique constraint via a database-level index for this field.
+
+
+ + Require all values to be unique + +
Add a unique constraint via a database-level index for this field.
+
+
+ )} ); diff --git a/packages/components/src/internal/components/domainproperties/constants.ts b/packages/components/src/internal/components/domainproperties/constants.ts index 7525f0dce1..2b654bbfae 100644 --- a/packages/components/src/internal/components/domainproperties/constants.ts +++ b/packages/components/src/internal/components/domainproperties/constants.ts @@ -40,6 +40,7 @@ export const DOMAIN_FIELD_HIDDEN = 'hidden'; export const DOMAIN_FIELD_MVENABLED = 'mvEnabled'; export const DOMAIN_FIELD_PHI = 'PHI'; export const DOMAIN_FIELD_UNIQUECONSTRAINT = 'uniqueConstraint'; +export const DOMAIN_FIELD_NONUNIQUECONSTRAINT = 'nonUniqueConstraint'; export const DOMAIN_FIELD_RECOMMENDEDVARIABLE = 'recommendedVariable'; export const DOMAIN_FIELD_SHOWNINDETAILSVIEW = 'shownInDetailsView'; export const DOMAIN_FIELD_SHOWNININSERTVIEW = 'shownInInsertView'; diff --git a/packages/components/src/internal/components/domainproperties/models.test.ts b/packages/components/src/internal/components/domainproperties/models.test.ts index 1e4adbe6e1..819fbe1314 100644 --- a/packages/components/src/internal/components/domainproperties/models.test.ts +++ b/packages/components/src/internal/components/domainproperties/models.test.ts @@ -825,17 +825,17 @@ describe('DomainDesign', () => { { columnNames: ['a', 'b', 'c'], unique: true }, { columnNames: ['a'], unique: true }, { columnNames: ['b'], unique: false }, - { columnNames: ['c'], unique: true }, + { columnNames: ['c'], unique: true }, // should be omitted since 'c' is not a field ], }); const ddJson = DomainDesign.serialize(dd); expect(ddJson.indices.length).toBe(3); expect(ddJson.indices[0].columnNames).toStrictEqual(['a', 'b', 'c']); expect(ddJson.indices[0].unique).toBe(true); - expect(ddJson.indices[1].columnNames).toStrictEqual(['b']); - expect(ddJson.indices[1].unique).toBe(false); - expect(ddJson.indices[2].columnNames).toStrictEqual(['a']); - expect(ddJson.indices[2].unique).toBe(true); + expect(ddJson.indices[1].columnNames).toStrictEqual(['a']); + expect(ddJson.indices[1].unique).toBe(true); + expect(ddJson.indices[2].columnNames).toStrictEqual(['b']); + expect(ddJson.indices[2].unique).toBe(false); }); }); @@ -1209,8 +1209,26 @@ describe('DomainField', () => { List.of('A', 'b', 'd') ); expect(fields.get(0).uniqueConstraint).toBe(true); // field a + expect(fields.get(0).nonUniqueConstraint).toBe(false); // field a + expect(fields.get(1).uniqueConstraint).toBe(true); // field b + expect(fields.get(1).nonUniqueConstraint).toBe(false); // field b + expect(fields.get(2).uniqueConstraint).toBe(false); // field c + expect(fields.get(2).nonUniqueConstraint).toBe(false); // field c + }); + + test('nonUniqueConstraintFieldNames in fromJS', () => { + const fields = DomainField.fromJS( + [{ name: 'a' } as IDomainField, { name: 'b' } as IDomainField, { name: 'c' } as IDomainField], + undefined, + List.of('A', 'b', 'd'), + List.of('c', 'd') + ); + expect(fields.get(0).uniqueConstraint).toBe(true); // field a + expect(fields.get(0).nonUniqueConstraint).toBe(false); // field a expect(fields.get(1).uniqueConstraint).toBe(true); // field b + expect(fields.get(1).nonUniqueConstraint).toBe(false); // field b expect(fields.get(2).uniqueConstraint).toBe(false); // field c + expect(fields.get(2).nonUniqueConstraint).toBe(true); // field c }); // TODO add other test cases for DomainField.serialize code @@ -1238,6 +1256,15 @@ describe('DomainIndex', () => { index = DomainIndex.fromJS([{ columnNames: ['_hashed_a', 'b'], unique: false } as IDomainIndex]).get(0); expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(false); }); + + test('isSingleFieldNonUniqueConstraint', () => { + let index = DomainIndex.fromJS([{ columnNames: ['a'], unique: false } as IDomainIndex]).get(0); + expect(index.isSingleFieldNonUniqueConstraint()).toBe(true); + index = DomainIndex.fromJS([{ columnNames: ['a'], unique: true } as IDomainIndex]).get(0); + expect(index.isSingleFieldNonUniqueConstraint()).toBe(false); + index = DomainIndex.fromJS([{ columnNames: ['a', 'b'], unique: false } as IDomainIndex]).get(0); + expect(index.isSingleFieldNonUniqueConstraint()).toBe(false); + }); }); describe('PropertyValidator', () => { diff --git a/packages/components/src/internal/components/domainproperties/models.tsx b/packages/components/src/internal/components/domainproperties/models.tsx index 50326689f3..6766ed4daf 100644 --- a/packages/components/src/internal/components/domainproperties/models.tsx +++ b/packages/components/src/internal/components/domainproperties/models.tsx @@ -238,6 +238,7 @@ export class DomainDesign let defaultValueOptions = List(); let mandatoryFieldNames = List(); let uniqueConstraintFieldNames = List(); + let nonUniqueConstraintFieldNames = List(); const domainException = DomainException.create(exception, exception ? exception.severity : undefined); @@ -262,10 +263,15 @@ export class DomainDesign index.columns.get(0).replace('_hashed_', '') ); }); + + nonUniqueConstraintFieldNames = indices + .filter(index => index.isSingleFieldNonUniqueConstraint()) + .map(index => index.columns.get(0)) + .toList(); } if (rawModel.fields) { - fields = DomainField.fromJS(rawModel.fields, mandatoryFieldNames, uniqueConstraintFieldNames); + fields = DomainField.fromJS(rawModel.fields, mandatoryFieldNames, uniqueConstraintFieldNames, nonUniqueConstraintFieldNames); } // allow calculated fields if the feature is enabled and the domain kind allows it, @@ -276,7 +282,8 @@ export class DomainDesign const calcFields = DomainField.fromJS( rawModel.calculatedFields, mandatoryFieldNames, - uniqueConstraintFieldNames + uniqueConstraintFieldNames, + nonUniqueConstraintFieldNames ); fields = fields.push(...calcFields.toArray()); } @@ -301,10 +308,14 @@ export class DomainDesign const json = dd.toJS(); // Issue 41677: allow for per-field unique constraints to be added via the field editor UI + // GitHub Issue 73: allow for per-field non-unique constraints to be added via the field editor UI json.indices = dd.indices - // filter out the single field unique indices, and keep the others + // filter out the single field indices, and keep the others .filter( - index => !index.isSingleFieldUniqueConstraint() && !index.isMSSQLHashedSingleFieldUniqueConstraint() + index => + !index.isSingleFieldUniqueConstraint() && + !index.isMSSQLHashedSingleFieldUniqueConstraint() && + !index.isSingleFieldNonUniqueConstraint() ) .map(index => DomainIndex.serialize(index)) .toArray(); @@ -314,6 +325,10 @@ export class DomainDesign json.indices.push( DomainIndex.serialize(new DomainIndex({ columns: List.of(field.name?.trim()), type: 'unique' })) ); + } else if (field.nonUniqueConstraint) { + json.indices.push( + DomainIndex.serialize(new DomainIndex({ columns: List.of(field.name?.trim()), type: 'nonunique' })) + ); } }); @@ -601,7 +616,11 @@ export class DomainIndex } isMSSQLHashedSingleFieldUniqueConstraint(): boolean { - return this.type === 'nonunique' && this.columns.size === 1 && this.columns.get(0).startsWith('_hashed_'); + return this.isSingleFieldNonUniqueConstraint() && this.columns.get(0).startsWith('_hashed_'); + } + + isSingleFieldNonUniqueConstraint(): boolean { + return this.type === 'nonunique' && this.columns.size === 1; } } @@ -912,6 +931,7 @@ export interface IDomainField { sourceOntology?: string; textChoiceValidator?: PropertyValidator; uniqueConstraint?: boolean; + nonUniqueConstraint?: boolean; updatedField: boolean; URL?: string; visible: boolean; @@ -982,6 +1002,7 @@ export class DomainField textChoiceValidator: undefined, recommendedVariable: false, uniqueConstraint: false, + nonUniqueConstraint: false, required: false, scale: MAX_TEXT_LENGTH, URL: undefined, @@ -1043,6 +1064,7 @@ export class DomainField declare textChoiceValidator?: PropertyValidator; declare recommendedVariable: boolean; declare uniqueConstraint: boolean; + declare nonUniqueConstraint: boolean; declare required?: boolean; declare scale?: number; declare scannable?: boolean; @@ -1145,14 +1167,17 @@ export class DomainField static fromJS( rawFields: IDomainField[], mandatoryFieldNames?: List, - uniqueConstraintFieldNames?: List + uniqueConstraintFieldNames?: List, + nonUniqueConstraintFieldNames?: List ): List { let fields = List(); const lowerUniqueConstraintFieldNames = uniqueConstraintFieldNames?.map(f => f.toLowerCase()).toArray(); + const lowerNonUniqueConstraintFieldNames = nonUniqueConstraintFieldNames?.map(f => f.toLowerCase()).toArray(); for (let i = 0; i < rawFields.length; i++) { const rawField = rawFields[i]; rawField.uniqueConstraint = lowerUniqueConstraintFieldNames?.indexOf(rawField.name?.toLowerCase()) > -1; + rawField.nonUniqueConstraint = lowerNonUniqueConstraintFieldNames?.indexOf(rawField.name?.toLowerCase()) > -1; fields = fields.push(DomainField.create(rawField, undefined, mandatoryFieldNames)); } @@ -1269,6 +1294,7 @@ export class DomainField delete json.selected; delete json.lookupIsValid; delete json.uniqueConstraint; + delete json.nonUniqueConstraint; return json; } From 928cdf81bf6bcc75dd1239513b49bd886e4c95b9 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 11:08:48 -0600 Subject: [PATCH 02/17] 7.7.1-fb-nonUniqueConst73.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 78d72b1d2d..fcf02c5556 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.0", + "version": "7.7.1-fb-nonUniqueConst73.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.0", + "version": "7.7.1-fb-nonUniqueConst73.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 56ab04dc9a..65d5ab2ffc 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.0", + "version": "7.7.1-fb-nonUniqueConst73.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From 6729b5148343c20aa56aa82fd9d324a4547b8ab2 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 14:51:02 -0600 Subject: [PATCH 03/17] change to select input for single-field index options (unique vs non-unique) --- .../components/releaseNotes/components.md | 2 +- .../AdvancedSettings.test.tsx | 15 ++- .../domainproperties/AdvancedSettings.tsx | 94 ++++++++++--------- .../components/domainproperties/constants.ts | 1 + 4 files changed, 63 insertions(+), 49 deletions(-) diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index c56be92979..cc551ffa6f 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -4,7 +4,7 @@ Components, models, actions, and utility functions for LabKey applications and p ### version TBD *Released*: TBD - GitHub Issue 73: Field editor Advanced Settings to allow for non-unique constraint / index - - update UI to allow for single field non-unique and unique constraints + - update UI to allow for single field non-unique and unique constraints via select dropdown - update DomainField model to support nonUniqueConstraint in addition to uniqueConstraint ### version 7.7.0 diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx index e5b576fe62..901e2b792d 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx @@ -7,6 +7,7 @@ import { createFormInputId } from './utils'; import { CALCULATED_CONCEPT_URI, DOMAIN_EDITABLE_DEFAULT, + DOMAIN_FIELD_CONSTRAINT, DOMAIN_FIELD_DEFAULT_VALUE_TYPE, DOMAIN_FIELD_DIMENSION, DOMAIN_FIELD_HIDDEN, @@ -128,9 +129,14 @@ describe('AdvancedSettings', () => { expect(recommendedVariable.getAttribute('checked')).toEqual(''); // Verify uniqueConstraint - id = createFormInputId(DOMAIN_FIELD_UNIQUECONSTRAINT, _domainIndex, _index); - const uniqueConstraint = document.querySelector('#' + id); - expect(uniqueConstraint.getAttribute('checked')).toEqual(''); + id = createFormInputId(DOMAIN_FIELD_CONSTRAINT, _domainIndex, _index); + const singleFieldIndex = document.querySelector('#' + id); + expect(singleFieldIndex.getAttribute('disabled')).toBeNull(); + let options = singleFieldIndex.querySelectorAll('option'); + expect(options).toHaveLength(3); + expect(options[0].textContent).toBe(''); + expect(options[1].textContent).toBe('Unique'); + expect(options[2].textContent).toBe('Non-Unique'); // Verify default type id = createFormInputId(DOMAIN_FIELD_DEFAULT_VALUE_TYPE, _domainIndex, _index); @@ -148,8 +154,7 @@ describe('AdvancedSettings', () => { id = createFormInputId(DOMAIN_FIELD_PHI, _domainIndex, _index); const phi = document.querySelector('#' + id); expect(phi.getAttribute('disabled')).toBeNull(); - - const options = phi.querySelectorAll('option'); + options = phi.querySelectorAll('option'); expect(options).toHaveLength(3); expect(options[0].textContent).toBe('Not PHI'); expect(options[1].textContent).toBe('Limited PHI'); diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx index 14a9c5e81d..03ea4e3ff5 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx @@ -39,6 +39,7 @@ import { DOMAIN_FIELD_UNIQUECONSTRAINT, DOMAIN_FIELD_NONUNIQUECONSTRAINT, DOMAIN_PHI_LEVELS, + DOMAIN_FIELD_CONSTRAINT, } from './constants'; import { DomainFieldLabel } from './DomainFieldLabel'; @@ -181,26 +182,23 @@ export class AdvancedSettings extends React.PureComponent { - let value = getCheckedValue(evt); - const fieldName = getNameFromId(evt.target.id); - - if (fieldName === DOMAIN_FIELD_UNIQUECONSTRAINT) { - // only one of uniqueConstraint or nonUniqueConstraint can be true at a time, so we need to toggle - // the non-unique when the unique is changed + handleSingleFieldIndexChange = evt => { + // only one of uniqueConstraint or nonUniqueConstraint can be true at a time + const value = evt.target.value; + if (value === DOMAIN_FIELD_UNIQUECONSTRAINT) { this.setState({ - uniqueConstraint: value, - nonUniqueConstraint: !value, + uniqueConstraint: true, + nonUniqueConstraint: false, }); - } else if (fieldName === DOMAIN_FIELD_NONUNIQUECONSTRAINT && !value) { - // if non-unique is being unchecked, we need to also uncheck unique + } else if (value === DOMAIN_FIELD_NONUNIQUECONSTRAINT) { this.setState({ uniqueConstraint: false, - nonUniqueConstraint: false, + nonUniqueConstraint: true, }); } else { this.setState({ - [fieldName]: value, + uniqueConstraint: false, + nonUniqueConstraint: false, }); } }; @@ -244,6 +242,16 @@ export class AdvancedSettings extends React.PureComponent { + return ( +
+

Add a single-field constraint via a database-level index for this field.

+

Unique: require all values to be unique

+

Non-Unique: index without requiring unique values

+
+ ); + }; + getDefaultTypeHelpText = () => { return (
@@ -396,7 +404,12 @@ export class AdvancedSettings extends React.PureComponent level.value === PHI) !== undefined; const disablePhiSelect = domainFormDisplayOptions.phiLevelDisabled || @@ -407,7 +420,7 @@ export class AdvancedSettings extends React.PureComponent
Miscellaneous Options
{!field.isCalculatedField() && ( -
+
@@ -435,6 +448,29 @@ export class AdvancedSettings extends React.PureComponent
)} + + {allowUniqueConstraintProperties && !field.isCalculatedField() && ( +
+
+ +
+
+ +
+
+
+ )} {field.dataType === DATETIME_TYPE && ( )} - {allowUniqueConstraintProperties && !field.isCalculatedField() && ( - <> - - Add a single-field index / constraint for this field - -
Add a non-unique constraint via a database-level index for this field.
-
-
- - Require all values to be unique - -
Add a unique constraint via a database-level index for this field.
-
-
- - )} ); }; diff --git a/packages/components/src/internal/components/domainproperties/constants.ts b/packages/components/src/internal/components/domainproperties/constants.ts index 2b654bbfae..d09610f560 100644 --- a/packages/components/src/internal/components/domainproperties/constants.ts +++ b/packages/components/src/internal/components/domainproperties/constants.ts @@ -39,6 +39,7 @@ export const DOMAIN_FIELD_DIMENSION = 'dimension'; export const DOMAIN_FIELD_HIDDEN = 'hidden'; export const DOMAIN_FIELD_MVENABLED = 'mvEnabled'; export const DOMAIN_FIELD_PHI = 'PHI'; +export const DOMAIN_FIELD_CONSTRAINT = 'singleFieldConstraint'; export const DOMAIN_FIELD_UNIQUECONSTRAINT = 'uniqueConstraint'; export const DOMAIN_FIELD_NONUNIQUECONSTRAINT = 'nonUniqueConstraint'; export const DOMAIN_FIELD_RECOMMENDEDVARIABLE = 'recommendedVariable'; From 3b95a81e6efcde99a2159efa457adc947072ae13 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 14:51:28 -0600 Subject: [PATCH 04/17] 7.7.1-fb-nonUniqueConst73.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 fcf02c5556..d0f5599df8 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.0", + "version": "7.7.1-fb-nonUniqueConst73.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.0", + "version": "7.7.1-fb-nonUniqueConst73.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 65d5ab2ffc..5bb9323756 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.0", + "version": "7.7.1-fb-nonUniqueConst73.1", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From dfa1fbcaccd99e750c1549238b11e1fe67f1f048 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 15:13:04 -0600 Subject: [PATCH 05/17] text updates per feedback --- .../components/domainproperties/AdvancedSettings.test.tsx | 2 +- .../internal/components/domainproperties/AdvancedSettings.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx index 901e2b792d..b99311ee5e 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx @@ -134,7 +134,7 @@ describe('AdvancedSettings', () => { expect(singleFieldIndex.getAttribute('disabled')).toBeNull(); let options = singleFieldIndex.querySelectorAll('option'); expect(options).toHaveLength(3); - expect(options[0].textContent).toBe(''); + expect(options[0].textContent).toBe('None'); expect(options[1].textContent).toBe('Unique'); expect(options[2].textContent).toBe('Non-Unique'); diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx index 03ea4e3ff5..23fe25615c 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx @@ -245,7 +245,7 @@ export class AdvancedSettings extends React.PureComponent { return (
-

Add a single-field constraint via a database-level index for this field.

+

Add a single-field database index for this field.

Unique: require all values to be unique

Non-Unique: index without requiring unique values

@@ -463,7 +463,7 @@ export class AdvancedSettings extends React.PureComponent - + From 0445c33163fe9412c0908277b5dc4d39826d56a9 Mon Sep 17 00:00:00 2001 From: cnathe Date: Mon, 29 Dec 2025 15:13:53 -0600 Subject: [PATCH 06/17] 7.7.1-fb-nonUniqueConst73.2 --- 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 d0f5599df8..fab7137607 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.1", + "version": "7.7.1-fb-nonUniqueConst73.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.1", + "version": "7.7.1-fb-nonUniqueConst73.2", "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 5bb9323756..cf68f5b49c 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.1", + "version": "7.7.1-fb-nonUniqueConst73.2", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From 6a6d5781f0330a60bc161770fde6919ef1495a34 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 07:51:55 -0600 Subject: [PATCH 07/17] 7.7.1-fb-nonUniqueConst73.3 --- 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 313278a3a9..ec7f0fc20b 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.1", + "version": "7.7.1-fb-nonUniqueConst73.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.1", + "version": "7.7.1-fb-nonUniqueConst73.3", "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 86bfb757f7..11ac927c3b 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.1", + "version": "7.7.1-fb-nonUniqueConst73.3", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From c53df40836b1552d5131bc3fc1d0cc9bb66f3e58 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 08:06:47 -0600 Subject: [PATCH 08/17] update select option wording to be more descriptive --- .../components/releaseNotes/components.md | 2 +- .../domainproperties/AdvancedSettings.tsx | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index a795760238..16dc06a20f 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -4,7 +4,7 @@ Components, models, actions, and utility functions for LabKey applications and p ### version TBD *Released*: TBD - GitHub Issue 73: Field editor Advanced Settings to allow for non-unique constraint / index - - update UI to allow for single field non-unique and unique constraints via select dropdown + - update UI to allow for single field non-unique index and unique constraint via select dropdown - update DomainField model to support nonUniqueConstraint in addition to uniqueConstraint ### version 7.7.1 diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx index 23fe25615c..c6f7be1264 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx @@ -246,8 +246,7 @@ export class AdvancedSettings extends React.PureComponent

Add a single-field database index for this field.

-

Unique: require all values to be unique

-

Non-Unique: index without requiring unique values

+

Optionally, also require all values to be unique for this field.

); }; @@ -421,7 +420,7 @@ export class AdvancedSettings extends React.PureComponentMiscellaneous Options
{!field.isCalculatedField() && (
-
+
@@ -445,14 +444,14 @@ export class AdvancedSettings extends React.PureComponent
-
+
)} {allowUniqueConstraintProperties && !field.isCalculatedField() && (
-
- +
+
-
+
)} {field.dataType === DATETIME_TYPE && ( From 08ce72d7690a103ab4270cb631d8dba77cabd8a5 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 08:08:08 -0600 Subject: [PATCH 09/17] jest test updates to match wording change --- .../components/domainproperties/AdvancedSettings.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx index b99311ee5e..a32c20ab08 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx @@ -134,9 +134,9 @@ describe('AdvancedSettings', () => { expect(singleFieldIndex.getAttribute('disabled')).toBeNull(); let options = singleFieldIndex.querySelectorAll('option'); expect(options).toHaveLength(3); - expect(options[0].textContent).toBe('None'); - expect(options[1].textContent).toBe('Unique'); - expect(options[2].textContent).toBe('Non-Unique'); + expect(options[0].textContent).toBe('No Index'); + expect(options[1].textContent).toBe('Index'); + expect(options[2].textContent).toBe('Index and require unique values'); // Verify default type id = createFormInputId(DOMAIN_FIELD_DEFAULT_VALUE_TYPE, _domainIndex, _index); From 4dc2adec1f15dace12cb5c15a0aba3bab739cb52 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 08:08:55 -0600 Subject: [PATCH 10/17] 7.7.1-fb-nonUniqueConst73.4 --- 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 ec7f0fc20b..6394626bf3 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.3", + "version": "7.7.1-fb-nonUniqueConst73.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.3", + "version": "7.7.1-fb-nonUniqueConst73.4", "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 11ac927c3b..ce96513f91 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.3", + "version": "7.7.1-fb-nonUniqueConst73.4", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From d3ff44c7b4e691b3780d0062c7a2b4b66bbe63af Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 16:24:24 -0600 Subject: [PATCH 11/17] fix for handling of SQL Server special case for unique constraint _hashed_ prefix --- .../domainproperties/models.test.ts | 13 ---------- .../components/domainproperties/models.tsx | 26 +++++++------------ 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/packages/components/src/internal/components/domainproperties/models.test.ts b/packages/components/src/internal/components/domainproperties/models.test.ts index 819fbe1314..28599ea769 100644 --- a/packages/components/src/internal/components/domainproperties/models.test.ts +++ b/packages/components/src/internal/components/domainproperties/models.test.ts @@ -1244,19 +1244,6 @@ describe('DomainIndex', () => { expect(index.isSingleFieldUniqueConstraint()).toBe(false); }); - test('isMSSQLHashedSingleFieldUniqueConstraint', () => { - let index = DomainIndex.fromJS([{ columnNames: ['a'], unique: true } as IDomainIndex]).get(0); - expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(false); - index = DomainIndex.fromJS([{ columnNames: ['a'], unique: false } as IDomainIndex]).get(0); - expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(false); - index = DomainIndex.fromJS([{ columnNames: ['_hashed_a'], unique: true } as IDomainIndex]).get(0); - expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(false); - index = DomainIndex.fromJS([{ columnNames: ['_hashed_a'], unique: false } as IDomainIndex]).get(0); - expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(true); - index = DomainIndex.fromJS([{ columnNames: ['_hashed_a', 'b'], unique: false } as IDomainIndex]).get(0); - expect(index.isMSSQLHashedSingleFieldUniqueConstraint()).toBe(false); - }); - test('isSingleFieldNonUniqueConstraint', () => { let index = DomainIndex.fromJS([{ columnNames: ['a'], unique: false } as IDomainIndex]).get(0); expect(index.isSingleFieldNonUniqueConstraint()).toBe(true); diff --git a/packages/components/src/internal/components/domainproperties/models.tsx b/packages/components/src/internal/components/domainproperties/models.tsx index 6766ed4daf..21a131b904 100644 --- a/packages/components/src/internal/components/domainproperties/models.tsx +++ b/packages/components/src/internal/components/domainproperties/models.tsx @@ -254,20 +254,19 @@ export class DomainDesign .map(index => index.columns.get(0)) .toList(); - // Hack: SQL server uses a hashed field for unique constraints on text columns, see - // BaseMicrosoftSqlServerDialect.addCreateIndexStatements (where it talks about HASHBYTES) indices - .filter(index => index.isMSSQLHashedSingleFieldUniqueConstraint()) + .filter(index => index.isSingleFieldNonUniqueConstraint()) .forEach(index => { - uniqueConstraintFieldNames = uniqueConstraintFieldNames.push( - index.columns.get(0).replace('_hashed_', '') - ); + // Hack: SQL server uses a hashed field for unique constraints on text columns, see + // BaseMicrosoftSqlServerDialect.addCreateIndexStatements (where it talks about HASHBYTES) + if (index.columns.get(0).startsWith('_hashed_')) { + uniqueConstraintFieldNames = uniqueConstraintFieldNames.push( + index.columns.get(0).replace('_hashed_', '') + ); + } else { + nonUniqueConstraintFieldNames = nonUniqueConstraintFieldNames.push(index.columns.get(0)); + } }); - - nonUniqueConstraintFieldNames = indices - .filter(index => index.isSingleFieldNonUniqueConstraint()) - .map(index => index.columns.get(0)) - .toList(); } if (rawModel.fields) { @@ -314,7 +313,6 @@ export class DomainDesign .filter( index => !index.isSingleFieldUniqueConstraint() && - !index.isMSSQLHashedSingleFieldUniqueConstraint() && !index.isSingleFieldNonUniqueConstraint() ) .map(index => DomainIndex.serialize(index)) @@ -615,10 +613,6 @@ export class DomainIndex return this.type === 'unique' && this.columns.size === 1; } - isMSSQLHashedSingleFieldUniqueConstraint(): boolean { - return this.isSingleFieldNonUniqueConstraint() && this.columns.get(0).startsWith('_hashed_'); - } - isSingleFieldNonUniqueConstraint(): boolean { return this.type === 'nonunique' && this.columns.size === 1; } From 6f889deb1b44295cd8a45e249d0694582675e71b Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 30 Dec 2025 16:25:27 -0600 Subject: [PATCH 12/17] 7.7.1-fb-nonUniqueConst73.5 --- 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 6394626bf3..166f4a24a1 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.4", + "version": "7.7.1-fb-nonUniqueConst73.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.4", + "version": "7.7.1-fb-nonUniqueConst73.5", "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 ce96513f91..ddd6e2ec9c 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.1-fb-nonUniqueConst73.4", + "version": "7.7.1-fb-nonUniqueConst73.5", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From e36e660d3ee6fd957f6412df99fe944e4d4e9da6 Mon Sep 17 00:00:00 2001 From: cnathe Date: Fri, 2 Jan 2026 10:07:18 -0600 Subject: [PATCH 13/17] 7.7.3-fb-nonUniqueConst73.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 08e20f7140..84c64f5c7a 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.7.3", + "version": "7.7.3-fb-nonUniqueConst73.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.7.3", + "version": "7.7.3-fb-nonUniqueConst73.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 ae0ca2eba2..6699715081 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.7.3", + "version": "7.7.3-fb-nonUniqueConst73.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From c1b10e925c66ccbf150cd0b1e86f5cff4320b6f3 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 6 Jan 2026 09:18:57 -0600 Subject: [PATCH 14/17] 7.8.1-fb-nonUniqueConst73.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 ac63174a57..3d5674505d 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.8.1", + "version": "7.8.1-fb-nonUniqueConst73.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.8.1", + "version": "7.8.1-fb-nonUniqueConst73.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 8add6202e4..c4b3434e6e 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.8.1", + "version": "7.8.1-fb-nonUniqueConst73.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From 3d5459f9b97483d62c3e9199028e6bc4d5d72a52 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 6 Jan 2026 14:30:25 -0600 Subject: [PATCH 15/17] 7.11.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 de99c7c40f..7610e79326 100644 --- a/packages/components/package-lock.json +++ b/packages/components/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/components", - "version": "7.10.0", + "version": "7.11.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/components", - "version": "7.10.0", + "version": "7.11.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 59a07417f8..84725424be 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/components", - "version": "7.10.0", + "version": "7.11.0", "description": "Components, models, actions, and utility functions for LabKey applications and pages", "sideEffects": false, "files": [ From 80c822dd74245267e3c82b493853d8a44bb1a18b Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 6 Jan 2026 14:31:01 -0600 Subject: [PATCH 16/17] Update release notes with version number and release date --- packages/components/releaseNotes/components.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/releaseNotes/components.md b/packages/components/releaseNotes/components.md index 4ecaa5f6e6..cedc332aa0 100644 --- a/packages/components/releaseNotes/components.md +++ b/packages/components/releaseNotes/components.md @@ -1,8 +1,8 @@ # @labkey/components Components, models, actions, and utility functions for LabKey applications and pages -### version TBD -*Released*: TBD +### version 7.11.0 +*Released*: 6 January 2026 - GitHub Issue 73: Field editor Advanced Settings to allow for non-unique constraint / index - update UI to allow for single field non-unique index and unique constraint via select dropdown - update DomainField model to support nonUniqueConstraint in addition to uniqueConstraint From 3149027c86e00d5289049029f11dbfef48853ea0 Mon Sep 17 00:00:00 2001 From: cnathe Date: Tue, 6 Jan 2026 14:31:21 -0600 Subject: [PATCH 17/17] npm run lint-branch-fix --- .../domainproperties/AdvancedSettings.tsx | 23 +++++++++++++------ .../components/domainproperties/models.tsx | 18 ++++++++------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx index c6f7be1264..b5c667c71d 100644 --- a/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx +++ b/packages/components/src/internal/components/domainproperties/AdvancedSettings.tsx @@ -25,21 +25,21 @@ import { DEFAULT_DOMAIN_FORM_DISPLAY_OPTIONS, DOMAIN_DEFAULT_TYPES, DOMAIN_EDITABLE_DEFAULT, + DOMAIN_FIELD_CONSTRAINT, DOMAIN_FIELD_DEFAULT_VALUE_TYPE, DOMAIN_FIELD_DIMENSION, DOMAIN_FIELD_EXCLUDE_FROM_SHIFTING, DOMAIN_FIELD_HIDDEN, DOMAIN_FIELD_MEASURE, DOMAIN_FIELD_MVENABLED, + DOMAIN_FIELD_NONUNIQUECONSTRAINT, DOMAIN_FIELD_PHI, DOMAIN_FIELD_RECOMMENDEDVARIABLE, DOMAIN_FIELD_SHOWNINDETAILSVIEW, DOMAIN_FIELD_SHOWNININSERTVIEW, DOMAIN_FIELD_SHOWNINUPDATESVIEW, DOMAIN_FIELD_UNIQUECONSTRAINT, - DOMAIN_FIELD_NONUNIQUECONSTRAINT, DOMAIN_PHI_LEVELS, - DOMAIN_FIELD_CONSTRAINT, } from './constants'; import { DomainFieldLabel } from './DomainFieldLabel'; @@ -69,6 +69,7 @@ interface AdvancedSettingsState { hidden?: boolean; measure?: boolean; mvEnabled?: boolean; + nonUniqueConstraint?: boolean; PHI?: string; phiLevels?: { label: string; value: string }[]; recommendedVariable?: boolean; @@ -76,7 +77,6 @@ interface AdvancedSettingsState { shownInInsertView?: boolean; shownInUpdateView?: boolean; uniqueConstraint?: boolean; - nonUniqueConstraint?: boolean; } export class AdvancedSettings extends React.PureComponent { @@ -451,7 +451,10 @@ export class AdvancedSettings extends React.PureComponent
- +
diff --git a/packages/components/src/internal/components/domainproperties/models.tsx b/packages/components/src/internal/components/domainproperties/models.tsx index 5e46ab67bd..2085714ca2 100644 --- a/packages/components/src/internal/components/domainproperties/models.tsx +++ b/packages/components/src/internal/components/domainproperties/models.tsx @@ -270,7 +270,12 @@ export class DomainDesign } if (rawModel.fields) { - fields = DomainField.fromJS(rawModel.fields, mandatoryFieldNames, uniqueConstraintFieldNames, nonUniqueConstraintFieldNames); + fields = DomainField.fromJS( + rawModel.fields, + mandatoryFieldNames, + uniqueConstraintFieldNames, + nonUniqueConstraintFieldNames + ); } // allow calculated fields if the feature is enabled and the domain kind allows it, @@ -310,11 +315,7 @@ export class DomainDesign // GitHub Issue 73: allow for per-field non-unique constraints to be added via the field editor UI json.indices = dd.indices // filter out the single field indices, and keep the others - .filter( - index => - !index.isSingleFieldUniqueConstraint() && - !index.isSingleFieldNonUniqueConstraint() - ) + .filter(index => !index.isSingleFieldUniqueConstraint() && !index.isSingleFieldNonUniqueConstraint()) .map(index => DomainIndex.serialize(index)) .toArray(); // add in the new set of single field unique indices @@ -912,6 +913,7 @@ export interface IDomainField { measure?: boolean; mvEnabled?: boolean; name: string; + nonUniqueConstraint?: boolean; original: Partial; PHI?: string; primaryKey?: boolean; @@ -932,7 +934,6 @@ export interface IDomainField { sourceOntology?: string; textChoiceValidator?: PropertyValidator; uniqueConstraint?: boolean; - nonUniqueConstraint?: boolean; updatedField: boolean; URL?: string; visible: boolean; @@ -1180,7 +1181,8 @@ export class DomainField for (let i = 0; i < rawFields.length; i++) { const rawField = rawFields[i]; rawField.uniqueConstraint = lowerUniqueConstraintFieldNames?.indexOf(rawField.name?.toLowerCase()) > -1; - rawField.nonUniqueConstraint = lowerNonUniqueConstraintFieldNames?.indexOf(rawField.name?.toLowerCase()) > -1; + rawField.nonUniqueConstraint = + lowerNonUniqueConstraintFieldNames?.indexOf(rawField.name?.toLowerCase()) > -1; fields = fields.push(DomainField.create(rawField, undefined, mandatoryFieldNames)); }