diff --git a/client/web/compose/src/components/ModuleFields/Configurator/Record.vue b/client/web/compose/src/components/ModuleFields/Configurator/Record.vue
index 7d24fb2e5..81c062817 100644
--- a/client/web/compose/src/components/ModuleFields/Configurator/Record.vue
+++ b/client/web/compose/src/components/ModuleFields/Configurator/Record.vue
@@ -77,7 +77,17 @@
v-model="f.options.selectType"
:options="selectOptions"
stacked
+ @change="onUpdateIsUniqueMultiValue"
/>
+
+ {{ $t('kind.select.allow-duplicates') }}
+
@@ -203,5 +213,13 @@ export default {
this.f.options.selectType = 'default'
},
},
+
+ methods: {
+ onUpdateIsUniqueMultiValue () {
+ if (this.f.options.selectType === 'multiple') {
+ this.f.options.isUniqueMultiValue = true
+ }
+ },
+ },
}
diff --git a/client/web/compose/src/components/ModuleFields/Configurator/Select.vue b/client/web/compose/src/components/ModuleFields/Configurator/Select.vue
index 0d1d737c5..4b78a058c 100644
--- a/client/web/compose/src/components/ModuleFields/Configurator/Select.vue
+++ b/client/web/compose/src/components/ModuleFields/Configurator/Select.vue
@@ -83,7 +83,17 @@
v-model="f.options.selectType"
:options="selectOptions"
stacked
+ @change="onUpdateIsUniqueMultiValue"
/>
+
+ {{ $t('kind.select.allow-duplicates') }}
+
@@ -157,6 +167,12 @@ export default {
this.newOption = { value: undefined, text: undefined, new: true }
}
},
+
+ onUpdateIsUniqueMultiValue () {
+ if (this.f.options.selectType === 'multiple') {
+ this.f.options.isUniqueMultiValue = true
+ }
+ },
},
}
diff --git a/client/web/compose/src/components/ModuleFields/Configurator/User.vue b/client/web/compose/src/components/ModuleFields/Configurator/User.vue
index 5833d68d9..cf0649a96 100644
--- a/client/web/compose/src/components/ModuleFields/Configurator/User.vue
+++ b/client/web/compose/src/components/ModuleFields/Configurator/User.vue
@@ -35,7 +35,17 @@
v-model="f.options.selectType"
:options="selectOptions"
stacked
+ @change="onUpdateIsUniqueMultiValue"
/>
+
+ {{ $t('kind.select.allow-duplicates') }}
+
@@ -76,6 +86,12 @@ export default {
getOptionKey ({ roleID }) {
return roleID
},
+
+ onUpdateIsUniqueMultiValue () {
+ if (this.f.options.selectType === 'multiple') {
+ this.f.options.isUniqueMultiValue = true
+ }
+ },
},
}
diff --git a/client/web/compose/src/components/ModuleFields/Editor/Record.vue b/client/web/compose/src/components/ModuleFields/Editor/Record.vue
index 63c939528..c76708243 100644
--- a/client/web/compose/src/components/ModuleFields/Editor/Record.vue
+++ b/client/web/compose/src/components/ModuleFields/Editor/Record.vue
@@ -308,7 +308,7 @@ export default {
if (value !== crtValue) {
if (value) {
if (index !== undefined) {
- this.value[index] = value
+ this.value.splice(index, 1, value)
} else {
this.value = value
}
@@ -330,7 +330,9 @@ export default {
return {
value: r.recordID,
label: this.processing ? '' : this.recordValues[r.recordID] || r.recordID,
- selectable: this.field.isMulti ? !(this.value || []).includes(r.recordID) : this.value !== r.recordID,
+ selectable: this.field.isMulti && !this.field.options.isUniqueMultiValue
+ ? this.value !== r.recordID
+ : !(this.value || []).includes(r.recordID),
}
},
@@ -495,10 +497,6 @@ export default {
}
},
- onOpen () {
- // this.loadLatest()
- },
-
goToPage (next = true) {
this.filter.pageCursor = next ? this.filter.nextPage : this.filter.prevPage
},
diff --git a/client/web/compose/src/components/ModuleFields/Editor/Select.vue b/client/web/compose/src/components/ModuleFields/Editor/Select.vue
index 2c9d52534..838f16f0b 100644
--- a/client/web/compose/src/components/ModuleFields/Editor/Select.vue
+++ b/client/web/compose/src/components/ModuleFields/Editor/Select.vue
@@ -109,7 +109,9 @@ export default {
computed: {
selectOptions () {
return this.field.options.options.map(o => {
- const disabled = o.value && this.field.isMulti ? (this.value || []).includes(o.value) : this.value === o.value
+ const disabled = o.value && this.field.isMulti && !this.field.options.isUniqueMultiValue
+ ? this.value === o.value
+ : (this.value || []).includes(o.value)
return { ...o, disabled }
}).filter(({ value = '' }) => value)
},
diff --git a/client/web/compose/src/components/ModuleFields/Editor/User.vue b/client/web/compose/src/components/ModuleFields/Editor/User.vue
index 111ad7ef4..53783b279 100644
--- a/client/web/compose/src/components/ModuleFields/Editor/User.vue
+++ b/client/web/compose/src/components/ModuleFields/Editor/User.vue
@@ -194,7 +194,12 @@ export default {
options () {
return this.users.map(u => {
- return { ...u, selectable: this.field.isMulti ? !(this.value || []).includes(u.userID) : this.value !== u.userID }
+ return {
+ ...u,
+ selectable: this.field.isMulti && !this.field.options.isUniqueMultiValue
+ ? this.value !== u.userID
+ : !(this.value || []).includes(u.userID),
+ }
})
},
diff --git a/lib/js/src/compose/types/module-field/record.ts b/lib/js/src/compose/types/module-field/record.ts
index 13117b225..7f5f7be81 100644
--- a/lib/js/src/compose/types/module-field/record.ts
+++ b/lib/js/src/compose/types/module-field/record.ts
@@ -12,6 +12,7 @@ interface RecordOptions extends Options {
queryFields: Array;
selectType: string;
multiDelimiter: string;
+ isUniqueMultiValue: boolean;
prefilter?: string;
}
@@ -23,6 +24,7 @@ const defaults = (): Readonly => Object.freeze({
queryFields: [],
selectType: '',
multiDelimiter: '\n',
+ isUniqueMultiValue: false,
prefilter: undefined,
})
@@ -42,6 +44,7 @@ export class ModuleFieldRecord extends ModuleField {
Apply(this.options, o, CortezaID, 'moduleID')
Apply(this.options, o, String, 'labelField', 'recordLabelField', 'selectType', 'multiDelimiter', 'prefilter')
+ Apply(this.options, o, Boolean, 'isUniqueMultiValue')
Apply(this.options, o, (o) => {
if (!o) {
return []
diff --git a/lib/js/src/compose/types/module-field/select.ts b/lib/js/src/compose/types/module-field/select.ts
index b94b80e62..a1facd0bc 100644
--- a/lib/js/src/compose/types/module-field/select.ts
+++ b/lib/js/src/compose/types/module-field/select.ts
@@ -10,6 +10,7 @@ interface SelectOptions extends Options {
options: Array;
selectType: string;
multiDelimiter: string;
+ isUniqueMultiValue: boolean;
}
const defaults = (): Readonly => Object.freeze({
@@ -17,6 +18,7 @@ const defaults = (): Readonly => Object.freeze({
options: [],
selectType: 'default',
multiDelimiter: '\n',
+ isUniqueMultiValue: false,
})
export class ModuleFieldSelect extends ModuleField {
@@ -34,6 +36,7 @@ export class ModuleFieldSelect extends ModuleField {
super.applyOptions(o)
Apply(this.options, o, String, 'selectType', 'multiDelimiter')
+ Apply(this.options, o, Boolean, 'isUniqueMultiValue')
if (o.options) {
let opt: Array<{ value: string; text: string }> = []
diff --git a/lib/js/src/compose/types/module-field/user.ts b/lib/js/src/compose/types/module-field/user.ts
index 6b4c97701..8e8a0bd75 100644
--- a/lib/js/src/compose/types/module-field/user.ts
+++ b/lib/js/src/compose/types/module-field/user.ts
@@ -11,6 +11,7 @@ interface UserOptions extends Options {
presetWithAuthenticated: boolean;
selectType: string;
multiDelimiter: string;
+ isUniqueMultiValue: boolean;
}
const defaults = (): Readonly => Object.freeze({
@@ -19,6 +20,7 @@ const defaults = (): Readonly => Object.freeze({
presetWithAuthenticated: false,
selectType: 'default',
multiDelimiter: '\n',
+ isUniqueMultiValue: false,
})
export class ModuleFieldUser extends ModuleField {
@@ -35,7 +37,7 @@ export class ModuleFieldUser extends ModuleField {
if (!o) return
super.applyOptions(o)
- Apply(this.options, o, Boolean, 'presetWithAuthenticated')
+ Apply(this.options, o, Boolean, 'presetWithAuthenticated', 'isUniqueMultiValue')
Apply(this.options, o, String, 'selectType', 'multiDelimiter')
Apply(this.options, o, (o) => {
if (!o) {
diff --git a/locale/en/corteza-webapp-compose/field.yaml b/locale/en/corteza-webapp-compose/field.yaml
index 952143d6c..6c65e0e91 100644
--- a/locale/en/corteza-webapp-compose/field.yaml
+++ b/locale/en/corteza-webapp-compose/field.yaml
@@ -107,6 +107,7 @@ kind:
prefilterLabel: Prefilter records
prefilterPlaceholder: field1 = 1 AND field2 = 232
select:
+ allow-duplicates: Allow duplicates
label: Select
optionAdd: Add
optionLabelPlaceholder: Label