mirror of
https://github.com/directus/directus.git
synced 2026-01-29 16:28:02 -05:00
Add actions
This commit is contained in:
@@ -11,9 +11,13 @@ export default defineInterface(({ i18n }) => ({
|
||||
{
|
||||
field: 'includeSeconds',
|
||||
name: i18n.t('include_seconds'),
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
default_value: false,
|
||||
system: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
},
|
||||
database: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -6,7 +6,8 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('many_to_one'),
|
||||
icon: 'arrow_right_alt',
|
||||
component: InterfaceManyToOne,
|
||||
types: ['string', 'text', 'integer', 'bigInteger'],
|
||||
types: ['uuid', 'string', 'text', 'integer', 'bigInteger'],
|
||||
relationship: 'm2o',
|
||||
options: [
|
||||
{
|
||||
field: 'template',
|
||||
|
||||
@@ -7,8 +7,9 @@ export type InterfaceConfig = {
|
||||
icon: string;
|
||||
name: string | VueI18n.TranslateResult;
|
||||
component: Component;
|
||||
options: Partial<Field>[] | Component;
|
||||
options: DeepPartial<Field>[] | Component;
|
||||
types: Type[];
|
||||
relationship?: null | 'm2o' | 'o2m' | 'm2m';
|
||||
hideLabel?: boolean;
|
||||
hideLoader?: boolean;
|
||||
};
|
||||
|
||||
@@ -26,9 +26,42 @@
|
||||
"duplicate_where_to": "Where would you like to duplicate this field to?",
|
||||
"editing_field": "Editing {field}",
|
||||
"within_collectoin": "within {collection}",
|
||||
|
||||
"schema_setup_title": "How should this field save to the database?",
|
||||
|
||||
"key": "Key",
|
||||
|
||||
"alias": "Alias",
|
||||
"bigInteger": "Big Integer",
|
||||
"boolean": "Boolean",
|
||||
"date": "Date",
|
||||
"datetime": "DateTime",
|
||||
"decimal": "Decimal",
|
||||
"float": "Float",
|
||||
"integer": "Integer",
|
||||
"json": "JSON",
|
||||
"string": "String",
|
||||
"text": "Text",
|
||||
"time": "Time",
|
||||
"timestamp": "Timestamp",
|
||||
"binary": "Binary",
|
||||
"uuid": "UUID",
|
||||
"unknown": "Unknown",
|
||||
|
||||
"include_seconds": "Include Seconds",
|
||||
|
||||
"add_note": "Add a helpful note for users...",
|
||||
|
||||
"default_value": "Default Value",
|
||||
"add_a_default_value": "Add a default value...",
|
||||
|
||||
"allow_null": "Allow NULL",
|
||||
"allow_null_label": "Can be set to \"NULL\"",
|
||||
|
||||
"interface_setup_title": "How will users view or interact with this field?",
|
||||
|
||||
"field_setup_title": "What type of field are you creating?",
|
||||
"relationship_setup_title": "What kind of relationship are you creating?",
|
||||
"interface_setup_title": "How will users view or interact with this field?",
|
||||
"display_setup_title": "How should this field’s value be displayed?",
|
||||
"schema_options_title": "All set! Below are some optional configuration options...",
|
||||
"creating_field": "Creating New Field",
|
||||
@@ -48,8 +81,6 @@
|
||||
"database_column_name": "Database Column Name",
|
||||
"translations": "Translations",
|
||||
"note": "Note",
|
||||
"add_helpful_note": "Enter a helpful comment for App users...",
|
||||
"default_value": "Default Value",
|
||||
"enter_a_value": "Enter a value...",
|
||||
"length": "Length",
|
||||
"required": "Required",
|
||||
@@ -151,7 +182,6 @@
|
||||
"interfaces": "Interfaces",
|
||||
"interface_count": "No Interfaces | One Interface | {count} Interfaces",
|
||||
|
||||
"datetime": "DateTime",
|
||||
"today": "Today",
|
||||
"yesterday": "Yesterday",
|
||||
|
||||
@@ -163,7 +193,6 @@
|
||||
"date-fns_date_short": "MMM d, u",
|
||||
"date-fns_date_short_no_year": "MMM d",
|
||||
"month": "Month",
|
||||
"date": "Date",
|
||||
"year": "Year",
|
||||
|
||||
"select_all": "Select All",
|
||||
@@ -225,7 +254,6 @@
|
||||
"primary_key_field": "Primary Key Field",
|
||||
"type": "Type",
|
||||
"number": "Number",
|
||||
"string": "String",
|
||||
"creating_new_collection": "Creating New Collection",
|
||||
"status": "Status",
|
||||
"sort": "Sort",
|
||||
@@ -660,7 +688,6 @@
|
||||
"activity_log": "Activity Log",
|
||||
"add_field_filter": "Add a field filter",
|
||||
"add_new": "Add New",
|
||||
"add_note": "Add a helpful note for users...",
|
||||
"additional_info": "Additional Info",
|
||||
"admin_email": "Admin Email",
|
||||
"admin_password": "Admin Password",
|
||||
@@ -1026,7 +1053,6 @@
|
||||
"spacing": "Spacing",
|
||||
"statuses": "Statuses",
|
||||
"template": "Template",
|
||||
"text": "Text",
|
||||
"translation": "Translation",
|
||||
"translated_field_name": "Translated field name...",
|
||||
"not_translated_in_language": "Not Translated in {language}",
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<div class="actions">
|
||||
<v-button secondary :to="`/settings/data-model/${collection}`">
|
||||
{{ $t('cancel') }}
|
||||
</v-button>
|
||||
<div class="spacer" />
|
||||
<v-button @click="previousTab" secondary :disabled="previousDisabled">
|
||||
{{ $t('previous') }}
|
||||
</v-button>
|
||||
<v-button v-if="currentTabIndex < tabs.length - 1" @click="nextTab" :disabled="nextDisabled">
|
||||
{{ $t('next') }}
|
||||
</v-button>
|
||||
<v-button v-else @click="$emit('save')" :loading="saving">
|
||||
{{ $t('save') }}
|
||||
</v-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, PropType } from '@vue/composition-api';
|
||||
import useSync from '@/composables/use-sync';
|
||||
|
||||
type Tab = {
|
||||
text: string;
|
||||
value: string;
|
||||
disabled: boolean;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
collection: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
current: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
tabs: {
|
||||
type: Array as PropType<Tab[]>,
|
||||
required: true,
|
||||
},
|
||||
saving: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const _currentTab = useSync(props, 'current', emit);
|
||||
|
||||
const currentTabIndex = computed(() => props.tabs.findIndex((tab) => tab.value === props.current[0]));
|
||||
|
||||
const previousDisabled = computed(() => {
|
||||
return currentTabIndex.value === 0;
|
||||
});
|
||||
|
||||
const nextDisabled = computed(() => {
|
||||
const nextTab = props.tabs[currentTabIndex.value + 1];
|
||||
|
||||
if (nextTab) {
|
||||
return nextTab.disabled;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return { _currentTab, previousDisabled, previousTab, nextDisabled, nextTab, currentTabIndex };
|
||||
|
||||
function previousTab() {
|
||||
const previousTab = props.tabs[currentTabIndex.value - 1];
|
||||
|
||||
if (previousTab) {
|
||||
_currentTab.value = [previousTab.value];
|
||||
}
|
||||
}
|
||||
|
||||
function nextTab() {
|
||||
const nextTab = props.tabs[currentTabIndex.value + 1];
|
||||
|
||||
if (nextTab) {
|
||||
_currentTab.value = [nextTab.value];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.actions {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.v-button:not(:last-child) {
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="type-title">{{ $t('display_setup_title') }}</h2>
|
||||
|
||||
<v-fancy-select class="select" :items="selectItems" v-model="_field.system.display" />
|
||||
|
||||
<template v-if="_field.system.display">
|
||||
<v-form
|
||||
v-if="
|
||||
selectedDisplay.options &&
|
||||
Array.isArray(selectedDisplay.options) &&
|
||||
selectedDisplay.options.length > 0
|
||||
"
|
||||
:fields="selectedDisplay.options"
|
||||
primary-key="+"
|
||||
v-model="_field.system.options"
|
||||
/>
|
||||
|
||||
<v-notice v-else>
|
||||
{{ $t('no_options_available') }}
|
||||
</v-notice>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import displays from '@/displays';
|
||||
import useSync from '@/composables/use-sync';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
fieldData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const _field = useSync(props, 'fieldData', emit);
|
||||
const availabledisplays = computed(() =>
|
||||
displays.filter((display) => {
|
||||
const matchesType = display.types.includes(props.fieldData.database.type);
|
||||
const matchesRelation = true;
|
||||
|
||||
// if (props.type === 'standard') {
|
||||
// matchesRelation = display.relationship === null || display.relationship === undefined;
|
||||
// } else if (props.type === 'file') {
|
||||
// matchesRelation = display.relationship === 'm2o';
|
||||
// } else if (props.type === 'files') {
|
||||
// matchesRelation = display.relationship === 'm2m';
|
||||
// } else {
|
||||
// matchesRelation = display.relationship === props.type;
|
||||
// }
|
||||
|
||||
return matchesType && matchesRelation;
|
||||
})
|
||||
);
|
||||
|
||||
const selectItems = computed(() =>
|
||||
availabledisplays.value.map((display) => ({
|
||||
text: display.name,
|
||||
value: display.id,
|
||||
icon: display.icon,
|
||||
}))
|
||||
);
|
||||
|
||||
const selectedDisplay = computed(() => {
|
||||
return displays.find((display) => display.id === _field.value.system.display);
|
||||
});
|
||||
|
||||
return { _field, selectItems, selectedDisplay };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.type-title,
|
||||
.select {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="type-title">{{ $t('interface_setup_title') }}</h2>
|
||||
|
||||
<v-fancy-select class="select" :items="selectItems" v-model="_field.system.interface" />
|
||||
|
||||
<template v-if="_field.system.interface">
|
||||
<v-form
|
||||
v-if="
|
||||
selectedInterface.options &&
|
||||
Array.isArray(selectedInterface.options) &&
|
||||
selectedInterface.options.length > 0
|
||||
"
|
||||
:fields="selectedInterface.options"
|
||||
primary-key="+"
|
||||
v-model="_field.system.options"
|
||||
/>
|
||||
|
||||
<v-notice v-else>
|
||||
{{ $t('no_options_available') }}
|
||||
</v-notice>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import interfaces from '@/interfaces';
|
||||
import useSync from '@/composables/use-sync';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
fieldData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const _field = useSync(props, 'fieldData', emit);
|
||||
const availableInterfaces = computed(() =>
|
||||
interfaces.filter((inter) => {
|
||||
const matchesType = inter.types.includes(props.fieldData.database.type);
|
||||
let matchesRelation = false;
|
||||
|
||||
if (props.type === 'standard') {
|
||||
matchesRelation = inter.relationship === null || inter.relationship === undefined;
|
||||
} else if (props.type === 'file') {
|
||||
matchesRelation = inter.relationship === 'm2o';
|
||||
} else if (props.type === 'files') {
|
||||
matchesRelation = inter.relationship === 'm2m';
|
||||
} else {
|
||||
matchesRelation = inter.relationship === props.type;
|
||||
}
|
||||
|
||||
return matchesType && matchesRelation;
|
||||
})
|
||||
);
|
||||
|
||||
const selectItems = computed(() =>
|
||||
availableInterfaces.value.map((inter) => ({
|
||||
text: inter.name,
|
||||
value: inter.id,
|
||||
icon: inter.icon,
|
||||
}))
|
||||
);
|
||||
|
||||
const selectedInterface = computed(() => {
|
||||
return interfaces.find((inter) => inter.id === _field.value.system.interface);
|
||||
});
|
||||
|
||||
return { _field, selectItems, selectedInterface };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.type-title,
|
||||
.select {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div>Relationship</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
|
||||
export default defineComponent({});
|
||||
</script>
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="type-title">{{ $t('schema_setup_title') }}</h2>
|
||||
|
||||
<div class="form">
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('key') }}</div>
|
||||
<v-input autofocus class="monospace" v-model="_field.field" db-safe />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('type') }}</div>
|
||||
<v-select :value="_field.database.type" @input="setType" :items="typesWithLabels" />
|
||||
</div>
|
||||
|
||||
<div class="field full">
|
||||
<div class="label type-label">{{ $t('note') }}</div>
|
||||
<v-input v-model="_field.database.comment" :placeholder="$t('add_note')" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('default_value') }}</div>
|
||||
<v-input
|
||||
class="monospace"
|
||||
v-model="_field.database.default_value"
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('length') }}</div>
|
||||
<v-input v-model="_field.database.max_length" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('allow_null') }}</div>
|
||||
<v-checkbox v-model="_field.database.is_nullable" :label="$t('allow_null_label')" block />
|
||||
</div>
|
||||
|
||||
<!--
|
||||
@todo add unique when the API supports it
|
||||
|
||||
<div class="field">
|
||||
<div class="label type-label">{{ $t('unique') }}</div>
|
||||
<v-input v-model="_field.database.unique" />
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import useSync from '@/composables/use-sync';
|
||||
import { types, Type } from '@/stores/fields/types';
|
||||
import i18n from '@/lang';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
fieldData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const _field = useSync(props, 'fieldData', emit);
|
||||
|
||||
const typesWithLabels = computed(() =>
|
||||
types
|
||||
.filter((type) => {
|
||||
// Remove alias and unknown, as those aren't real column types you can use
|
||||
return ['alias', 'unknown'].includes(type) === false;
|
||||
})
|
||||
.map((type) => {
|
||||
return {
|
||||
value: type,
|
||||
text: i18n.t(type),
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return { _field, typesWithLabels, setType };
|
||||
|
||||
function setType(value: Type) {
|
||||
if (value === 'uuid') {
|
||||
_field.value.system.special = 'uuid';
|
||||
} else {
|
||||
_field.value.system.special = null;
|
||||
}
|
||||
|
||||
// We'll reset the interface/display as they most likely won't work for the newly selected
|
||||
// type
|
||||
_field.value.system.interface = null;
|
||||
_field.value.system.options = null;
|
||||
_field.value.system.display = null;
|
||||
_field.value.system.display_options = null;
|
||||
|
||||
_field.value.database.type = value;
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.type-title {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: grid;
|
||||
grid-gap: 32px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.full {
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.monospace {
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<v-tabs vertical v-model="_currentTab">
|
||||
<v-tab v-for="tab in tabs" :key="tab.value" :value="tab.value" :disabled="tab.disabled">
|
||||
{{ tab.text }}
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import useSync from '@/composables/use-sync';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
tabs: {
|
||||
type: Array as PropType<string[]>,
|
||||
required: true,
|
||||
},
|
||||
current: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: 'schema',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'standard',
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const _currentTab = useSync(props, 'current', emit);
|
||||
|
||||
return { _currentTab };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -1,14 +1,40 @@
|
||||
<template>
|
||||
<v-modal :active="active" title="Test">
|
||||
{{ field }} {{ type }}
|
||||
<router-link to="/settings/data-model/customers">Back</router-link>
|
||||
<v-modal :active="active" title="Test" persistent>
|
||||
<template #sidebar>
|
||||
<setup-tabs :current.sync="currentTab" :tabs="tabs" :type="type" />
|
||||
</template>
|
||||
|
||||
<setup-schema v-if="currentTab[0] === 'schema'" :field-data.sync="fieldData" :type="type" />
|
||||
<setup-relationship v-if="currentTab[0] === 'relationship'" :field-data.sync="fieldData" :type="type" />
|
||||
<setup-interface v-if="currentTab[0] === 'interface'" :field-data.sync="fieldData" :type="type" />
|
||||
<setup-display v-if="currentTab[0] === 'display'" :field-data.sync="fieldData" :type="type" />
|
||||
|
||||
<template #footer>
|
||||
<setup-actions :collection="collection" :current.sync="currentTab" :tabs="tabs" />
|
||||
</template>
|
||||
</v-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from '@vue/composition-api';
|
||||
import { defineComponent, onMounted, ref, computed, reactive, PropType } from '@vue/composition-api';
|
||||
import SetupTabs from './components/tabs.vue';
|
||||
import SetupActions from './components/actions.vue';
|
||||
import SetupSchema from './components/schema.vue';
|
||||
import SetupRelationship from './components/relationship.vue';
|
||||
import SetupInterface from './components/interface.vue';
|
||||
import SetupDisplay from './components/display.vue';
|
||||
import { i18n } from '@/lang';
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SetupTabs,
|
||||
SetupActions,
|
||||
SetupSchema,
|
||||
SetupRelationship,
|
||||
SetupInterface,
|
||||
SetupDisplay,
|
||||
},
|
||||
props: {
|
||||
collection: {
|
||||
type: String,
|
||||
@@ -19,23 +45,74 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
type: String as PropType<'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m'>,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
setup(props) {
|
||||
const active = ref(false);
|
||||
|
||||
const fieldData = reactive({
|
||||
collection: props.collection,
|
||||
field: null,
|
||||
database: {
|
||||
type: null,
|
||||
default_value: null,
|
||||
max_length: null,
|
||||
is_nullable: true,
|
||||
comment: '',
|
||||
},
|
||||
system: {
|
||||
hidden: false,
|
||||
interface: null,
|
||||
options: null,
|
||||
display: null,
|
||||
display_options: null,
|
||||
readonly: false,
|
||||
special: null,
|
||||
},
|
||||
});
|
||||
|
||||
// This makes sure we still see the enter animation
|
||||
onMounted(() => {
|
||||
active.value = true;
|
||||
});
|
||||
|
||||
return { active };
|
||||
const tabs = computed(() => {
|
||||
return [
|
||||
{
|
||||
text: i18n.t('schema'),
|
||||
value: 'schema',
|
||||
disabled: false,
|
||||
},
|
||||
// {
|
||||
// text: i18n.t('relationship'),
|
||||
// value: 'relationship',
|
||||
// },
|
||||
{
|
||||
text: i18n.t('interface'),
|
||||
value: 'interface',
|
||||
disabled: interfaceDisabled(),
|
||||
},
|
||||
{
|
||||
text: i18n.t('display'),
|
||||
value: 'display',
|
||||
disabled: displayDisabled(),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const currentTab = ref(['schema']);
|
||||
|
||||
return { active, tabs, currentTab, fieldData };
|
||||
|
||||
function interfaceDisabled() {
|
||||
return isEmpty(fieldData.field) || isEmpty(fieldData.database.type);
|
||||
}
|
||||
|
||||
function displayDisabled() {
|
||||
return isEmpty(fieldData.field) || isEmpty(fieldData.database.type);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -24,6 +24,7 @@ export type Type =
|
||||
| 'json'
|
||||
| 'uuid'
|
||||
| 'binary'
|
||||
| 'uuid'
|
||||
| 'unknown';
|
||||
|
||||
export const types: Type[] = [
|
||||
@@ -41,6 +42,7 @@ export const types: Type[] = [
|
||||
'time',
|
||||
'timestamp',
|
||||
'binary',
|
||||
'uuid',
|
||||
'unknown',
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user