Ask for value when changing nullable to not-nullable (#5400)

* Add ContainsNullValues exception abstraction

* Add dialog for null values when disabling non-null

Fixes #2934

* Add translation for CONTAINS_NULL_VALUE error

* Make dialog title translated
This commit is contained in:
Rijk van Zanten
2021-04-30 15:27:18 -04:00
committed by GitHub
parent c62d30b816
commit f3574deae0
10 changed files with 171 additions and 9 deletions

View File

@@ -91,6 +91,7 @@ no_access: No Access
use_custom: Use Custom
nullable: Nullable
allow_null_value: Allow NULL value
enter_value_to_replace_nulls: Please enter a new value to replace any NULLs currently within this field.
field_standard: Standard
field_presentation: Presentation & Aliases
field_file: Single File
@@ -408,6 +409,7 @@ errors:
ROUTE_NOT_FOUND: Not found
RECORD_NOT_UNIQUE: Duplicate value detected
USER_SUSPENDED: User Suspended
CONTAINS_NULL_VALUES: Field contains null values
UNKNOWN: Unexpected Error
value_hashed: Value Securely Hashed
bookmark_name: Bookmark name...

View File

@@ -96,6 +96,21 @@
@cancel="cancelField"
/>
</template>
<v-dialog v-model="nullValuesDialog" @esc="nullValuesDialog = false">
<v-card>
<v-card-title>{{ $t('enter_value_to_replace_nulls') }}</v-card-title>
<v-card-text>
<v-input placeholder="NULL" v-model="nullValueOverride" />
</v-card-text>
<v-card-actions>
<v-button secondary @click="nullValuesDialog = false">{{ $t('cancel') }}</v-button>
<v-button :disabled="nullValueOverride === null" @click="saveNullOverride" :loading="nullOverrideSaving">
{{ $t('save') }}
</v-button>
</v-card-actions>
</v-card>
</v-dialog>
</v-drawer>
</template>
@@ -161,6 +176,8 @@ export default defineComponent({
const { collection } = toRefs(props);
const { info: collectionInfo } = useCollection(collection);
const { nullValueOverride, nullValuesDialog, nullOverrideSaving, saveNullOverride } = useContainsNull();
const existingField = computed(() => {
if (props.field === '+') return null;
@@ -207,6 +224,10 @@ export default defineComponent({
translationsManual,
currentTabInfo,
title,
nullValuesDialog,
nullValueOverride,
nullOverrideSaving,
saveNullOverride,
};
function useTabs() {
@@ -400,7 +421,12 @@ export default defineComponent({
router.push(`/settings/data-model/${props.collection}`);
clearLocalStore();
} catch (err) {
unexpectedError(err);
if (err?.response?.data?.errors?.[0]?.extensions?.code === 'CONTAINS_NULL_VALUES') {
nullValueOverride.value = state.fieldData?.schema?.default_value || null;
nullValuesDialog.value = true;
} else {
unexpectedError(err);
}
} finally {
saving.value = false;
}
@@ -410,6 +436,49 @@ export default defineComponent({
router.push(`/settings/data-model/${props.collection}`);
clearLocalStore();
}
/**
* In case you're setting allow null to false and you have null values already stored, we need
* to override those null values with a new value before you can try saving again
*/
function useContainsNull() {
const nullValuesDialog = ref(false);
const nullValueOverride = ref();
const nullOverrideSaving = ref(false);
return { nullValueOverride, nullValuesDialog, nullOverrideSaving, saveNullOverride };
async function saveNullOverride() {
nullOverrideSaving.value = true;
try {
const endpoint = props.collection.startsWith('directus_')
? `/${props.collection.substring(9)}`
: `/items/${props.collection}`;
await api.patch(endpoint, {
query: {
filter: {
[props.field]: {
_null: true,
},
},
limit: -1,
},
data: {
[props.field]: nullValueOverride.value,
},
});
nullValuesDialog.value = false;
return saveField();
} catch (err) {
unexpectedError(err);
} finally {
nullOverrideSaving.value = false;
}
}
}
},
});
</script>