mirror of
https://github.com/directus/directus.git
synced 2026-02-15 06:45:23 -05:00
Fix type errors
This commit is contained in:
@@ -9,11 +9,11 @@
|
||||
|
||||
<component
|
||||
v-if="interfaceExists"
|
||||
:is="`interface-${field.interface}`"
|
||||
v-bind="field.options"
|
||||
:is="`interface-${field.system.interface}`"
|
||||
v-bind="field.system.options"
|
||||
:disabled="disabled"
|
||||
:value="value === undefined ? field.default_value : value"
|
||||
:width="field.width"
|
||||
:value="value === undefined ? field.database.default_value : value"
|
||||
:width="field.system.width"
|
||||
:type="field.type"
|
||||
:collection="field.collection"
|
||||
:field="field.field"
|
||||
@@ -66,7 +66,7 @@ export default defineComponent({
|
||||
},
|
||||
setup(props) {
|
||||
const interfaceExists = computed(() => {
|
||||
return !!interfaces.find((inter) => inter.id === props.field.interface);
|
||||
return !!interfaces.find((inter) => inter.id === props.field.system.interface);
|
||||
});
|
||||
|
||||
return { interfaceExists };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="field" :key="field.field" :class="field.width">
|
||||
<div class="field" :key="field.field" :class="field.system.width">
|
||||
<v-menu
|
||||
v-if="field.hideLabel !== true"
|
||||
placement="bottom-start"
|
||||
@@ -90,7 +90,7 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const isDisabled = computed(() => {
|
||||
if (props.disabled) return true;
|
||||
if (props.field.readonly) return true;
|
||||
if (props.field.system.readonly) return true;
|
||||
if (props.batchMode && props.batchActive === false) return true;
|
||||
return false;
|
||||
});
|
||||
@@ -98,7 +98,7 @@ export default defineComponent({
|
||||
const _value = computed(() => {
|
||||
if (props.value !== undefined) return props.value;
|
||||
if (props.initialValue !== undefined) return props.initialValue;
|
||||
return props.field.default_value;
|
||||
return props.field.database?.default_value;
|
||||
});
|
||||
|
||||
return { isDisabled, marked, _value };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Field } from '@/stores/fields/types';
|
||||
import { TranslateResult } from 'vue-i18n';
|
||||
|
||||
export type FormField = Partial<Field> & {
|
||||
export type FormField = DeepPartial<Field> & {
|
||||
field: string;
|
||||
name: string | TranslateResult;
|
||||
hideLabel?: boolean;
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import markdown from './readme.md';
|
||||
import withPadding from '../../../.storybook/decorators/with-padding';
|
||||
import VForm from './v-form.vue';
|
||||
import { defineComponent, ref } from '@vue/composition-api';
|
||||
import { useFieldsStore } from '@/stores/fields';
|
||||
import { FormField } from './types';
|
||||
import { i18n } from '@/lang';
|
||||
import { withKnobs, boolean } from '@storybook/addon-knobs';
|
||||
import RawValue from '../../../.storybook/raw-value.vue';
|
||||
|
||||
Vue.component('v-form', VForm);
|
||||
|
||||
export default {
|
||||
title: 'Components / Form',
|
||||
parameters: {
|
||||
notes: markdown,
|
||||
},
|
||||
decorators: [withPadding, withKnobs],
|
||||
};
|
||||
|
||||
export const collection = () =>
|
||||
defineComponent({
|
||||
i18n,
|
||||
setup() {
|
||||
const fieldsStore = useFieldsStore({});
|
||||
fieldsStore.state.fields = [
|
||||
{
|
||||
collection: 'articles',
|
||||
field: 'title',
|
||||
datatype: 'VARCHAR',
|
||||
unique: false,
|
||||
primary_key: false,
|
||||
auto_increment: false,
|
||||
default_value: null,
|
||||
note: '',
|
||||
signed: true,
|
||||
id: 197,
|
||||
type: 'string',
|
||||
sort: 2,
|
||||
interface: 'text-input',
|
||||
hidden_detail: false,
|
||||
hidden_browse: false,
|
||||
required: false,
|
||||
options: {
|
||||
font: 'monospace',
|
||||
},
|
||||
locked: false,
|
||||
translation: null,
|
||||
readonly: false,
|
||||
width: 'full',
|
||||
validation: null,
|
||||
group: null,
|
||||
length: '65535',
|
||||
name: 'Title',
|
||||
},
|
||||
] as any;
|
||||
},
|
||||
template: `
|
||||
<v-form
|
||||
collection="articles"
|
||||
:initial-values="{
|
||||
title: 'Hello World!'
|
||||
}"
|
||||
/>
|
||||
`,
|
||||
});
|
||||
|
||||
export const fields = () =>
|
||||
defineComponent({
|
||||
i18n,
|
||||
components: { RawValue },
|
||||
props: {
|
||||
loading: {
|
||||
default: boolean('Loading', false),
|
||||
},
|
||||
batchMode: {
|
||||
default: boolean('Batch', false),
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const fields: FormField[] = [
|
||||
{
|
||||
field: 'field',
|
||||
name: 'My Field',
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
options: { placeholder: 'First Field' },
|
||||
sort: 1,
|
||||
},
|
||||
{
|
||||
field: 'another-field',
|
||||
name: 'Another Field',
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
options: null,
|
||||
note: 'I am required',
|
||||
sort: 2,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'third-field',
|
||||
name: 'A Third Field',
|
||||
interface: 'text-input',
|
||||
width: 'full',
|
||||
options: null,
|
||||
sort: 3,
|
||||
default_value: 'This is my default value',
|
||||
},
|
||||
];
|
||||
|
||||
const edits = ref({});
|
||||
|
||||
return { fields, edits };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<v-form
|
||||
v-model="edits"
|
||||
:loading="loading"
|
||||
:batch-mode="batchMode"
|
||||
:fields="fields"
|
||||
:initial-values="{
|
||||
'third-field': 'Hello World!'
|
||||
}"
|
||||
/>
|
||||
<raw-value>{{ edits }}</raw-value>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
@@ -130,7 +130,7 @@ export default defineComponent({
|
||||
return (
|
||||
props.loading ||
|
||||
props.disabled === true ||
|
||||
field.readonly === true ||
|
||||
field.system.readonly === true ||
|
||||
(props.batchMode && batchActiveFields.value.includes(field.field) === false)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export function useCollection(collection: Ref<string>) {
|
||||
// Every collection has a primary key; rules of the land
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return fields.value?.find(
|
||||
(field) => field.collection === collection.value && field.database.is_primary_key === true
|
||||
(field) => field.collection === collection.value && field.database?.is_primary_key === true
|
||||
)!;
|
||||
});
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function useFormFields(fields: Ref<Field[]>) {
|
||||
const interfaceExists = interfaceUsed !== undefined;
|
||||
|
||||
if (interfaceExists === false) {
|
||||
field.system!.interface = getDefaultInterfaceForType(field.system!.type);
|
||||
field.system!.interface = getDefaultInterfaceForType(field.type);
|
||||
}
|
||||
|
||||
if (interfaceUsed?.hideLabel === true) {
|
||||
|
||||
@@ -7,5 +7,5 @@ export default defineDisplay(({ i18n }) => ({
|
||||
icon: 'query_builder',
|
||||
handler: DisplayDateTime,
|
||||
options: [],
|
||||
types: ['datetime', 'datetime_created', 'datetime_updated', 'date', 'time'],
|
||||
types: ['datetime', 'date', 'time', 'timestamp'],
|
||||
}));
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineDisplay(({ i18n }) => ({
|
||||
name: i18n.t('file'),
|
||||
icon: 'insert_photo',
|
||||
handler: DisplayFile,
|
||||
types: ['file'],
|
||||
types: ['string'],
|
||||
options: [],
|
||||
fields: ['data', 'type', 'title'],
|
||||
}));
|
||||
|
||||
@@ -4,7 +4,7 @@ import DisplayImage from './image.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'image',
|
||||
name: i18n.t('image'),
|
||||
types: ['file'],
|
||||
types: ['string'],
|
||||
icon: 'insert_photo',
|
||||
handler: DisplayImage,
|
||||
options: [
|
||||
|
||||
@@ -4,7 +4,7 @@ import DisplayStatusBadge from './status-badge.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'status-badge',
|
||||
name: i18n.t('status_badge'),
|
||||
types: ['status'],
|
||||
types: ['string'],
|
||||
icon: 'flag',
|
||||
handler: DisplayStatusBadge,
|
||||
options: null,
|
||||
|
||||
@@ -4,7 +4,7 @@ import DisplayStatusDot from './status-dot.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'status-dot',
|
||||
name: i18n.t('status_dot'),
|
||||
types: ['status'],
|
||||
types: ['string'],
|
||||
icon: 'flag',
|
||||
handler: DisplayStatusDot,
|
||||
options: null,
|
||||
|
||||
@@ -4,7 +4,7 @@ import DisplayTags from './tags.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'tags',
|
||||
name: i18n.t('tags'),
|
||||
types: ['array'],
|
||||
types: ['json'],
|
||||
icon: 'label',
|
||||
handler: DisplayTags,
|
||||
options: [
|
||||
|
||||
@@ -23,7 +23,7 @@ export default defineDisplay(({ i18n }) => ({
|
||||
width: 'full',
|
||||
},
|
||||
],
|
||||
types: ['m2o', 'o2m', 'm2m'],
|
||||
types: ['alias', 'string', 'integer', 'bigInteger', 'text'],
|
||||
fields: (options: Options, { field, collection }) => {
|
||||
const relatedCollection = getRelatedCollection(collection, field);
|
||||
const { primaryKeyField } = useCollection(ref(relatedCollection as string));
|
||||
|
||||
@@ -4,7 +4,7 @@ import DisplayUser from './user.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'user',
|
||||
name: i18n.t('user'),
|
||||
types: ['user', 'user_created', 'user_updated'],
|
||||
types: ['string'],
|
||||
icon: 'person',
|
||||
handler: DisplayUser,
|
||||
options: [
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('checkboxes'),
|
||||
icon: 'radio_button_checked',
|
||||
component: InterfaceCheckboxes,
|
||||
types: ['array'],
|
||||
types: ['json'],
|
||||
options: [
|
||||
{
|
||||
field: 'choices',
|
||||
|
||||
@@ -15,7 +15,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('code'),
|
||||
icon: 'code',
|
||||
component: InterfaceCode,
|
||||
types: ['string', 'json', 'array'],
|
||||
types: ['string', 'json', 'text'],
|
||||
options: [
|
||||
{
|
||||
field: 'template',
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('datetime'),
|
||||
icon: 'today',
|
||||
component: InterfaceDateTime,
|
||||
types: ['datetime', 'datetime_created', 'datetime_updated', 'date', 'time'],
|
||||
types: ['datetime', 'date', 'time', 'timestamp'],
|
||||
options: [
|
||||
{
|
||||
field: 'includeSeconds',
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('dropdown_multiple'),
|
||||
icon: 'arrow_drop_down_circle',
|
||||
component: InterfaceDropdownMultiselect,
|
||||
types: ['array'],
|
||||
types: ['json'],
|
||||
options: [
|
||||
{
|
||||
field: 'choices',
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('file'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceFile,
|
||||
types: ['file'],
|
||||
types: ['string'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('files'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceFiles,
|
||||
types: ['files'],
|
||||
types: ['alias'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('image'),
|
||||
icon: 'insert_photo',
|
||||
component: InterfaceImage,
|
||||
types: ['file'],
|
||||
types: ['string'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('many_to_many'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceManyToMany,
|
||||
types: ['m2m'],
|
||||
types: ['alias'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('many_to_one'),
|
||||
icon: 'arrow_right_alt',
|
||||
component: InterfaceManyToOne,
|
||||
types: ['m2o'],
|
||||
types: ['string', 'text', 'integer', 'bigInteger'],
|
||||
options: [
|
||||
{
|
||||
field: 'template',
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('numeric'),
|
||||
icon: 'dialpad',
|
||||
component: InterfaceNumeric,
|
||||
types: ['integer', 'decimal'],
|
||||
types: ['integer', 'decimal', 'float'],
|
||||
options: [
|
||||
{
|
||||
field: 'placeholder',
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('one_to_many'),
|
||||
icon: 'arrow_right_alt',
|
||||
component: InterfaceOneToMany,
|
||||
types: ['o2m'],
|
||||
types: ['alias'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -99,7 +99,7 @@ export default defineComponent({
|
||||
|
||||
props.fields.forEach((field) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
newDefaults[field.field!] = field.default_value;
|
||||
newDefaults[field.field!] = field.database?.default_value;
|
||||
});
|
||||
|
||||
if (props.value !== null) {
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('slider'),
|
||||
icon: 'linear_scale',
|
||||
component: InterfaceSlider,
|
||||
types: ['integer', 'decimal'],
|
||||
types: ['integer', 'decimal', 'float'],
|
||||
options: [
|
||||
{
|
||||
field: 'minValue',
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('status'),
|
||||
icon: 'bubble_chart',
|
||||
component: InterfaceStatus,
|
||||
types: ['status'],
|
||||
types: ['string'],
|
||||
options: [
|
||||
{
|
||||
field: 'status_mapping',
|
||||
|
||||
@@ -6,7 +6,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('tags'),
|
||||
icon: 'local_offer',
|
||||
component: InterfaceTags,
|
||||
types: ['array'],
|
||||
types: ['json'],
|
||||
options: [
|
||||
{
|
||||
field: 'placeholder',
|
||||
|
||||
@@ -5,7 +5,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
id: 'translations',
|
||||
name: i18n.t('translations'),
|
||||
icon: 'replay',
|
||||
types: ['translation'],
|
||||
types: ['alias'],
|
||||
component: InterfaceTranslations,
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -6,6 +6,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('user'),
|
||||
icon: 'person',
|
||||
component: InterfaceUser,
|
||||
types: ['user', 'user_created', 'user_updated'],
|
||||
types: ['integer', 'bigInteger', 'string', 'text'],
|
||||
options: [],
|
||||
}));
|
||||
|
||||
@@ -190,7 +190,7 @@ export default defineComponent({
|
||||
},
|
||||
detailRoute: {
|
||||
type: String,
|
||||
default: `/{{project}}/collections/{{collection}}/{{primaryKey}}`,
|
||||
default: `/collections/{{collection}}/{{primaryKey}}`,
|
||||
},
|
||||
file: {
|
||||
type: Object as PropType<File>,
|
||||
@@ -219,11 +219,11 @@ export default defineComponent({
|
||||
const { info, primaryKeyField, fields: fieldsInCollection } = useCollection(collection);
|
||||
|
||||
const availableFields = computed(() =>
|
||||
fieldsInCollection.value.filter((field) => field.hidden_browse === false)
|
||||
fieldsInCollection.value.filter((field) => field.system.hidden_browse !== true)
|
||||
);
|
||||
|
||||
const fileFields = computed(() => {
|
||||
return [...availableFields.value.filter((field) => field.type === 'file')];
|
||||
return [...availableFields.value.filter((field) => field.system.special === 'file')];
|
||||
});
|
||||
|
||||
const { size, icon, imageSource, title, subtitle, imageFit } = useViewOptions();
|
||||
|
||||
@@ -206,7 +206,7 @@ export default defineComponent({
|
||||
},
|
||||
detailRoute: {
|
||||
type: String,
|
||||
default: `/{{project}}/collections/{{collection}}/{{primaryKey}}`,
|
||||
default: `/collections/{{collection}}/{{primaryKey}}`,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
@@ -369,7 +369,7 @@ export default defineComponent({
|
||||
_viewQuery.value?.fields ||
|
||||
availableFields.value
|
||||
.filter((field: Field) => {
|
||||
return field.primary_key === false && field.type !== 'sort';
|
||||
return field.database?.is_primary_key === false && field.system.special !== 'sort';
|
||||
})
|
||||
.slice(0, 4)
|
||||
.map(({ field }) => field);
|
||||
@@ -425,10 +425,10 @@ export default defineComponent({
|
||||
value: field.field,
|
||||
width: localWidths.value[field.field] || _viewOptions.value?.widths?.[field.field] || null,
|
||||
field: {
|
||||
display: field.display,
|
||||
displayOptions: field.display_options,
|
||||
interface: field.interface,
|
||||
interfaceOptions: field.options,
|
||||
display: field.system.display,
|
||||
displayOptions: field.system.display_options,
|
||||
interface: field.system.interface,
|
||||
interfaceOptions: field.system.options,
|
||||
type: field.type,
|
||||
field: field.field,
|
||||
},
|
||||
@@ -516,11 +516,11 @@ export default defineComponent({
|
||||
const field = availableFields.value.find((field) => field.field === fieldKey);
|
||||
|
||||
if (field === undefined) return null;
|
||||
if (!field.display) return null;
|
||||
if (!field.system.display) return null;
|
||||
|
||||
return {
|
||||
display: field.display,
|
||||
options: field.display_options,
|
||||
display: field.system.display,
|
||||
options: field.system.display_options,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ const redirectIfNeeded: NavigationGuard = async (to, from, next) => {
|
||||
|
||||
const primaryKeyField = fieldsStore.getPrimaryKeyFieldForCollection(to.params.collection);
|
||||
|
||||
const item = await api.get(`/${to.params.project}/items/${to.params.collection}`, {
|
||||
const item = await api.get(`/items/${to.params.collection}`, {
|
||||
params: {
|
||||
limit: 1,
|
||||
fields: primaryKeyField.field,
|
||||
@@ -170,7 +170,7 @@ const redirectIfNeeded: NavigationGuard = async (to, from, next) => {
|
||||
|
||||
const primaryKey = item.data.data[primaryKeyField.field];
|
||||
|
||||
return next(`/${to.params.project}/collections/${to.params.collection}/${primaryKey}`);
|
||||
return next(`/collections/${to.params.collection}/${primaryKey}`);
|
||||
}
|
||||
|
||||
return next();
|
||||
|
||||
@@ -217,17 +217,19 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function getPrimaryKeyField() {
|
||||
const field: Partial<Field> = {
|
||||
auto_increment: true,
|
||||
const field: DeepPartial<Field> = {
|
||||
field: primaryKeyFieldName.value,
|
||||
hidden_browse: false,
|
||||
hidden_detail: false,
|
||||
interface: 'numeric',
|
||||
length: 15,
|
||||
primary_key: true,
|
||||
type: 'integer',
|
||||
datatype: 'INT',
|
||||
readonly: true,
|
||||
system: {
|
||||
hidden_browse: false,
|
||||
hidden_detail: false,
|
||||
interface: 'numeric',
|
||||
readonly: true,
|
||||
},
|
||||
database: {
|
||||
has_auto_increment: true,
|
||||
is_primary_key: true,
|
||||
type: 'INT',
|
||||
},
|
||||
};
|
||||
|
||||
if (primaryKeyFieldType.value === 'uuid') {
|
||||
@@ -256,127 +258,150 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
function getSystemFields() {
|
||||
const fields: Partial<Field>[] = [];
|
||||
const fields: DeepPartial<Field>[] = [];
|
||||
|
||||
if (systemFields[0].enabled === true) {
|
||||
fields.push({
|
||||
type: 'status',
|
||||
datatype: 'VARCHAR',
|
||||
length: 20,
|
||||
field: systemFields[0].name,
|
||||
interface: 'status',
|
||||
default_value: 'draft',
|
||||
width: 'full',
|
||||
required: true,
|
||||
options: {
|
||||
status_mapping: {
|
||||
published: {
|
||||
name: 'Published',
|
||||
value: 'published',
|
||||
text_color: 'white',
|
||||
background_color: 'accent',
|
||||
browse_subdued: false,
|
||||
browse_badge: true,
|
||||
soft_delete: false,
|
||||
published: true,
|
||||
required_fields: true,
|
||||
},
|
||||
draft: {
|
||||
name: 'Draft',
|
||||
value: 'draft',
|
||||
text_color: 'white',
|
||||
background_color: 'blue-grey-100',
|
||||
browse_subdued: true,
|
||||
browse_badge: true,
|
||||
soft_delete: false,
|
||||
published: false,
|
||||
required_fields: false,
|
||||
},
|
||||
deleted: {
|
||||
name: 'Deleted',
|
||||
value: 'deleted',
|
||||
text_color: 'white',
|
||||
background_color: 'red',
|
||||
browse_subdued: true,
|
||||
browse_badge: true,
|
||||
soft_delete: true,
|
||||
published: false,
|
||||
required_fields: false,
|
||||
system: {
|
||||
width: 'full',
|
||||
required: true,
|
||||
options: {
|
||||
status_mapping: {
|
||||
published: {
|
||||
name: 'Published',
|
||||
value: 'published',
|
||||
text_color: 'white',
|
||||
background_color: 'accent',
|
||||
browse_subdued: false,
|
||||
browse_badge: true,
|
||||
soft_delete: false,
|
||||
published: true,
|
||||
required_fields: true,
|
||||
},
|
||||
draft: {
|
||||
name: 'Draft',
|
||||
value: 'draft',
|
||||
text_color: 'white',
|
||||
background_color: 'blue-grey-100',
|
||||
browse_subdued: true,
|
||||
browse_badge: true,
|
||||
soft_delete: false,
|
||||
published: false,
|
||||
required_fields: false,
|
||||
},
|
||||
deleted: {
|
||||
name: 'Deleted',
|
||||
value: 'deleted',
|
||||
text_color: 'white',
|
||||
background_color: 'red',
|
||||
browse_subdued: true,
|
||||
browse_badge: true,
|
||||
soft_delete: true,
|
||||
published: false,
|
||||
required_fields: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
special: 'status',
|
||||
interface: 'status',
|
||||
},
|
||||
database: {
|
||||
type: 'VARCHAR',
|
||||
default_value: 'draft',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (systemFields[1].enabled === true) {
|
||||
fields.push({
|
||||
type: 'sort',
|
||||
datatype: 'INT',
|
||||
field: systemFields[1].name,
|
||||
interface: 'sort',
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
system: {
|
||||
interface: 'sort',
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
special: 'sort',
|
||||
},
|
||||
database: {
|
||||
type: 'INT',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (systemFields[2].enabled === true) {
|
||||
fields.push({
|
||||
type: 'user_created',
|
||||
datatype: 'INT',
|
||||
field: systemFields[2].name,
|
||||
interface: 'owner',
|
||||
options: {
|
||||
template: '{{first_name}} {{last_name}}',
|
||||
display: 'both',
|
||||
system: {
|
||||
special: 'user_created',
|
||||
interface: 'owner',
|
||||
options: {
|
||||
template: '{{first_name}} {{last_name}}',
|
||||
display: 'both',
|
||||
},
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
},
|
||||
database: {
|
||||
type: 'INT' /** @todo make these vendor based */,
|
||||
},
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
});
|
||||
}
|
||||
|
||||
if (systemFields[3].enabled === true) {
|
||||
fields.push({
|
||||
type: 'datetime_created',
|
||||
datatype: 'DATETIME',
|
||||
field: systemFields[3].name,
|
||||
interface: 'datetime-created',
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
system: {
|
||||
special: 'datetime_created',
|
||||
interface: 'datetime-created',
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
},
|
||||
database: {
|
||||
type: 'DATETIME',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (systemFields[4].enabled === true) {
|
||||
fields.push({
|
||||
type: 'user_updated',
|
||||
datatype: 'INT',
|
||||
field: systemFields[4].name,
|
||||
interface: 'user-updated',
|
||||
options: {
|
||||
template: '{{first_name}} {{last_name}}',
|
||||
display: 'both',
|
||||
system: {
|
||||
special: 'user_updated',
|
||||
interface: 'user-updated',
|
||||
options: {
|
||||
template: '{{first_name}} {{last_name}}',
|
||||
display: 'both',
|
||||
},
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
},
|
||||
database: {
|
||||
type: 'INT',
|
||||
},
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
});
|
||||
}
|
||||
|
||||
if (systemFields[5].enabled === true) {
|
||||
fields.push({
|
||||
type: 'datetime_updated',
|
||||
datatype: 'DATETIME',
|
||||
field: systemFields[5].name,
|
||||
interface: 'datetime-updated',
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
system: {
|
||||
special: 'datetime_updated',
|
||||
interface: 'datetime-updated',
|
||||
readonly: true,
|
||||
hidden_detail: true,
|
||||
hidden_browse: true,
|
||||
width: 'full',
|
||||
},
|
||||
database: {
|
||||
type: 'DATETIME',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ export default defineComponent({
|
||||
const { duplicateActive, duplicateName, collections, duplicateTo, saveDuplicate, duplicating } = useDuplicate();
|
||||
|
||||
const interfaceName = computed(() => {
|
||||
return interfaces.find((inter) => inter.id === props.field.interface)?.name;
|
||||
return interfaces.find((inter) => inter.id === props.field.system.interface)?.name;
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -194,8 +194,8 @@ export default defineComponent({
|
||||
collection: duplicateTo.value,
|
||||
};
|
||||
|
||||
delete newField.id;
|
||||
delete newField.sort;
|
||||
delete newField.system.id;
|
||||
delete newField.system.sort;
|
||||
delete newField.name;
|
||||
|
||||
duplicating.value = true;
|
||||
|
||||
@@ -69,7 +69,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const selectedDisplay = computed(() => {
|
||||
return displays.find((inter) => inter.id === props.value.display) || null;
|
||||
return displays.find((inter) => inter.id === props.value.system.display) || null;
|
||||
});
|
||||
|
||||
return { emitValue, items, selectedDisplay };
|
||||
|
||||
@@ -71,7 +71,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const selectedInterface = computed(() => {
|
||||
return interfaces.find((inter) => inter.id === props.value.interface) || null;
|
||||
return interfaces.find((inter) => inter.id === props.value.system.interface) || null;
|
||||
});
|
||||
|
||||
return { emitValue, items, selectedInterface, setInterface };
|
||||
|
||||
@@ -25,7 +25,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const selectedInterface = computed(() => interfaces.find((inter) => inter.id === props.value.interface));
|
||||
const selectedInterface = computed(() => interfaces.find((inter) => inter.id === props.value.system.interface));
|
||||
|
||||
const typeChoices = computed(() => {
|
||||
let availableTypes = types;
|
||||
@@ -45,115 +45,145 @@ export default defineComponent({
|
||||
{
|
||||
field: 'field',
|
||||
name: i18n.t('database_column_name'),
|
||||
interface: 'slug',
|
||||
width: 'half',
|
||||
options: null,
|
||||
readonly: props.isNew === false,
|
||||
system: {
|
||||
interface: 'slug',
|
||||
width: 'half',
|
||||
options: null,
|
||||
readonly: props.isNew === false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'note',
|
||||
name: i18n.t('note'),
|
||||
interface: 'text-input',
|
||||
width: 'full',
|
||||
options: {
|
||||
placeholder: i18n.t('add_helpful_note'),
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
width: 'full',
|
||||
options: {
|
||||
placeholder: i18n.t('add_helpful_note'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'translation',
|
||||
name: i18n.t('translations'),
|
||||
interface: 'key-value',
|
||||
width: 'full',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'key-value',
|
||||
width: 'full',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'default_value',
|
||||
name: i18n.t('default_value'),
|
||||
interface: 'text-input' /** @TODO base on selected datatype */,
|
||||
width: 'half',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_value'),
|
||||
system: {
|
||||
interface: 'text-input' /** @TODO base on selected datatype */,
|
||||
width: 'half',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_value'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'length',
|
||||
name: i18n.t('length'),
|
||||
interface: 'numeric',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'numeric',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'required',
|
||||
name: i18n.t('required'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'readonly',
|
||||
name: i18n.t('readonly'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'hidden_detail',
|
||||
name: i18n.t('hide_on_detail'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'hidden_browse',
|
||||
name: i18n.t('hide_on_browse'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'unique',
|
||||
name: i18n.t('unique'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'primary_key',
|
||||
name: i18n.t('primary_key'),
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
system: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'validation',
|
||||
name: i18n.t('validation_regex'),
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
options: {
|
||||
font: 'monospace',
|
||||
placeholder: 'eg: /^[A-Z]+$/',
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
options: {
|
||||
font: 'monospace',
|
||||
placeholder: 'eg: /^[A-Z]+$/',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'validation_message',
|
||||
name: i18n.t('validation_message'),
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
name: i18n.t('directus_type'),
|
||||
interface: 'dropdown',
|
||||
width: 'half',
|
||||
options: {
|
||||
choices: typeChoices.value,
|
||||
system: {
|
||||
interface: 'dropdown',
|
||||
width: 'half',
|
||||
options: {
|
||||
choices: typeChoices.value,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'datatype',
|
||||
name: i18n.t('database_type'),
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
system: {
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ import FieldSetup from './field-setup.vue';
|
||||
import { types, Type } from '@/stores/fields/types';
|
||||
import { LocalType } from './types';
|
||||
|
||||
const localTypeGroups: Record<LocalType, Type[]> = {
|
||||
/**
|
||||
* @todo fix local type groups in settings
|
||||
*/
|
||||
const localTypeGroups: Record<LocalType, string[]> = {
|
||||
relational: ['m2o', 'o2m', 'm2m', 'translation'],
|
||||
file: ['file'],
|
||||
files: ['files'],
|
||||
|
||||
@@ -13,11 +13,11 @@ export default function useValidation(field: Ref<Field>, localType: Ref<LocalTyp
|
||||
});
|
||||
|
||||
const interfaceComplete = computed<boolean>(() => {
|
||||
return notEmpty(field.value.interface);
|
||||
return notEmpty(field.value.system.interface);
|
||||
});
|
||||
|
||||
const displayComplete = computed<boolean>(() => {
|
||||
return notEmpty(field.value.display);
|
||||
return notEmpty(field.value.system.display);
|
||||
});
|
||||
|
||||
const schemaComplete = computed<boolean>(() => {
|
||||
|
||||
@@ -105,15 +105,15 @@ export default defineComponent({
|
||||
|
||||
const sortedVisibleFields = computed(() =>
|
||||
sortBy(
|
||||
[...fields.value].filter(({ hidden_detail }) => hidden_detail === false),
|
||||
(field) => field.sort || Infinity
|
||||
[...fields.value].filter((field) => field.system.hidden_detail === false),
|
||||
(field) => field.system.sort || Infinity
|
||||
)
|
||||
);
|
||||
|
||||
const sortedHiddenFields = computed(() =>
|
||||
sortBy(
|
||||
[...fields.value].filter(({ hidden_detail }) => hidden_detail === true),
|
||||
(field) => field.sort || Infinity
|
||||
[...fields.value].filter((field) => field.system.hidden_detail === true),
|
||||
(field) => field.system.sort || Infinity
|
||||
)
|
||||
);
|
||||
|
||||
@@ -157,9 +157,10 @@ export default defineComponent({
|
||||
|
||||
const fieldsInGroup = location === 'visible' ? sortedVisibleFields.value : sortedHiddenFields.value;
|
||||
|
||||
const updates: Partial<Field>[] = fieldsInGroup.slice(newIndex).map((field) => {
|
||||
const updates: DeepPartial<Field>[] = fieldsInGroup.slice(newIndex).map((field) => {
|
||||
const sortValue =
|
||||
field.sort || fieldsInGroup.findIndex((existingField) => existingField.field === field.field);
|
||||
field.system.sort ||
|
||||
fieldsInGroup.findIndex((existingField) => existingField.field === field.field);
|
||||
|
||||
return {
|
||||
field: field.field,
|
||||
@@ -169,11 +170,11 @@ export default defineComponent({
|
||||
|
||||
const addedToEnd = newIndex === fieldsInGroup.length;
|
||||
|
||||
let newSortValue = fieldsInGroup[newIndex]?.sort;
|
||||
let newSortValue = fieldsInGroup[newIndex]?.system.sort;
|
||||
|
||||
if (!newSortValue && addedToEnd) {
|
||||
const previousItem = fieldsInGroup[newIndex - 1];
|
||||
if (previousItem && previousItem.sort) newSortValue = previousItem.sort + 1;
|
||||
if (previousItem && previousItem.system.sort) newSortValue = previousItem.system.sort + 1;
|
||||
}
|
||||
|
||||
if (!newSortValue) {
|
||||
@@ -182,8 +183,10 @@ export default defineComponent({
|
||||
|
||||
updates.push({
|
||||
field: element.field,
|
||||
sort: newSortValue,
|
||||
hidden_detail: location === 'hidden',
|
||||
system: {
|
||||
hidden_detail: location === 'hidden',
|
||||
sort: newSortValue,
|
||||
},
|
||||
});
|
||||
|
||||
fieldsStore.updateFields(element.collection, updates);
|
||||
@@ -197,11 +200,11 @@ export default defineComponent({
|
||||
|
||||
const fields = location === 'visible' ? sortedVisibleFields.value : sortedHiddenFields.value;
|
||||
|
||||
const updates: Partial<Field>[] = fields.slice(...selectionRange).map((field) => {
|
||||
const updates: DeepPartial<Field>[] = fields.slice(...selectionRange).map((field) => {
|
||||
// If field.sort isn't set yet, base it on the index of the array. That way, the
|
||||
// new sort value will match what's visible on the screen
|
||||
const sortValue =
|
||||
field.sort || fields.findIndex((existingField) => existingField.field === field.field);
|
||||
field.system.sort || fields.findIndex((existingField) => existingField.field === field.field);
|
||||
|
||||
return {
|
||||
field: field.field,
|
||||
@@ -209,10 +212,12 @@ export default defineComponent({
|
||||
};
|
||||
});
|
||||
|
||||
const sortOfItemOnNewIndex = fields[newIndex].sort || newIndex;
|
||||
const sortOfItemOnNewIndex = fields[newIndex].system.sort || newIndex;
|
||||
updates.push({
|
||||
field: element.field,
|
||||
sort: sortOfItemOnNewIndex,
|
||||
system: {
|
||||
sort: sortOfItemOnNewIndex,
|
||||
},
|
||||
});
|
||||
|
||||
fieldsStore.updateFields(element.collection, updates);
|
||||
|
||||
@@ -251,9 +251,9 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const statuses = computed<Status[] | null>(() => {
|
||||
if (statusField.value && statusField.value.options) {
|
||||
return Object.keys(statusField.value.options.status_mapping).map((key: string) => ({
|
||||
...statusField.value?.options?.status_mapping[key],
|
||||
if (statusField.value && statusField.value.system.options) {
|
||||
return Object.keys(statusField.value.system.options.status_mapping).map((key: string) => ({
|
||||
...statusField.value?.system.options?.status_mapping[key],
|
||||
value: key,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<v-list nav>
|
||||
<v-list-item :to="`/${project}/users/all`">
|
||||
<v-list-item to="/users/all">
|
||||
<v-list-item-icon><v-icon name="people" /></v-list-item-icon>
|
||||
<v-list-item-content>{{ $t('all_users') }}</v-list-item-content>
|
||||
</v-list-item>
|
||||
@@ -13,7 +13,7 @@
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
<v-list-item v-for="{ name, id } in roles" :key="id" :to="`/${project}/users/${id}`">
|
||||
<v-list-item v-for="{ name, id } in roles" :key="id" :to="`/users/${id}`">
|
||||
<v-list-item-icon><v-icon name="people" /></v-list-item-icon>
|
||||
<v-list-item-content>{{ name }}</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
38
src/shims.d.ts
vendored
38
src/shims.d.ts
vendored
@@ -42,3 +42,41 @@ declare module 'js-yaml' {
|
||||
const x: any;
|
||||
export default x;
|
||||
}
|
||||
|
||||
type Primitive = string | number | boolean | bigint | symbol | undefined | null;
|
||||
type Builtin = Primitive | Function | Date | Error | RegExp;
|
||||
type IsTuple<T> = T extends [infer A]
|
||||
? T
|
||||
: T extends [infer A, infer B]
|
||||
? T
|
||||
: T extends [infer A, infer B, infer C]
|
||||
? T
|
||||
: T extends [infer A, infer B, infer C, infer D]
|
||||
? T
|
||||
: T extends [infer A, infer B, infer C, infer D, infer E]
|
||||
? T
|
||||
: never;
|
||||
|
||||
type DeepPartial<T> = T extends Primitive | Builtin
|
||||
? T
|
||||
: T extends Map<infer K, infer V>
|
||||
? Map<DeepPartial<K>, DeepPartial<V>>
|
||||
: T extends ReadonlyMap<infer K, infer V>
|
||||
? ReadonlyMap<DeepPartial<K>, DeepPartial<V>>
|
||||
: T extends WeakMap<infer K, infer V>
|
||||
? WeakMap<DeepPartial<K>, DeepPartial<V>>
|
||||
: T extends Set<infer U>
|
||||
? Set<DeepPartial<U>>
|
||||
: T extends ReadonlySet<infer U>
|
||||
? ReadonlySet<DeepPartial<U>>
|
||||
: T extends WeakSet<infer U>
|
||||
? WeakSet<DeepPartial<U>>
|
||||
: T extends Array<infer U>
|
||||
? T extends IsTuple<T>
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Array<DeepPartial<U>>
|
||||
: T extends Promise<infer U>
|
||||
? Promise<DeepPartial<U>>
|
||||
: T extends {}
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>;
|
||||
|
||||
@@ -7,23 +7,41 @@ type Translation = {
|
||||
|
||||
export type Width = 'half' | 'half-left' | 'half-right' | 'full' | 'fill';
|
||||
|
||||
export type LocalType =
|
||||
export type Type =
|
||||
| 'alias'
|
||||
| 'bigInteger'
|
||||
| 'binary'
|
||||
| 'binary'
|
||||
| 'boolean'
|
||||
| 'date'
|
||||
| 'datetime'
|
||||
| 'decimal'
|
||||
| 'float'
|
||||
| 'integer'
|
||||
| 'json'
|
||||
| 'string'
|
||||
| 'text'
|
||||
| 'time'
|
||||
| 'timestamp'
|
||||
| 'unknown';
|
||||
|
||||
export const types: Type[] = [
|
||||
'alias',
|
||||
'bigInteger',
|
||||
'binary',
|
||||
'boolean',
|
||||
'date',
|
||||
'datetime',
|
||||
'decimal',
|
||||
'float',
|
||||
'integer',
|
||||
'json',
|
||||
'string',
|
||||
'text',
|
||||
'time',
|
||||
'timestamp',
|
||||
'unknown',
|
||||
];
|
||||
|
||||
export type DatabaseColumn = {
|
||||
/** @todo import this from knex-schema-inspector when that's launched */
|
||||
name: string;
|
||||
@@ -73,6 +91,6 @@ export interface FieldRaw {
|
||||
|
||||
export interface Field extends FieldRaw {
|
||||
name: string | TranslateResult;
|
||||
type: LocalType;
|
||||
type: Type;
|
||||
system: SystemField;
|
||||
}
|
||||
|
||||
@@ -1,51 +1,23 @@
|
||||
export default function getDefaultInterfaceForType(type: string | null | undefined) {
|
||||
switch (type) {
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'datetime_created':
|
||||
case 'datetime_updated':
|
||||
return 'datetime';
|
||||
import { Type } from '@/stores/fields/types';
|
||||
|
||||
case 'owner':
|
||||
case 'user_updated':
|
||||
case 'user':
|
||||
return 'user';
|
||||
const defaultInterfaceMap = {
|
||||
alias: 'text-input',
|
||||
bigInteger: 'numeric',
|
||||
binary: 'text-input',
|
||||
boolean: 'toggle',
|
||||
date: 'datetime',
|
||||
datetime: 'datetime',
|
||||
decimal: 'numeric',
|
||||
float: 'numeric',
|
||||
integer: 'numeric',
|
||||
json: 'json',
|
||||
string: 'text-input',
|
||||
text: 'textarea',
|
||||
time: 'datetime',
|
||||
timestamp: 'datetime',
|
||||
unknown: 'text-input',
|
||||
};
|
||||
|
||||
case 'file':
|
||||
return 'file';
|
||||
|
||||
case 'integer':
|
||||
case 'sort':
|
||||
case 'decimal':
|
||||
return 'numeric';
|
||||
|
||||
case 'status':
|
||||
return 'status';
|
||||
|
||||
case 'slug':
|
||||
return 'slug';
|
||||
|
||||
case 'm2o':
|
||||
return 'many-to-one';
|
||||
|
||||
case 'json':
|
||||
return 'code';
|
||||
|
||||
case 'array':
|
||||
return 'tags';
|
||||
|
||||
case 'hash':
|
||||
case 'group':
|
||||
case 'lang':
|
||||
case 'translation':
|
||||
case 'uuid':
|
||||
case 'string':
|
||||
case 'alias':
|
||||
case 'binary':
|
||||
case 'boolean':
|
||||
case 'o2m':
|
||||
default:
|
||||
return 'text-input';
|
||||
}
|
||||
export default function getDefaultInterfaceForType(type: Type) {
|
||||
return defaultInterfaceMap[type] || 'text-input';
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { LocalType } from '@/stores/fields/types';
|
||||
import { Type } from '@/stores/fields/types';
|
||||
|
||||
/**
|
||||
* Typemap graciously provided by @gpetrov
|
||||
*/
|
||||
const localTypeMap: Record<string, { type: LocalType; useTz?: boolean }> = {
|
||||
const localTypeMap: Record<string, { type: Type; useTimezone?: boolean }> = {
|
||||
// Shared
|
||||
boolean: { type: 'boolean' },
|
||||
tinyint: { type: 'boolean' },
|
||||
@@ -47,7 +47,7 @@ const localTypeMap: Record<string, { type: LocalType; useTz?: boolean }> = {
|
||||
bit: { type: 'boolean' },
|
||||
smallmoney: { type: 'float' },
|
||||
money: { type: 'float' },
|
||||
datetimeoffset: { type: 'datetime', useTz: true },
|
||||
datetimeoffset: { type: 'datetime', useTimezone: true },
|
||||
datetime2: { type: 'datetime' },
|
||||
smalldatetime: { type: 'datetime' },
|
||||
nchar: { type: 'text' },
|
||||
@@ -55,6 +55,8 @@ const localTypeMap: Record<string, { type: LocalType; useTz?: boolean }> = {
|
||||
varbinary: { type: 'binary' },
|
||||
|
||||
// Postgres
|
||||
json: { type: 'json' },
|
||||
uuid: { type: 'string' },
|
||||
int2: { type: 'integer' },
|
||||
serial4: { type: 'integer' },
|
||||
int4: { type: 'integer' },
|
||||
@@ -67,16 +69,16 @@ const localTypeMap: Record<string, { type: LocalType; useTz?: boolean }> = {
|
||||
_varchar: { type: 'string' },
|
||||
bpchar: { type: 'string' },
|
||||
timestamptz: { type: 'timestamp' },
|
||||
'timestamp with time zone': { type: 'timestamp', useTz: true },
|
||||
'timestamp with time zone': { type: 'timestamp', useTimezone: true },
|
||||
'timestamp without thime zone': { type: 'timestamp' },
|
||||
timetz: { type: 'time' },
|
||||
'time with time zone': { type: 'time', useTz: true },
|
||||
'time with time zone': { type: 'time', useTimezone: true },
|
||||
'time without time zone': { type: 'time' },
|
||||
float4: { type: 'float' },
|
||||
float8: { type: 'float' },
|
||||
};
|
||||
|
||||
export default function getLocalType(databaseType: string) {
|
||||
export default function getLocalType(databaseType: string): Type {
|
||||
const type = localTypeMap[databaseType];
|
||||
|
||||
if (type) {
|
||||
|
||||
Reference in New Issue
Block a user