mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Implement unique constraint support (#4467)
* Allow creating unique fields * Allow removing unique constriant * Show unique constraint error as validation error in app
This commit is contained in:
@@ -54,7 +54,7 @@
|
||||
<small class="note" v-if="field.meta && field.meta.note" v-html="marked(field.meta.note)" />
|
||||
|
||||
<small class="validation-error" v-if="validationError">
|
||||
{{ $t(`validationError.${validationError.type}`, validationError) }}
|
||||
{{ validationMessage }}
|
||||
</small>
|
||||
</div>
|
||||
</template>
|
||||
@@ -69,6 +69,7 @@ import FormFieldInterface from './form-field-interface.vue';
|
||||
import { ValidationError } from './types';
|
||||
import { getJSType } from '@/utils/get-js-type';
|
||||
import { isEqual } from 'lodash';
|
||||
import { i18n } from '@/lang';
|
||||
|
||||
export default defineComponent({
|
||||
components: { FormFieldLabel, FormFieldMenu, FormFieldInterface },
|
||||
@@ -133,7 +134,15 @@ export default defineComponent({
|
||||
|
||||
const { showRaw, rawValue } = useRaw();
|
||||
|
||||
return { isDisabled, marked, _value, emitValue, showRaw, rawValue };
|
||||
const validationMessage = computed(() => {
|
||||
if (props.validationError.code === 'RECORD_NOT_UNIQUE') {
|
||||
return i18n.t('validationError.unique');
|
||||
} else {
|
||||
return i18n.t(`validationError.${props.validationError.type}`, props.validationError);
|
||||
}
|
||||
});
|
||||
|
||||
return { isDisabled, marked, _value, emitValue, showRaw, rawValue, validationMessage };
|
||||
|
||||
function emitValue(value: any) {
|
||||
if (
|
||||
|
||||
@@ -9,6 +9,7 @@ export type FormField = DeepPartial<Field> & {
|
||||
};
|
||||
|
||||
export type ValidationError = {
|
||||
code: string;
|
||||
field: string;
|
||||
type: FilterOperator;
|
||||
valid?: number | string | (number | string)[];
|
||||
|
||||
@@ -110,14 +110,16 @@ export function useItem(collection: Ref<string>, primaryKey: Ref<string | number
|
||||
return response.data.data;
|
||||
} catch (err) {
|
||||
if (err?.response?.data?.errors) {
|
||||
const validationTypes = ['FAILED_VALIDATION', 'RECORD_NOT_UNIQUE'];
|
||||
|
||||
validationErrors.value = err.response.data.errors
|
||||
.filter((err: APIError) => err?.extensions?.code === 'FAILED_VALIDATION')
|
||||
.filter((err: APIError) => validationTypes.includes(err?.extensions?.code))
|
||||
.map((err: APIError) => {
|
||||
return err.extensions;
|
||||
});
|
||||
|
||||
const otherErrors = err.response.data.errors.filter(
|
||||
(err: APIError) => err?.extensions?.code !== 'FAILED_VALIDATION'
|
||||
(err: APIError) => validationTypes.includes(err?.extensions?.code) === false
|
||||
);
|
||||
|
||||
if (otherErrors.length > 0) {
|
||||
|
||||
@@ -82,6 +82,7 @@ validationError:
|
||||
null: Value has to be null
|
||||
nnull: Value can't be null
|
||||
required: Value is required
|
||||
unique: Value has to be unique
|
||||
all_access: All Access
|
||||
no_access: No Access
|
||||
use_custom: Use Custom
|
||||
@@ -390,6 +391,7 @@ errors:
|
||||
ITEM_LIMIT_REACHED: Item limit reached
|
||||
ITEM_NOT_FOUND: Item not found
|
||||
ROUTE_NOT_FOUND: Not found
|
||||
RECORD_NOT_UNIQUE: Duplicate value detected
|
||||
UNKNOWN: Unexpected Error
|
||||
value_hashed: Value Securely Hashed
|
||||
bookmark_name: Bookmark name...
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<div class="form">
|
||||
<div class="field">
|
||||
<div class="label type-label">
|
||||
@@ -139,6 +138,16 @@
|
||||
block
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field half-right" v-if="fieldData.schema">
|
||||
<div class="label type-label">{{ $t('unique') }}</div>
|
||||
<v-checkbox
|
||||
:input-value="fieldData.schema.is_unique"
|
||||
@change="fieldData.schema.is_unique = $event"
|
||||
:label="$t('value_unique')"
|
||||
block
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -43,6 +43,7 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
|
||||
default_value: undefined,
|
||||
max_length: undefined,
|
||||
is_nullable: true,
|
||||
is_unique: false,
|
||||
numeric_precision: null,
|
||||
numeric_scale: null,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user