mirror of
https://github.com/directus/directus.git
synced 2026-01-25 10:48:45 -05:00
Merge pull request #220 from directus/room-cleaning
Cleaned up all interfaces and displays.
This commit is contained in:
@@ -24,6 +24,7 @@ You can add any custom (text) prefix/suffix to the value in the input using the
|
||||
| `slug` | Force the value to be URL safe | `false` |
|
||||
| `slug-separator` | What character to use as separator in slugs | `-` |
|
||||
| `active` | Force the focus state | `false` |
|
||||
| `trim` | Trim the start and end whitespace | `false` |
|
||||
|
||||
Note: all other attached attributes are bound to the input HTMLELement in the component. This allows you to attach any of the standard HTML attributes like `min`, `length`, or `pattern`.
|
||||
|
||||
|
||||
@@ -121,6 +121,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
trim: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit, listeners }) {
|
||||
const input = ref<HTMLInputElement | null>(null);
|
||||
@@ -177,20 +181,28 @@ export default defineComponent({
|
||||
function emitValue(event: InputEvent) {
|
||||
let value = (event.target as HTMLInputElement).value;
|
||||
|
||||
if (props.slug === true) {
|
||||
const endsWithSpace = value.endsWith(' ');
|
||||
value = slugify(value, { separator: props.slugSeparator });
|
||||
if (endsWithSpace) value += props.slugSeparator;
|
||||
}
|
||||
if (props.type === 'number') {
|
||||
emit('input', Number(value));
|
||||
} else {
|
||||
if (props.trim === true) {
|
||||
value = value.trim();
|
||||
}
|
||||
|
||||
if (props.dbSafe === true) {
|
||||
value = value.toLowerCase();
|
||||
value = value.replace(/\s/g, '_');
|
||||
// Replace é -> e etc
|
||||
value = value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
}
|
||||
if (props.slug === true) {
|
||||
const endsWithSpace = value.endsWith(' ');
|
||||
value = slugify(value, { separator: props.slugSeparator });
|
||||
if (endsWithSpace) value += props.slugSeparator;
|
||||
}
|
||||
|
||||
emit('input', value);
|
||||
if (props.dbSafe === true) {
|
||||
value = value.toLowerCase();
|
||||
value = value.replace(/\s/g, '_');
|
||||
// Replace é -> e etc
|
||||
value = value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
}
|
||||
|
||||
emit('input', value);
|
||||
}
|
||||
}
|
||||
|
||||
function stepUp() {
|
||||
@@ -200,8 +212,8 @@ export default defineComponent({
|
||||
|
||||
input.value.stepUp();
|
||||
|
||||
if (input.value.value) {
|
||||
return emit('input', input.value.value);
|
||||
if (input.value.value != null) {
|
||||
return emit('input', Number(input.value.value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +225,7 @@ export default defineComponent({
|
||||
input.value.stepDown();
|
||||
|
||||
if (input.value.value) {
|
||||
return emit('input', input.value.value);
|
||||
return emit('input', Number(input.value.value));
|
||||
} else {
|
||||
return emit('input', props.min || 0);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ import DisplayCollection from './collection.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'collection',
|
||||
name: i18n.t('collection'),
|
||||
name: i18n.t('displays.collection.collection'),
|
||||
description: i18n.t('displays.collection.description'),
|
||||
types: ['string'],
|
||||
icon: 'label',
|
||||
handler: DisplayCollection,
|
||||
@@ -15,9 +16,12 @@ export default defineDisplay(({ i18n }) => ({
|
||||
meta: {
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: `Show the collection's icon`,
|
||||
label: i18n.t('displays.collection.icon_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="color-dot">
|
||||
<value-null v-if="value === null" />
|
||||
<div class="dot" :style="styles" v-tooltip="displayValue"></div>
|
||||
</div>
|
||||
@@ -8,6 +8,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, PropType } from '@vue/composition-api';
|
||||
import formatTitle from '@directus/format-title';
|
||||
import { isHex } from '@/utils/color';
|
||||
|
||||
type Choice = {
|
||||
value: string;
|
||||
@@ -42,24 +43,32 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const styles = computed(() => {
|
||||
if (isHex(props.value)) {
|
||||
return { backgroundColor: props.value || props.defaultColor };
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundColor: currentChoice.value?.color || props.defaultColor,
|
||||
};
|
||||
});
|
||||
|
||||
return { displayValue, styles };
|
||||
return { displayValue, styles, isHex };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dot {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0 4px;
|
||||
vertical-align: middle;
|
||||
border-radius: 6px;
|
||||
.color-dot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.dot {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0 4px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,14 +3,15 @@ import DisplayColorDot from './color-dot.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'color-dot',
|
||||
name: i18n.t('color_dot'),
|
||||
name: i18n.t('displays.color-dot.color-dot'),
|
||||
description: i18n.t('displays.color-dot.description'),
|
||||
types: ['string'],
|
||||
icon: 'flag',
|
||||
handler: DisplayColorDot,
|
||||
options: [
|
||||
{
|
||||
field: 'defaultColor',
|
||||
name: i18n.t('default_color'),
|
||||
name: i18n.t('displays.color-dot.default_color'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'color',
|
||||
@@ -25,6 +26,7 @@ export default defineDisplay(({ i18n }) => ({
|
||||
name: i18n.t('choices'),
|
||||
type: 'json',
|
||||
meta: {
|
||||
note: i18n.t('displays.color-dot.choices_note'),
|
||||
interface: 'repeater',
|
||||
options: {
|
||||
template: '{{text}}',
|
||||
|
||||
@@ -16,9 +16,9 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<'datetime' | 'time' | 'date'>,
|
||||
type: String as PropType<'dateTime' | 'time' | 'date' | 'timestamp'>,
|
||||
required: true,
|
||||
validator: (val: string) => ['datetime', 'date', 'time', 'timestamp'].includes(val),
|
||||
validator: (val: string) => ['dateTime', 'date', 'time', 'timestamp'].includes(val),
|
||||
},
|
||||
relative: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -3,20 +3,24 @@ import DisplayDateTime from './datetime.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'datetime',
|
||||
name: i18n.t('datetime'),
|
||||
name: i18n.t('displays.datetime.datetime'),
|
||||
description: i18n.t('displays.datetime.description'),
|
||||
icon: 'query_builder',
|
||||
handler: DisplayDateTime,
|
||||
options: [
|
||||
{
|
||||
field: 'relative',
|
||||
name: i18n.t('relative'),
|
||||
name: i18n.t('displays.datetime.relative'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: 'Show relative time, eg: 5 minutes ago',
|
||||
label: i18n.t('displays.datetime.relative_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
types: ['dateTime', 'date', 'time', 'timestamp'],
|
||||
|
||||
@@ -3,8 +3,9 @@ import DisplayFile from './file.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'file',
|
||||
name: i18n.t('file'),
|
||||
icon: 'insert_photo',
|
||||
name: i18n.t('displays.file.file'),
|
||||
description: i18n.t('displays.file.description'),
|
||||
icon: 'insert_drive_file',
|
||||
handler: DisplayFile,
|
||||
types: ['uuid'],
|
||||
options: [],
|
||||
|
||||
@@ -3,9 +3,10 @@ import handler from './handler';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'filesize',
|
||||
name: i18n.t('filesize'),
|
||||
name: i18n.t('displays.filesize.filesize'),
|
||||
description: i18n.t('displays.filesize.description'),
|
||||
icon: 'description',
|
||||
handler: handler,
|
||||
options: null,
|
||||
options: [],
|
||||
types: ['integer'],
|
||||
}));
|
||||
|
||||
@@ -3,19 +3,21 @@ import DisplayFormattedValue from './formatted-value.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'formatted-value',
|
||||
name: i18n.t('formatted_value'),
|
||||
name: i18n.t('displays.formatted-value.formatted-value'),
|
||||
description: i18n.t('displays.formatted-value.description'),
|
||||
types: ['string', 'text'],
|
||||
icon: 'text_format',
|
||||
handler: DisplayFormattedValue,
|
||||
options: [
|
||||
{
|
||||
field: 'formatTitle',
|
||||
name: i18n.t('format_title'),
|
||||
name: i18n.t('displays.formatted-value.format_title'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('auto_format_casing'),
|
||||
label: i18n.t('displays.formatted-value.format_title_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
@@ -25,13 +27,17 @@ export default defineDisplay(({ i18n }) => ({
|
||||
{
|
||||
field: 'bold',
|
||||
name: i18n.t('bold'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('use_bold_style'),
|
||||
label: i18n.t('displays.formatted-value.bold_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'color',
|
||||
@@ -55,6 +61,9 @@ export default defineDisplay(({ i18n }) => ({
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'sans-serif',
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
<template functional>
|
||||
<v-icon small :name="props.value" />
|
||||
<template>
|
||||
<v-icon small :name="value" :style="style" :filled="filled" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
import { computed, defineComponent } from '@vue/composition-api';
|
||||
import { isHex } from '@/utils/color';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'display-icon',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
filled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const style = computed(() => {
|
||||
if (isHex(props.color)) return { '--v-icon-color': props.color };
|
||||
else return {};
|
||||
});
|
||||
|
||||
return { style };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -3,21 +3,34 @@ import DisplayIcon from './icon.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'icon',
|
||||
name: i18n.t('icon'),
|
||||
name: i18n.t('displays.icon.icon'),
|
||||
description: i18n.t('displays.icon.description'),
|
||||
icon: 'thumb_up',
|
||||
handler: DisplayIcon,
|
||||
options: [
|
||||
{
|
||||
field: 'outline',
|
||||
name: i18n.t('outline'),
|
||||
field: 'filled',
|
||||
name: i18n.t('displays.icon.filled'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: {
|
||||
label: i18n.t('use_outline_variant'),
|
||||
label: i18n.t('displays.icon.filled_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'color',
|
||||
name: i18n.t('color'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'color',
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
],
|
||||
types: ['string'],
|
||||
|
||||
@@ -3,18 +3,24 @@ import DisplayImage from './image.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'image',
|
||||
name: i18n.t('image'),
|
||||
name: i18n.t('displays.image.image'),
|
||||
description: i18n.t('displays.image.description'),
|
||||
types: ['uuid'],
|
||||
icon: 'insert_photo',
|
||||
handler: DisplayImage,
|
||||
options: [
|
||||
{
|
||||
field: 'circle',
|
||||
name: i18n.t('circle'),
|
||||
name: i18n.t('displays.image.circle'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('displays.image.circle_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,14 +3,15 @@ import DisplayLabels from './labels.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'labels',
|
||||
name: i18n.t('labels'),
|
||||
name: i18n.t('displays.labels.labels'),
|
||||
description: i18n.t('displays.labels.description'),
|
||||
types: ['string', 'json'],
|
||||
icon: 'flag',
|
||||
handler: DisplayLabels,
|
||||
options: [
|
||||
{
|
||||
field: 'defaultForeground',
|
||||
name: i18n.t('default_foreground'),
|
||||
name: i18n.t('displays.labels.default_foreground'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'color',
|
||||
@@ -22,7 +23,7 @@ export default defineDisplay(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'defaultBackground',
|
||||
name: i18n.t('default_background'),
|
||||
name: i18n.t('displays.labels.default_background'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
interface: 'color',
|
||||
@@ -39,6 +40,9 @@ export default defineDisplay(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half-left',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('displays.labels.format_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: true,
|
||||
|
||||
@@ -4,18 +4,21 @@ import { defineDisplay } from '@/displays/define';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'mime-type',
|
||||
name: i18n.t('mime_type'),
|
||||
name: i18n.t('displays.mime-type.mime-type'),
|
||||
description: i18n.t('displays.mime-type.description'),
|
||||
icon: 'picture_as_pdf',
|
||||
options: [
|
||||
{
|
||||
field: 'showAsExtension',
|
||||
name: i18n.t('extension_only'),
|
||||
name: i18n.t('displays.mime-type.extension_only'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('only_show_the_file_extension'),
|
||||
label: i18n.t('displays.mime-type.extension_only_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,8 +4,25 @@ import DisplayRating from './rating.vue';
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'rating',
|
||||
name: i18n.t('displays.rating.rating'),
|
||||
description: i18n.t('displays.rating.description'),
|
||||
icon: 'star',
|
||||
handler: DisplayRating,
|
||||
options: null,
|
||||
options: [
|
||||
{
|
||||
field: 'simple',
|
||||
name: i18n.t('displays.rating.simple'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
interface: 'toggle',
|
||||
width: 'half',
|
||||
options: {
|
||||
label: i18n.t('displays.rating.simple_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
types: ['integer', 'decimal', 'float'],
|
||||
}));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<span v-if="false" class="rating simple">
|
||||
<span v-if="simple" class="rating simple">
|
||||
<v-icon small name="star" />
|
||||
{{ value }}
|
||||
</span>
|
||||
@@ -17,7 +17,9 @@
|
||||
import { defineComponent, computed, PropType } from '@vue/composition-api';
|
||||
|
||||
type InterfaceOptions = {
|
||||
maxStars: number;
|
||||
minValue: number;
|
||||
maxValue: number;
|
||||
stepInterval: number;
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
@@ -26,6 +28,10 @@ export default defineComponent({
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
simple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
interfaceOptions: {
|
||||
type: Object as PropType<InterfaceOptions>,
|
||||
default: null,
|
||||
@@ -35,7 +41,7 @@ export default defineComponent({
|
||||
const starCount = computed(() => {
|
||||
if (props.interfaceOptions === null) return 5;
|
||||
|
||||
return props.interfaceOptions.maxStars;
|
||||
return Math.ceil(props.interfaceOptions.maxValue);
|
||||
});
|
||||
|
||||
const ratingPercentage = computed(() => ({
|
||||
|
||||
@@ -12,8 +12,9 @@ type Options = {
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'related-values',
|
||||
name: i18n.t('related_values'),
|
||||
icon: 'text_fields',
|
||||
name: i18n.t('displays.related-values.related-values'),
|
||||
description: i18n.t('displays.related-values.description'),
|
||||
icon: 'settings_ethernet',
|
||||
handler: DisplayRelatedValues,
|
||||
options: [
|
||||
/** @todo make this a component so we have dynamic collection for display template component */
|
||||
|
||||
@@ -3,7 +3,8 @@ import DisplayUser from './user.vue';
|
||||
|
||||
export default defineDisplay(({ i18n }) => ({
|
||||
id: 'user',
|
||||
name: i18n.t('user'),
|
||||
name: i18n.t('displays.user.user'),
|
||||
description: i18n.t('displays.user.description'),
|
||||
types: ['uuid'],
|
||||
icon: 'person',
|
||||
handler: DisplayUser,
|
||||
@@ -13,21 +14,24 @@ export default defineDisplay(({ i18n }) => ({
|
||||
name: i18n.t('display'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'dropdown',
|
||||
options: [
|
||||
{
|
||||
text: i18n.t('avatar'),
|
||||
value: 'avatar',
|
||||
},
|
||||
{
|
||||
text: i18n.t('name'),
|
||||
value: 'name',
|
||||
},
|
||||
{
|
||||
text: i18n.t('both'),
|
||||
value: 'both',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
choices: [
|
||||
{
|
||||
text: i18n.t('displays.user.avatar'),
|
||||
value: 'avatar',
|
||||
},
|
||||
{
|
||||
text: i18n.t('displays.user.name'),
|
||||
value: 'name',
|
||||
},
|
||||
{
|
||||
text: i18n.t('displays.user.both'),
|
||||
value: 'both',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'both',
|
||||
@@ -40,6 +44,11 @@ export default defineDisplay(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('displays.user.circle_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,9 +3,10 @@ import InterfaceCheckboxes from './checkboxes.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'checkboxes',
|
||||
name: i18n.t('checkboxes'),
|
||||
name: i18n.t('interfaces.checkboxes.checkboxes'),
|
||||
icon: 'check_box',
|
||||
component: InterfaceCheckboxes,
|
||||
description: i18n.t('interfaces.checkboxes.description'),
|
||||
types: ['json'],
|
||||
options: [
|
||||
{
|
||||
@@ -43,7 +44,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'allowOther',
|
||||
name: i18n.t('allow_other'),
|
||||
name: i18n.t('interfaces.checkboxes.allow_other'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
@@ -77,8 +78,8 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'icon',
|
||||
},
|
||||
schema: {
|
||||
default_value: 'check_box',
|
||||
},
|
||||
default_value: 'check_box'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'iconOff',
|
||||
@@ -89,8 +90,8 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'icon',
|
||||
},
|
||||
schema: {
|
||||
default_value: 'check_box_outline_blank',
|
||||
},
|
||||
default_value: 'check_box_outline_blank'
|
||||
}
|
||||
},
|
||||
],
|
||||
recommendedDisplays: ['tags'],
|
||||
|
||||
@@ -19,6 +19,7 @@ import 'codemirror/addon/search/matchesonscrollbar.js';
|
||||
import 'codemirror/addon/scroll/annotatescrollbar.js';
|
||||
import 'codemirror/addon/lint/lint.js';
|
||||
import 'codemirror/addon/search/search.js';
|
||||
import 'codemirror/addon/display/placeholder.js';
|
||||
|
||||
import 'codemirror/addon/comment/comment.js';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
@@ -48,6 +49,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: 'text/plain',
|
||||
@@ -235,6 +240,7 @@ export default defineComponent({
|
||||
lineNumbers: props.lineNumber,
|
||||
readOnly: props.disabled ? 'nocursor' : false,
|
||||
mode: props.language,
|
||||
placeholder: props.placeholder,
|
||||
},
|
||||
props.altOptions ? props.altOptions : {}
|
||||
);
|
||||
@@ -268,7 +274,13 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
function fillTemplate() {
|
||||
emit('input', props.template);
|
||||
if(props.type === 'json') {
|
||||
try {
|
||||
emit('input', JSON.parse(props.template));
|
||||
} catch {}
|
||||
} else {
|
||||
emit('input', props.template);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -12,7 +12,8 @@ choices.push({ text: 'JSON', value: 'JSON' });
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'code',
|
||||
name: i18n.t('code'),
|
||||
name: i18n.t('interfaces.code.code'),
|
||||
description: i18n.t('interfaces.code.description'),
|
||||
icon: 'code',
|
||||
component: InterfaceCode,
|
||||
types: ['string', 'json', 'text'],
|
||||
@@ -29,7 +30,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'lineNumber',
|
||||
name: i18n.t('line_number'),
|
||||
name: i18n.t('interfaces.code.line_number'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
@@ -47,6 +48,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'full',
|
||||
interface: 'code',
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.code.placeholder'),
|
||||
language: 'text/plain',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
includeMeta: {
|
||||
includeSystem: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
@@ -25,7 +25,7 @@ export default defineComponent({
|
||||
const collectionsStore = useCollectionsStore();
|
||||
|
||||
const collections = computed(() => {
|
||||
if (props.includeMeta) return collectionsStore.state.collections;
|
||||
if (props.includeSystem) return collectionsStore.state.collections;
|
||||
|
||||
return collectionsStore.state.collections.filter(
|
||||
(collection) => collection.collection.startsWith('directus_') === false
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceCollections from './collections.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'collections',
|
||||
name: i18n.t('collections'),
|
||||
name: i18n.t('interfaces.collections.collections'),
|
||||
description: i18n.t('interfaces.collections.description'),
|
||||
icon: 'featured_play_list',
|
||||
component: InterfaceCollections,
|
||||
types: ['string'],
|
||||
@@ -16,12 +17,13 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('include_system_collections'),
|
||||
label: i18n.t('interfaces.collections.include_system_collections'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
recommendedDisplays: ['collection'],
|
||||
}));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<template #activator>
|
||||
<v-input
|
||||
:disabled="disabled"
|
||||
:placeholder="$t('choose_a_color')"
|
||||
:placeholder="$t('interfaces.color.placeholder')"
|
||||
v-model="hexValue"
|
||||
:pattern="/#([a-f\d]{2}){3}/i"
|
||||
class="color-input"
|
||||
|
||||
@@ -3,19 +3,22 @@ import InterfaceColor from './color.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'color',
|
||||
name: i18n.t('color'),
|
||||
name: i18n.t('interfaces.color.color'),
|
||||
description: i18n.t('interfaces.color.description'),
|
||||
icon: 'palette',
|
||||
component: InterfaceColor,
|
||||
types: ['string'],
|
||||
recommendedDisplays: ['color-dot'],
|
||||
options: [
|
||||
{
|
||||
field: 'presets',
|
||||
name: i18n.t('preset_colors'),
|
||||
name: i18n.t('interfaces.color.preset_colors'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'full',
|
||||
interface: 'repeater',
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.color.preset_colors_placeholder'),
|
||||
template: '{{ name }} - {{ color }}',
|
||||
fields: [
|
||||
{
|
||||
@@ -25,7 +28,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
interface: 'text-input',
|
||||
width: 'half',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'color',
|
||||
@@ -33,12 +36,12 @@ export default defineInterface(({ i18n }) => ({
|
||||
name: i18n.t('color'),
|
||||
meta: {
|
||||
interface: 'color',
|
||||
width: 'half'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
width: 'half',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<v-divider />
|
||||
|
||||
<button class="to-now" @click="setToNow">{{ $t('set_to_now') }}</button>
|
||||
<button class="to-now" @click="setToNow">{{ $t('interfaces.datetime.set_to_now') }}</button>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,14 +3,16 @@ import InterfaceDateTime from './datetime.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'datetime',
|
||||
name: i18n.t('datetime'),
|
||||
name: i18n.t('interfaces.datetime.datetime'),
|
||||
description: i18n.t('interfaces.datetime.description'),
|
||||
icon: 'today',
|
||||
component: InterfaceDateTime,
|
||||
types: ['dateTime', 'date', 'time', 'timestamp'],
|
||||
options: [
|
||||
{
|
||||
field: 'includeSeconds',
|
||||
name: i18n.t('include_seconds'),
|
||||
name: i18n.t('interfaces.datetime.include_seconds'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<v-notice v-if="!collectionField" type="warning">
|
||||
{{ $t('collection_field_not_setup') }}
|
||||
{{ $t('interfaces.display-template.collection_field_not_setup') }}
|
||||
</v-notice>
|
||||
<v-notice v-else-if="collection === null" type="warning">
|
||||
{{ $t('select_a_collection') }}
|
||||
{{ $t('interfaces.display-template.select_a_collection') }}
|
||||
</v-notice>
|
||||
<v-field-template v-else :collection="collection" @input="$listeners.input" :value="value" :disabled="disabled" />
|
||||
</template>
|
||||
|
||||
@@ -3,10 +3,24 @@ import InterfaceDisplayTemplate from './display-template.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'display-template',
|
||||
name: i18n.t('display-template'),
|
||||
name: i18n.t('interfaces.display-template.display-template'),
|
||||
description: i18n.t('interfaces.display-template.description'),
|
||||
icon: 'arrow_drop_down_circle',
|
||||
component: InterfaceDisplayTemplate,
|
||||
types: ['string'],
|
||||
system: true,
|
||||
options: [],
|
||||
options: [
|
||||
{
|
||||
field: 'collectionField',
|
||||
name: i18n.t('interfaces.display-template.collection_field'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'full',
|
||||
interface: 'text-input'
|
||||
},
|
||||
schema: {
|
||||
default_value: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<v-divider
|
||||
:inline-title="false"
|
||||
:class="{ margin: icon || title }"
|
||||
:style="{
|
||||
'--v-divider-color': color,
|
||||
'--v-divider-label-color': color,
|
||||
}"
|
||||
large
|
||||
:inline-title="inlineTitle"
|
||||
>
|
||||
<template v-if="icon" #icon><v-icon :name="icon" /></template>
|
||||
<template v-if="title" #default>{{ title }}</template>
|
||||
@@ -30,6 +30,10 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
inlineTitle: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceDivider from './divider.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'divider',
|
||||
name: i18n.t('divider'),
|
||||
name: i18n.t('interfaces.divider.divider'),
|
||||
description: i18n.t('interfaces.divider.description'),
|
||||
icon: 'remove',
|
||||
component: InterfaceDivider,
|
||||
hideLabel: true,
|
||||
@@ -17,7 +18,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'color',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'icon',
|
||||
@@ -26,7 +27,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'title',
|
||||
@@ -35,7 +36,25 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
}
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.divider.title_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'inlineTitle',
|
||||
name: i18n.t('interfaces.divider.inline_title'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.divider.inline_title_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:show-deselect="allowNone"
|
||||
:placeholder="placeholder"
|
||||
:allow-other="allowOther"
|
||||
:close-on-content-click="false"
|
||||
>
|
||||
<template #prepend v-if="icon">
|
||||
<v-icon :name="icon" />
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceDropdownMultiselect from './dropdown-multiselect.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'dropdown-multiselect',
|
||||
name: i18n.t('dropdown_multiple'),
|
||||
name: i18n.t('interfaces.dropdown-multiselect.dropdown-multiselect'),
|
||||
description: i18n.t('interfaces.dropdown-multiselect.description'),
|
||||
icon: 'arrow_drop_down_circle',
|
||||
component: InterfaceDropdownMultiselect,
|
||||
types: ['json'],
|
||||
@@ -16,6 +17,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'full',
|
||||
interface: 'repeater',
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.dropdown.choices_placeholder'),
|
||||
template: '{{ text }}',
|
||||
fields: [
|
||||
{
|
||||
@@ -23,6 +25,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
type: 'string',
|
||||
name: i18n.t('text'),
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
},
|
||||
},
|
||||
@@ -31,6 +34,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
type: 'string',
|
||||
name: i18n.t('value'),
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
font: 'monospace',
|
||||
@@ -43,24 +47,46 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'allowOther',
|
||||
name: i18n.t('allow_other'),
|
||||
name: i18n.t('interfaces.dropdown.allow_other'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.dropdown.allow_other_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'allowNone',
|
||||
name: i18n.t('allow_none'),
|
||||
name: i18n.t('interfaces.dropdown.allow_none'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.dropdown.allow_none_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'placeholder',
|
||||
name: i18n.t('placeholder'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'icon',
|
||||
name: i18n.t('icon'),
|
||||
|
||||
@@ -4,6 +4,7 @@ import InterfaceDropdown from './dropdown.vue';
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'dropdown',
|
||||
name: i18n.t('dropdown'),
|
||||
description: i18n.t('interfaces.dropdown.description'),
|
||||
icon: 'arrow_drop_down_circle',
|
||||
component: InterfaceDropdown,
|
||||
types: ['string'],
|
||||
@@ -16,6 +17,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'full',
|
||||
interface: 'repeater',
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.dropdown.choices_placeholder'),
|
||||
template: '{{ text }}',
|
||||
fields: [
|
||||
{
|
||||
@@ -45,21 +47,31 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'allowOther',
|
||||
name: i18n.t('allow_other'),
|
||||
name: i18n.t('interfaces.dropdown.allow_other'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.dropdown.allow_other_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'allowNone',
|
||||
name: i18n.t('allow_none'),
|
||||
name: i18n.t('interfaces.dropdown.allow_none'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.dropdown.allow_none_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
@@ -79,6 +91,9 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceFile from './file.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'file',
|
||||
name: i18n.t('file'),
|
||||
name: i18n.t('interfaces.file.file'),
|
||||
description: i18n.t('interfaces.file.description'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceFile,
|
||||
types: ['uuid'],
|
||||
|
||||
@@ -3,10 +3,12 @@ import InterfaceFiles from './files.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'files',
|
||||
name: i18n.t('files'),
|
||||
name: i18n.t('interfaces.files.files'),
|
||||
description: i18n.t('interfaces.files.description'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceFiles,
|
||||
types: ['alias'],
|
||||
relationship: 'm2m',
|
||||
options: [],
|
||||
recommendedDisplays: ['files'],
|
||||
}));
|
||||
|
||||
@@ -3,8 +3,9 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'hash',
|
||||
name: i18n.t('hash'),
|
||||
icon: 'text_fields',
|
||||
name: i18n.t('interfaces.hash.hash'),
|
||||
description: i18n.t('interfaces.hash.description'),
|
||||
icon: 'fingerprint',
|
||||
component: InterfaceHash,
|
||||
types: ['string'],
|
||||
options: [
|
||||
@@ -15,16 +16,25 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
}
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'masked',
|
||||
name: i18n.t('masked'),
|
||||
name: i18n.t('interfaces.hash.masked'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
}
|
||||
options: {
|
||||
label: i18n.t('interfaces.hash.masked_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<template #activator="{ active, activate }">
|
||||
<v-input
|
||||
:disabled="disabled"
|
||||
:placeholder="value ? formatTitle(value) : $t('search_for_icon')"
|
||||
:placeholder="value ? formatTitle(value) : $t('interfaces.icon.search_for_icon')"
|
||||
v-model="searchQuery"
|
||||
@focus="activate"
|
||||
:class="{ 'has-value' : value}"
|
||||
:class="{ 'has-value': value }"
|
||||
>
|
||||
<template #prepend>
|
||||
<v-icon v-if="value" @click="activate" :name="value" :class="{ active: value }" />
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceIcon from './icon.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'icon',
|
||||
name: i18n.t('icon'),
|
||||
name: i18n.t('interfaces.icon.icon'),
|
||||
description: i18n.t('interfaces.icon.description'),
|
||||
icon: 'insert_emoticon',
|
||||
component: InterfaceIcon,
|
||||
types: ['string'],
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceImage from './image.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'image',
|
||||
name: i18n.t('image'),
|
||||
name: i18n.t('interfaces.image.image'),
|
||||
description: i18n.t('interfaces.image.description'),
|
||||
icon: 'insert_photo',
|
||||
component: InterfaceImage,
|
||||
types: ['uuid'],
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceOptions from './interface-options.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'interface-options',
|
||||
name: 'Interface Options',
|
||||
name: i18n.t('interfaces.interface-options.interface-options'),
|
||||
description: i18n.t('interfaces.interface-options.description'),
|
||||
icon: 'box',
|
||||
component: InterfaceOptions,
|
||||
types: ['string'],
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceInterface from './interface.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'interface',
|
||||
name: 'Interface',
|
||||
name: i18n.t('interfaces.interface.interface'),
|
||||
description: i18n.t('interfaces.interface.description'),
|
||||
icon: 'box',
|
||||
component: InterfaceInterface,
|
||||
types: ['string'],
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceManyToMany from './many-to-many.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'many-to-many',
|
||||
name: i18n.t('many_to_many'),
|
||||
name: i18n.t('interfaces.many-to-many.many-to-many'),
|
||||
description: i18n.t('interfaces.many-to-many.description'),
|
||||
icon: 'note_add',
|
||||
component: InterfaceManyToMany,
|
||||
relationship: 'm2m',
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceManyToOne from './many-to-one.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'many-to-one',
|
||||
name: i18n.t('many_to_one'),
|
||||
name: i18n.t('interfaces.many-to-one.many-to-one'),
|
||||
description: i18n.t('interfaces.many-to-one.description'),
|
||||
icon: 'arrow_right_alt',
|
||||
component: InterfaceManyToOne,
|
||||
types: ['uuid', 'string', 'text', 'integer', 'bigInteger'],
|
||||
@@ -11,7 +12,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
options: [
|
||||
{
|
||||
field: 'template',
|
||||
name: i18n.t('display_template'),
|
||||
name: i18n.t('interfaces.many-to-one.display_template'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
|
||||
@@ -3,8 +3,9 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'markdown',
|
||||
name: i18n.t('markdown'),
|
||||
icon: 'text_fields',
|
||||
name: i18n.t('interfaces.markdown.markdown'),
|
||||
description: i18n.t('interfaces.markdown.description'),
|
||||
icon: 'functions',
|
||||
component: InterfaceMarkdown,
|
||||
types: ['text'],
|
||||
options: [
|
||||
@@ -15,15 +16,24 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'tabbed',
|
||||
name: i18n.t('tabbed'),
|
||||
name: i18n.t('interfaces.markdown.tabbed'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.markdown.tabbed_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<v-tabs v-model="currentTab">
|
||||
<v-tab>
|
||||
<v-icon name="code" left />
|
||||
{{ $t('edit') }}
|
||||
{{ $t('interfaces.markdown.edit') }}
|
||||
</v-tab>
|
||||
<v-tab>
|
||||
<v-icon name="visibility" outline left />
|
||||
{{ $t('preview') }}
|
||||
{{ $t('interfaces.markdown.preview') }}
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
</div>
|
||||
@@ -64,7 +64,6 @@ export default defineComponent({
|
||||
.interface-markdown {
|
||||
--v-textarea-min-height: var(--input-height-tall);
|
||||
--v-textarea-max-height: 400px;
|
||||
|
||||
--v-tab-background-color: var(--background-subdued);
|
||||
--v-tab-background-color-active: var(--background-subdued);
|
||||
|
||||
@@ -74,9 +73,9 @@ export default defineComponent({
|
||||
.toolbar {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
background-color: var(--background-subdued);
|
||||
border: var(--border-width) solid var(--border-normal);
|
||||
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
||||
background-color: var(--background-subdued);
|
||||
}
|
||||
|
||||
.v-textarea {
|
||||
|
||||
@@ -3,8 +3,9 @@ import InterfaceNotice from './notice.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'notice',
|
||||
name: i18n.t('notice'),
|
||||
icon: 'remove',
|
||||
name: i18n.t('interfaces.notice.notice'),
|
||||
description: i18n.t('interfaces.notice.description'),
|
||||
icon: 'info',
|
||||
component: InterfaceNotice,
|
||||
hideLabel: true,
|
||||
hideLoader: true,
|
||||
@@ -19,15 +20,18 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'dropdown',
|
||||
default_value: 'normal',
|
||||
options: {
|
||||
items: [
|
||||
{ itemText: i18n.t('normal'), itemValue: 'normal' },
|
||||
{ itemText: i18n.t('info'), itemValue: 'info' },
|
||||
{ itemText: i18n.t('success'), itemValue: 'success' },
|
||||
{ itemText: i18n.t('warning'), itemValue: 'warning' },
|
||||
{ itemText: i18n.t('danger'), itemValue: 'danger' },
|
||||
choices: [
|
||||
{ text: i18n.t('normal'), value: 'normal' },
|
||||
{ text: i18n.t('info'), value: 'info' },
|
||||
{ text: i18n.t('success'), value: 'success' },
|
||||
{ text: i18n.t('warning'), value: 'warning' },
|
||||
{ text: i18n.t('danger'), value: 'danger' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
schema: {
|
||||
default_value: 'normal',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'icon',
|
||||
@@ -36,7 +40,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'text',
|
||||
@@ -45,7 +49,10 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'full',
|
||||
interface: 'textarea',
|
||||
}
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.notice.text'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -3,14 +3,15 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'numeric',
|
||||
name: i18n.t('numeric'),
|
||||
name: i18n.t('interfaces.numeric.numeric'),
|
||||
description: i18n.t('interfaces.numeric.description'),
|
||||
icon: 'dialpad',
|
||||
component: InterfaceNumeric,
|
||||
types: ['integer', 'decimal', 'float', 'bigInteger'],
|
||||
options: [
|
||||
{
|
||||
field: 'min',
|
||||
name: i18n.t('minimum_value'),
|
||||
name: i18n.t('interfaces.numeric.minimum_value'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
@@ -19,7 +20,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'max',
|
||||
name: i18n.t('maximum_value'),
|
||||
name: i18n.t('interfaces.numeric.maximum_value'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
@@ -28,12 +29,15 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'step',
|
||||
name: i18n.t('step_interval'),
|
||||
name: i18n.t('interfaces.numeric.step_interval'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'numeric',
|
||||
},
|
||||
schema: {
|
||||
default_value: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'placeholder',
|
||||
@@ -42,6 +46,9 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -77,6 +84,9 @@ export default defineInterface(({ i18n }) => ({
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'sans-serif',
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -25,7 +25,7 @@ import { defineComponent, PropType } from '@vue/composition-api';
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String],
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
disabled: {
|
||||
|
||||
@@ -3,7 +3,8 @@ import InterfaceOneToMany from './one-to-many.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'one-to-many',
|
||||
name: i18n.t('one_to_many'),
|
||||
name: i18n.t('interfaces.one-to-many.one-to-many'),
|
||||
description: i18n.t('interfaces.one-to-many.description'),
|
||||
icon: 'arrow_right_alt',
|
||||
component: InterfaceOneToMany,
|
||||
types: ['alias'],
|
||||
@@ -17,7 +18,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'tags',
|
||||
width: 'full',
|
||||
options: {
|
||||
placeholder: i18n.t('readable_fields_copy'),
|
||||
placeholder: i18n.t('interfaces.one-to-many.readable_fields_copy'),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,10 +3,12 @@ import InterfaceRadioButtons from './radio-buttons.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'radio-buttons',
|
||||
name: i18n.t('radio_buttons'),
|
||||
name: i18n.t('interfaces.radio-buttons.radio-buttons'),
|
||||
description: i18n.t('interfaces.radio-buttons.description'),
|
||||
icon: 'radio_button_checked',
|
||||
component: InterfaceRadioButtons,
|
||||
types: ['string'],
|
||||
recommendedDisplays: ['badge'],
|
||||
options: [
|
||||
{
|
||||
field: 'choices',
|
||||
@@ -23,6 +25,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
type: 'string',
|
||||
name: i18n.t('text'),
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
},
|
||||
},
|
||||
@@ -31,6 +34,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
type: 'string',
|
||||
name: i18n.t('value'),
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
font: 'monospace',
|
||||
@@ -50,8 +54,8 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'icon',
|
||||
},
|
||||
schema: {
|
||||
default_value: 'radio_button_checked',
|
||||
},
|
||||
default_value: 'radio_button_checked'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'iconOff',
|
||||
@@ -62,8 +66,8 @@ export default defineInterface(({ i18n }) => ({
|
||||
interface: 'icon',
|
||||
},
|
||||
schema: {
|
||||
default_value: 'radio_button_unchecked',
|
||||
},
|
||||
default_value: 'radio_button_unchecked'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'color',
|
||||
@@ -73,19 +77,16 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'half',
|
||||
interface: 'color',
|
||||
},
|
||||
schema: {
|
||||
default_value: '#2f80ed',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'allowOther',
|
||||
name: i18n.t('allow_other'),
|
||||
name: i18n.t('interfaces.dropdown.allow_other'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('enable_custom_values'),
|
||||
label: i18n.t('interfaces.dropdown.allow_other_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
|
||||
@@ -4,7 +4,8 @@ import RepeaterOptions from './options.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'repeater',
|
||||
name: i18n.t('repeater'),
|
||||
name: i18n.t('interfaces.repeater.repeater'),
|
||||
description: i18n.t('interfaces.repeater.description'),
|
||||
icon: 'replay',
|
||||
component: InterfaceRepeater,
|
||||
types: ['json'],
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
<p class="type-label">Template</p>
|
||||
<v-input class="input" v-model="template" :placeholder="`{{ field }}`" />
|
||||
<div class="grid">
|
||||
<div class="grid-element full">
|
||||
<p class="type-label">{{ $t('template') }}</p>
|
||||
<v-input class="input" v-model="template" :placeholder="`{{ field }}`" />
|
||||
</div>
|
||||
|
||||
<p class="type-label">Fields</p>
|
||||
<repeater v-model="repeaterValue" :template="`{{ field }} — {{ interface }}`" :fields="repeaterFields" />
|
||||
<div class="grid-element full">
|
||||
<p class="type-label">{{ $t('interfaces.repeater.edit_fields') }}</p>
|
||||
<repeater
|
||||
v-model="repeaterValue"
|
||||
:template="`{{ field }} — {{ interface }}`"
|
||||
:fields="repeaterFields"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid-element full">
|
||||
<p class="type-label">{{ $t('interfaces.repeater.add_label') }}</p>
|
||||
<v-input class="input" v-model="addLabel" :placeholder="$t('add_a_new_item')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -127,17 +142,37 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
|
||||
return { repeaterValue, repeaterFields, template };
|
||||
const addLabel = computed({
|
||||
get() {
|
||||
return props.value?.addLabel;
|
||||
},
|
||||
set(newAddLabel: string) {
|
||||
emit('input', {
|
||||
...(props.value || {}),
|
||||
addLabel: newAddLabel,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return { repeaterValue, repeaterFields, template, addLabel };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: [start] minmax(0, 1fr) [half] minmax(0, 1fr) [full];
|
||||
gap: var(--form-vertical-gap) var(--form-horizontal-gap);
|
||||
|
||||
&-element {
|
||||
&.full {
|
||||
grid-column: start/full;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.type-label {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</draggable>
|
||||
<button @click="addNew" class="add-new" v-if="showAddNew">
|
||||
<v-icon name="add" />
|
||||
{{ createItemText }}
|
||||
{{ addLabel }}
|
||||
</button>
|
||||
</v-item-group>
|
||||
</template>
|
||||
@@ -42,7 +42,7 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
createItemText: {
|
||||
addLabel: {
|
||||
type: String,
|
||||
default: i18n.t('add_a_new_item'),
|
||||
},
|
||||
@@ -60,7 +60,7 @@ export default defineComponent({
|
||||
if (props.disabled) return false;
|
||||
if (props.value === null) return true;
|
||||
if (props.limit === null) return true;
|
||||
if (Array.isArray(props.value) && props.value.length <= props.limit) return true;
|
||||
if (Array.isArray(props.value) && props.value.length < props.limit) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
@@ -3,37 +3,38 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'slider',
|
||||
name: i18n.t('slider'),
|
||||
name: i18n.t('interfaces.slider.slider'),
|
||||
description: i18n.t('interfaces.slider.description'),
|
||||
icon: 'linear_scale',
|
||||
component: InterfaceSlider,
|
||||
types: ['integer', 'decimal', 'float', 'bigInteger'],
|
||||
options: [
|
||||
{
|
||||
field: 'minValue',
|
||||
name: i18n.t('minimum_value'),
|
||||
name: i18n.t('interfaces.numeric.minimum_value'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'numeric',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'maxValue',
|
||||
name: i18n.t('maximum_value'),
|
||||
name: i18n.t('interfaces.numeric.maximum_value'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'numeric',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'stepInterval',
|
||||
name: i18n.t('step_interval'),
|
||||
name: i18n.t('interfaces.numeric.step_interval'),
|
||||
type: 'integer',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'numeric',
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -3,9 +3,40 @@ import InterfaceSlug from './slug.vue';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'slug',
|
||||
name: i18n.t('slug'),
|
||||
name: i18n.t('interfaces.slug.slug'),
|
||||
description: i18n.t('interfaces.slug.description'),
|
||||
icon: 'link',
|
||||
component: InterfaceSlug,
|
||||
types: ['string'],
|
||||
options: [],
|
||||
options: [
|
||||
{
|
||||
field: 'placeholder',
|
||||
name: i18n.t('placeholder'),
|
||||
meta: {
|
||||
width: 'full',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'iconLeft',
|
||||
name: i18n.t('icon_left'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'iconRight',
|
||||
name: i18n.t('icon_right'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<template>
|
||||
<v-input :value="value" :disabled="disabled" @input="$emit('input', $event)" slug />
|
||||
<v-input
|
||||
:value="value"
|
||||
:disabled="disabled"
|
||||
:placeholder="placeholder"
|
||||
:iconLeft="iconLeft"
|
||||
:iconRight="iconRight"
|
||||
@input="$emit('input', $event)"
|
||||
slug
|
||||
>
|
||||
<template v-if="iconLeft" #prepend><v-icon :name="iconLeft" /></template>
|
||||
<template v-if="iconRight" #append><v-icon :name="iconRight" /></template>
|
||||
</v-input>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -15,6 +26,18 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: null,
|
||||
},
|
||||
iconLeft: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
iconRight: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,8 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'tags',
|
||||
name: i18n.t('tags'),
|
||||
name: i18n.t('interfaces.tags.tags'),
|
||||
description: i18n.t('interfaces.tags.description'),
|
||||
icon: 'local_offer',
|
||||
component: InterfaceTags,
|
||||
types: ['json'],
|
||||
@@ -19,27 +20,33 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'alphabetize',
|
||||
name: i18n.t('alphabetize'),
|
||||
name: i18n.t('interfaces.tags.alphabetize'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('force_alphabetical_order'),
|
||||
label: i18n.t('interfaces.tags.alphabetize_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'lowercase',
|
||||
name: i18n.t('lowercase'),
|
||||
name: i18n.t('interfaces.tags.lowercase'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('force_lowercase'),
|
||||
label: i18n.t('interfaces.tags.lowercase_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'placeholder',
|
||||
@@ -48,19 +55,25 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'allowCustom',
|
||||
name: i18n.t('allow_other'),
|
||||
name: i18n.t('interfaces.dropdown.allow_other'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('enable_custom_values'),
|
||||
label: i18n.t('interfaces.dropdown.allow_other_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'iconLeft',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="interface-tags">
|
||||
<v-input
|
||||
:placeholder="placeholder || $t('add_tags')"
|
||||
:placeholder="placeholder || $t('interfaces.tags.add_tags')"
|
||||
@keydown="onInput"
|
||||
:disabled="disabled"
|
||||
v-if="allowCustom"
|
||||
|
||||
@@ -3,7 +3,8 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'text-input',
|
||||
name: i18n.t('text_input'),
|
||||
name: i18n.t('interfaces.text-input.text-input'),
|
||||
description: i18n.t('interfaces.text-input.description'),
|
||||
icon: 'text_fields',
|
||||
component: InterfaceTextInput,
|
||||
types: ['string', 'uuid'],
|
||||
@@ -15,17 +16,17 @@ export default defineInterface(({ i18n }) => ({
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('text_shown_when_no_value'),
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'font',
|
||||
name: i18n.t('font'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'dropdown',
|
||||
default: 'sans-serif',
|
||||
options: {
|
||||
choices: [
|
||||
{ text: i18n.t('sans_serif'), value: 'sans-serif' },
|
||||
@@ -34,10 +35,14 @@ export default defineInterface(({ i18n }) => ({
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'sans-serif',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'iconLeft',
|
||||
name: i18n.t('icon_left'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
@@ -46,10 +51,41 @@ export default defineInterface(({ i18n }) => ({
|
||||
{
|
||||
field: 'iconRight',
|
||||
name: i18n.t('icon_right'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'trim',
|
||||
name: i18n.t('interfaces.text-input.trim'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.text-input.trim_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'masked',
|
||||
name: i18n.t('interfaces.text-input.mask'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.text-input.mask_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:trim="trim"
|
||||
:type="masked ? 'password' : 'text'"
|
||||
:class="font"
|
||||
:maxlength="length"
|
||||
@input="$listeners.input"
|
||||
>
|
||||
<template v-if="iconLeft" #prepend><v-icon :name="iconLeft" /></template>
|
||||
@@ -67,7 +67,7 @@ export default defineComponent({
|
||||
default: 'sans-serif',
|
||||
},
|
||||
length: {
|
||||
type: [Number, String],
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,7 +3,8 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'textarea',
|
||||
name: i18n.t('textarea'),
|
||||
name: i18n.t('interfaces.textarea.textarea'),
|
||||
description: i18n.t('interfaces.textarea.description'),
|
||||
icon: 'text_fields',
|
||||
component: InterfaceTextarea,
|
||||
types: ['text'],
|
||||
@@ -11,27 +12,47 @@ export default defineInterface(({ i18n }) => ({
|
||||
{
|
||||
field: 'placeholder',
|
||||
name: i18n.t('placeholder'),
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('enter_a_placeholder'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'trim',
|
||||
name: i18n.t('trim'),
|
||||
width: 'half',
|
||||
interface: 'switch',
|
||||
name: i18n.t('interfaces.text-input.trim'),
|
||||
type: 'boolean',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'toggle',
|
||||
options: {
|
||||
label: i18n.t('interfaces.text-input.trim_label'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'font',
|
||||
name: i18n.t('font'),
|
||||
width: 'half',
|
||||
interface: 'dropdown',
|
||||
default: 'sans-serif',
|
||||
options: {
|
||||
choices: [
|
||||
{ text: i18n.t('sans_serif'), value: 'sans-serif' },
|
||||
{ text: i18n.t('monospace'), value: 'monospace' },
|
||||
{ text: i18n.t('serif'), value: 'serif' },
|
||||
],
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'dropdown',
|
||||
options: {
|
||||
choices: [
|
||||
{ text: i18n.t('sans_serif'), value: 'sans-serif' },
|
||||
{ text: i18n.t('monospace'), value: 'monospace' },
|
||||
{ text: i18n.t('serif'), value: 'serif' },
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'sans-serif',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -40,15 +40,15 @@ export default defineComponent({
|
||||
<style lang="scss" scoped>
|
||||
.v-textarea {
|
||||
&.monospace {
|
||||
--v-input-font-family: var(--family-monospace);
|
||||
--v-textarea-font-family: var(--family-monospace);
|
||||
}
|
||||
|
||||
&.serif {
|
||||
--v-input-font-family: var(--family-serif);
|
||||
--v-textarea-font-family: var(--family-serif);
|
||||
}
|
||||
|
||||
&.sans-serif {
|
||||
--v-input-font-family: var(--family-sans-serif);
|
||||
--v-textarea-font-family: var(--family-sans-serif);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,7 +3,8 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'toggle',
|
||||
name: i18n.t('toggle'),
|
||||
name: i18n.t('interfaces.toggle.toggle'),
|
||||
description: i18n.t('interfaces.toggle.description'),
|
||||
icon: 'check_box',
|
||||
component: InterfaceToggle,
|
||||
types: ['boolean'],
|
||||
@@ -15,8 +16,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
default_value: 'check_box_outline_blank',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'iconOn',
|
||||
@@ -25,8 +25,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'icon',
|
||||
default_value: 'check_box',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'label',
|
||||
@@ -35,8 +34,13 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'text-input',
|
||||
options: {
|
||||
placeholder: i18n.t('interfaces.toggle.label_placeholder'),
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: i18n.t('active'),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'color',
|
||||
@@ -45,8 +49,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'color',
|
||||
default_value: 'var(--primary)',
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
@@ -3,9 +3,31 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'user',
|
||||
name: i18n.t('user'),
|
||||
name: i18n.t('interfaces.user.user'),
|
||||
description: i18n.t('interfaces.user.description'),
|
||||
icon: 'person',
|
||||
component: InterfaceUser,
|
||||
types: ['uuid'],
|
||||
options: [],
|
||||
options: [
|
||||
{
|
||||
field: 'selectMode',
|
||||
name: i18n.t('interfaces.user.select_mode'),
|
||||
type: 'string',
|
||||
meta: {
|
||||
width: 'full',
|
||||
interface: 'dropdown',
|
||||
options: {
|
||||
choices: [
|
||||
{ text: i18n.t('interfaces.user.modes.auto'), value: 'auto' },
|
||||
{ text: i18n.t('interfaces.user.modes.dropdown'), value: 'dropdown' },
|
||||
{ text: i18n.t('interfaces.user.modes.modal'), value: 'modal' },
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'auto',
|
||||
},
|
||||
},
|
||||
],
|
||||
recommendedDisplays: ['user'],
|
||||
}));
|
||||
|
||||
@@ -102,7 +102,7 @@ export default defineComponent({
|
||||
components: { ModalDetail, ModalBrowse },
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, Object],
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
template: {
|
||||
@@ -162,7 +162,7 @@ export default defineComponent({
|
||||
(newValue) => {
|
||||
// When the newly configured value is a primitive, assume it's the primary key
|
||||
// of the item and fetch it from the API to render the preview
|
||||
if (newValue !== null && newValue !== currentUser.value?.id && typeof newValue === 'number') {
|
||||
if (newValue !== null && newValue !== currentUser.value?.id && typeof newValue === 'string') {
|
||||
fetchCurrent();
|
||||
}
|
||||
|
||||
@@ -178,16 +178,8 @@ export default defineComponent({
|
||||
const currentPrimaryKey = computed<string | number>(() => {
|
||||
if (!currentUser.value) return '+';
|
||||
if (!props.value) return '+';
|
||||
|
||||
if (typeof props.value === 'number' || typeof props.value === 'string') {
|
||||
return props.value;
|
||||
}
|
||||
|
||||
if (typeof props.value === 'object' && props.value.hasOwnProperty('id')) {
|
||||
return props.value.id;
|
||||
}
|
||||
|
||||
return '+';
|
||||
|
||||
return props.value;
|
||||
});
|
||||
|
||||
return { setCurrent, currentUser, loading, currentPrimaryKey };
|
||||
@@ -312,15 +304,7 @@ export default defineComponent({
|
||||
const selection = computed<(number | string)[]>(() => {
|
||||
if (!props.value) return [];
|
||||
|
||||
if (typeof props.value === 'object' && props.value.hasOwnProperty('id')) {
|
||||
return [props.value.id];
|
||||
}
|
||||
|
||||
if (typeof props.value === 'string' || typeof props.value === 'number') {
|
||||
return [props.value];
|
||||
}
|
||||
|
||||
return [];
|
||||
return [props.value];
|
||||
});
|
||||
|
||||
return { selection, stageSelection, selectModalActive };
|
||||
|
||||
@@ -3,14 +3,15 @@ import { defineInterface } from '@/interfaces/define';
|
||||
|
||||
export default defineInterface(({ i18n }) => ({
|
||||
id: 'wysiwyg',
|
||||
name: i18n.t('wysiwyg'),
|
||||
name: i18n.t('interfaces.wysiwyg.wysiwyg'),
|
||||
description: i18n.t('interfaces.wysiwyg.description'),
|
||||
icon: 'format_quote',
|
||||
component: InterfaceWYSIWYG,
|
||||
types: ['text'],
|
||||
options: [
|
||||
{
|
||||
field: 'toolbar',
|
||||
name: i18n.t('toolbar'),
|
||||
name: i18n.t('interfaces.wysiwyg.toolbar'),
|
||||
type: 'json',
|
||||
schema: {
|
||||
default_value: [
|
||||
@@ -224,7 +225,6 @@ export default defineInterface(({ i18n }) => ({
|
||||
meta: {
|
||||
width: 'half',
|
||||
interface: 'dropdown',
|
||||
default: 'sans-serif',
|
||||
options: {
|
||||
choices: [
|
||||
{ text: i18n.t('sans_serif'), value: 'sans-serif' },
|
||||
@@ -233,10 +233,13 @@ export default defineInterface(({ i18n }) => ({
|
||||
],
|
||||
},
|
||||
},
|
||||
schema: {
|
||||
default_value: 'sans-serif',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'customFormats',
|
||||
name: i18n.t('custom_formats'),
|
||||
name: i18n.t('interfaces.wysiwyg.custom_formats'),
|
||||
type: 'json',
|
||||
meta: {
|
||||
interface: 'code',
|
||||
@@ -258,7 +261,7 @@ export default defineInterface(({ i18n }) => ({
|
||||
},
|
||||
{
|
||||
field: 'tinymceOverrides',
|
||||
name: i18n.t('options_override'),
|
||||
name: i18n.t('interfaces.wysiwyg.options_override'),
|
||||
type: 'json',
|
||||
meta: {
|
||||
interface: 'code',
|
||||
|
||||
@@ -1,16 +1,83 @@
|
||||
{
|
||||
"displays": {
|
||||
"icon": {
|
||||
"icon": "Icon"
|
||||
"collection": {
|
||||
"collection": "Collection",
|
||||
"description": "Display a collection.",
|
||||
"icon_label": "Show the collection's icon"
|
||||
},
|
||||
"format-title": {
|
||||
"format-title": "Format Title"
|
||||
"color-dot": {
|
||||
"color-dot": "Color Dot",
|
||||
"description": "Display a colored dot.",
|
||||
"default_color": "Default Color",
|
||||
"choices_note": "Set colors relative to the text."
|
||||
},
|
||||
"datetime": {
|
||||
"datetime": "Datetime",
|
||||
"description": "Display values related to time.",
|
||||
"relative": "Relative",
|
||||
"relative_label": "Show relative time, eg: 5 minutes ago"
|
||||
},
|
||||
"file": {
|
||||
"file": "File",
|
||||
"description": "Display files."
|
||||
},
|
||||
"filesize": {
|
||||
"filesize": "File Size",
|
||||
"description": "Display the size of a file."
|
||||
},
|
||||
"formatted-value": {
|
||||
"formatted-value": "Formatted Value",
|
||||
"description": "Display a formatted version of the text.",
|
||||
"format_title": "Format Title",
|
||||
"format_title_label": "Auto-format casing",
|
||||
"bold_label": "Use bold style"
|
||||
},
|
||||
"icon": {
|
||||
"icon": "Icon",
|
||||
"description": "Display an icon.",
|
||||
"filled": "Filled",
|
||||
"filled_label": "Use the filled variant"
|
||||
},
|
||||
"image": {
|
||||
"image": "Image",
|
||||
"description": "Display a tiny image preview.",
|
||||
"circle": "Circle",
|
||||
"circle_label": "Display as a circle"
|
||||
},
|
||||
"labels": {
|
||||
"labels": "Labels",
|
||||
"description": "Display either a single or a list of labels.",
|
||||
"default_foreground": "Default Foreground",
|
||||
"default_background": "Default Background",
|
||||
"format_label": "Format each label"
|
||||
|
||||
},
|
||||
"mime-type": {
|
||||
"mime-type": "MIME Type",
|
||||
"description": "Show the MIME-Type of a file.",
|
||||
"extension_only": "Extension Only",
|
||||
"extension_only_label": "Only show the file extension"
|
||||
},
|
||||
"rating": {
|
||||
"rating": "Rating"
|
||||
"rating": "Rating",
|
||||
"description": "Visualize a number as stars relative to the max-value.",
|
||||
"simple": "Simple",
|
||||
"simple_label": "Show stars in a simple format."
|
||||
},
|
||||
"raw": {
|
||||
"raw": "Raw Value"
|
||||
},
|
||||
"related-values": {
|
||||
"related-values": "Related Values",
|
||||
"description": "Display relative values."
|
||||
},
|
||||
"user": {
|
||||
"user": "User",
|
||||
"description": "Display a directus user.",
|
||||
"avatar": "Avatar",
|
||||
"name": "Name",
|
||||
"both": "Both",
|
||||
"circle_label": "Show user in a circle"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
"translations": "Translations",
|
||||
"note": "Note",
|
||||
"enter_a_value": "Enter a value...",
|
||||
"enter_a_placeholder": "Enter a placeholder...",
|
||||
"length": "Length",
|
||||
"required": "Required",
|
||||
"readonly": "Readonly",
|
||||
@@ -344,6 +345,8 @@
|
||||
"notice": "Notice",
|
||||
"slug": "Slug",
|
||||
"repeater": "Repeater",
|
||||
"max-amount": "Max Amount",
|
||||
"select_mode": "Select Mode",
|
||||
|
||||
"months": {
|
||||
"january": "January",
|
||||
@@ -404,6 +407,8 @@
|
||||
"primary_key_field": "Primary Key Field",
|
||||
"type": "Type",
|
||||
"number": "Number",
|
||||
"true": "True",
|
||||
"false": "False",
|
||||
"creating_new_collection": "Creating New Collection",
|
||||
"status": "Status",
|
||||
"sort": "Sort",
|
||||
@@ -520,6 +525,7 @@
|
||||
|
||||
"formatted_value": "Formatted Value",
|
||||
"format_title": "Format Title",
|
||||
"inline_title": "Inline Title",
|
||||
"auto_format_casing": "Auto-format casing",
|
||||
|
||||
"errors": {
|
||||
@@ -623,6 +629,7 @@
|
||||
"step_interval": "Step Interval",
|
||||
"icon_left": "Icon Left",
|
||||
"icon_right": "Icon Right",
|
||||
"trimed": "Trimed",
|
||||
"font_family": "Font Family",
|
||||
"font": "Font",
|
||||
"numeric": "Numeric",
|
||||
@@ -734,6 +741,7 @@
|
||||
"role_only": "Role Only",
|
||||
"update": "Update",
|
||||
|
||||
"edit_fields": "Edit Fields",
|
||||
"select_fields": "Select Fields",
|
||||
"readable_fields": "Readable Fields",
|
||||
"writable_fields": "Writable Fields",
|
||||
@@ -745,9 +753,6 @@
|
||||
"tags": "Tags",
|
||||
"format_text": "Format Text",
|
||||
|
||||
"outline": "Outline",
|
||||
"use_outline_variant": "Use the outline variant",
|
||||
|
||||
"bold": "Bold",
|
||||
"subdued": "Subdued",
|
||||
|
||||
|
||||
@@ -1,5 +1,189 @@
|
||||
{
|
||||
"interfaces": {
|
||||
|
||||
"checkboxes": {
|
||||
"checkboxes": "Checkboxes",
|
||||
"description": "Choose between multiple options via checkboxes.",
|
||||
"allow_other": "Allow Other",
|
||||
"enable_custom_values": "Enable custom values"
|
||||
},
|
||||
"code": {
|
||||
"code": "Code",
|
||||
"description": "Write or share code snippets.",
|
||||
"line_number": "Line Number",
|
||||
"placeholder": "Enter code here..."
|
||||
},
|
||||
"collections": {
|
||||
"collections": "Collections",
|
||||
"description": "Select between existing collections.",
|
||||
"include_system_collections": "Include System Collections"
|
||||
},
|
||||
"color": {
|
||||
"color": "Color",
|
||||
"description": "Enter color values.",
|
||||
"placeholder": "Choose a color...",
|
||||
"preset_colors": "Preset Colors",
|
||||
"preset_colors_placeholder": "Add a new color..."
|
||||
},
|
||||
"datetime": {
|
||||
"datetime": "Datetime",
|
||||
"description": "Enter dates and times.",
|
||||
"include_seconds": "Include Seconds",
|
||||
"set_to_now": "Set to Now"
|
||||
},
|
||||
"display-template": {
|
||||
"display-template": "Display Template",
|
||||
"description": "Mix text with field values.",
|
||||
"collection_field": "Collection field",
|
||||
"collection_field_not_setup": "The collection field option is misconfigured",
|
||||
"select_a_collection": "Select a Collection"
|
||||
},
|
||||
"divider": {
|
||||
"divider": "Divider",
|
||||
"description": "Divide fields into seperate sections.",
|
||||
"title_placeholder": "Enter a title...",
|
||||
"inline_title": "Inline Title",
|
||||
"inline_title_label": "Show title inside line."
|
||||
},
|
||||
"dropdown": {
|
||||
"dropdown": "Dropdown",
|
||||
"description": "Select a value from a dropdown.",
|
||||
"choices_placeholder": "Add a new choice",
|
||||
"allow_other": "Allow Other",
|
||||
"allow_other_label": "Allow other values",
|
||||
"allow_none": "Allow None",
|
||||
"allow_none_label": "Allow no selection"
|
||||
},
|
||||
"dropdown-multiselect": {
|
||||
"dropdown-multiselect": "Dropdown (Multiple)",
|
||||
"description": "Select multiple values of a dropdown."
|
||||
},
|
||||
"file": {
|
||||
"file": "File",
|
||||
"description": "Select or upload a file."
|
||||
},
|
||||
"files": {
|
||||
"files": "Files",
|
||||
"description": "Select or upload multiple files."
|
||||
},
|
||||
"hash": {
|
||||
"hash": "Hash",
|
||||
"description": "Enter a hash.",
|
||||
"masked": "Masked",
|
||||
"masked_label": "Hide the true values"
|
||||
},
|
||||
"icon": {
|
||||
"icon": "Icon",
|
||||
"description": "Select an icon from a dropdown.",
|
||||
"search_for_icon": "Search for icon..."
|
||||
},
|
||||
"image": {
|
||||
"image": "Image",
|
||||
"description": "Select or upload an image."
|
||||
},
|
||||
"interface": {
|
||||
"interface": "Interface",
|
||||
"description": "Select an existing interface."
|
||||
},
|
||||
"interface-options": {
|
||||
"interface-options": "Interface Options",
|
||||
"description": "A modal for selecting options of an interface."
|
||||
},
|
||||
"many-to-many": {
|
||||
"many-to-many": "Many to Many",
|
||||
"description": "Select related items."
|
||||
},
|
||||
"many-to-one": {
|
||||
"many-to-one": "Many to One",
|
||||
"description": "Select a single related item.",
|
||||
"display_template": "Display Template"
|
||||
},
|
||||
"markdown": {
|
||||
"markdown": "Markdown",
|
||||
"description": "Enter and preview markdown.",
|
||||
"tabbed": "Tabbed",
|
||||
"tabbed_label": "Show preview in separate tab",
|
||||
"edit": "Edit",
|
||||
"preview": "Preview"
|
||||
},
|
||||
"notice": {
|
||||
"notice": "Notice",
|
||||
"description": "Display a short notice.",
|
||||
"text": "Enter notice content here..."
|
||||
},
|
||||
"numeric": {
|
||||
"numeric": "Numeric",
|
||||
"description": "Enter a number.",
|
||||
"minimum_value": "Minimum Value",
|
||||
"maximum_value": "Maximum Value",
|
||||
"step_interval": "Step Interval"
|
||||
},
|
||||
"one-to-many": {
|
||||
"one-to-many": "One to Many",
|
||||
"description": "Select related items.",
|
||||
"readable_fields_copy": "Select the fields that the user can view"
|
||||
},
|
||||
"radio-buttons": {
|
||||
"radio-buttons": "Radio Buttons",
|
||||
"description": "Select one of multiple choices."
|
||||
},
|
||||
"repeater": {
|
||||
"repeater": "Repeater",
|
||||
"description": "Have multiple entires of the same structure.",
|
||||
"max_amount": "Maximum Amount",
|
||||
"max_amount_placeholder": "Maximum amount of items...",
|
||||
"edit_fields": "Edit Fields",
|
||||
"add_label": "\"Add New Row\" Label"
|
||||
},
|
||||
"slider": {
|
||||
"slider": "Slider",
|
||||
"description": "Select a number using a slider."
|
||||
},
|
||||
"slug": {
|
||||
"slug": "Slug",
|
||||
"description": "Enter a word connected with hyphens."
|
||||
},
|
||||
"tags": {
|
||||
"tags": "Tags",
|
||||
"description": "Select or add tags.",
|
||||
"lowercase": "Lowercase",
|
||||
"lowercase_label": "Force Lowercase",
|
||||
"alphabetize": "Alphabetize",
|
||||
"alphabetize_label": "Force Alphabetical Order",
|
||||
"add_tags": "Add tags..."
|
||||
},
|
||||
"text-input": {
|
||||
"text-input": "Text Input",
|
||||
"description": "Enter a single line text.",
|
||||
"trim": "Trimed",
|
||||
"trim_label": "Trim the start and end",
|
||||
"mask": "Masked",
|
||||
"mask_label": "Hide the real value"
|
||||
},
|
||||
"textarea": {
|
||||
"textarea": "Textarea",
|
||||
"description": "Enter multiline text."
|
||||
},
|
||||
"toggle": {
|
||||
"toggle": "Toggle",
|
||||
"description": "Switch between an on and off state.",
|
||||
"label_placeholder": "Enter a label..."
|
||||
},
|
||||
"user": {
|
||||
"user": "User",
|
||||
"description": "Select an existing directus user.",
|
||||
"select_mode": "Select Mode",
|
||||
"modes": {
|
||||
"auto": "Auto",
|
||||
"dropdown": "Dropdown",
|
||||
"modal": "Modal"
|
||||
}
|
||||
},
|
||||
"wysiwyg": {
|
||||
"wysiwyg": "WYSIWYG",
|
||||
"description": "A text editor for writing complex text.",
|
||||
"toolbar": "Toolbar",
|
||||
"custom_formats": "Custom Formats",
|
||||
"options_override": "Options Override"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,10 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const selectItems = computed(() => {
|
||||
const recommended = clone(selectedInterface.value?.recommendedDisplays) || [];
|
||||
let recommended = clone(selectedInterface.value?.recommendedDisplays) || [];
|
||||
|
||||
recommended.push('raw', 'formatted-value');
|
||||
recommended = [...new Set(recommended)];
|
||||
|
||||
const displayItems: FancySelectItem[] = availableDisplays.value.map((display) => {
|
||||
const item: FancySelectItem = {
|
||||
@@ -71,15 +72,23 @@ export default defineComponent({
|
||||
return item;
|
||||
});
|
||||
|
||||
if (displayItems.length >= 5 && recommended.length > 0) {
|
||||
return [
|
||||
...recommended.map((key) => displayItems.find((item) => item.value === key)),
|
||||
{ divider: true },
|
||||
...displayItems.filter((item) => recommended.includes(item.value as string) === false),
|
||||
].filter((i) => i);
|
||||
} else {
|
||||
return displayItems;
|
||||
const recommendedItems: (FancySelectItem | { divider: boolean } | undefined)[] = [];
|
||||
|
||||
const recommendedList = recommended.map((key) => displayItems.find((item) => item.value === key));
|
||||
if (recommendedList !== undefined) {
|
||||
recommendedItems.push(...recommendedList.filter((i) => i));
|
||||
}
|
||||
|
||||
if (displayItems.length >= 5 && recommended.length > 0) {
|
||||
recommendedItems.push({ divider: true });
|
||||
}
|
||||
|
||||
const displayList = displayItems.filter((item) => recommended.includes(item.value as string) === false);
|
||||
if (displayList !== undefined) {
|
||||
recommendedItems.push(...displayList.filter((i) => i));
|
||||
}
|
||||
|
||||
return recommendedItems;
|
||||
});
|
||||
|
||||
const selectedDisplay = computed(() => {
|
||||
|
||||
@@ -64,7 +64,7 @@ export default defineComponent({
|
||||
datetime: ['datetime'],
|
||||
date: ['datetime'],
|
||||
time: ['datetime'],
|
||||
json: ['code'],
|
||||
json: ['checkboxes', 'tags'],
|
||||
uuid: ['text-input'],
|
||||
};
|
||||
|
||||
@@ -85,15 +85,23 @@ export default defineComponent({
|
||||
return item;
|
||||
});
|
||||
|
||||
if (interfaceItems.length >= 5 && recommended.length > 0) {
|
||||
return [
|
||||
...recommended.map((key) => interfaceItems.find((item) => item.value === key)),
|
||||
{ divider: true },
|
||||
...interfaceItems.filter((item) => recommended.includes(item.value as string) === false),
|
||||
].filter((i) => i);
|
||||
} else {
|
||||
return interfaceItems;
|
||||
const recommendedItems: (FancySelectItem | { divider: boolean } | undefined)[] = [];
|
||||
|
||||
const recommendedList = recommended.map((key) => interfaceItems.find((item) => item.value === key));
|
||||
if (recommendedList !== undefined) {
|
||||
recommendedItems.push(...recommendedList.filter((i) => i));
|
||||
}
|
||||
|
||||
if (interfaceItems.length >= 5 && recommended.length > 0) {
|
||||
recommendedItems.push({ divider: true });
|
||||
}
|
||||
|
||||
const interfaceList = interfaceItems.filter((item) => recommended.includes(item.value as string) === false);
|
||||
if (interfaceList !== undefined) {
|
||||
recommendedItems.push(...interfaceList.filter((i) => i));
|
||||
}
|
||||
|
||||
return recommendedItems;
|
||||
});
|
||||
|
||||
const selectedInterface = computed(() => {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
:value="fieldData.type"
|
||||
:items="typesWithLabels"
|
||||
:placeholder="typePlaceholder"
|
||||
@input="setType"
|
||||
@input="fieldData.type = $event"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -40,11 +40,45 @@
|
||||
</div>
|
||||
|
||||
<!-- @todo base default value field type on selected type -->
|
||||
<div class="field" v-if="fieldData.schema">
|
||||
<div class="field" v-if="fieldData.schema" :class="{ full: ['text', 'json'].includes(fieldData.type) }">
|
||||
<div class="label type-label">{{ $t('default_value') }}</div>
|
||||
<v-input
|
||||
v-if="['string', 'uuid'].includes(fieldData.type)"
|
||||
class="monospace"
|
||||
v-model="fieldData.schema.default_value"
|
||||
v-model="defaultValue"
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
<v-textarea
|
||||
v-else-if="['text', 'json'].includes(fieldData.type)"
|
||||
class="monospace"
|
||||
v-model="defaultValue"
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
<v-input
|
||||
v-else-if="['integer', 'bigInteger', 'float', 'decimal'].includes(fieldData.type)"
|
||||
type="number"
|
||||
class="monospace"
|
||||
v-model="defaultValue"
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
<v-input
|
||||
v-else-if="['timestamp', 'datetime', 'date', 'time'].includes(fieldData.type)"
|
||||
class="monospace"
|
||||
v-model="defaultValue"
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
<v-checkbox
|
||||
v-else-if="fieldData.type === 'boolean'"
|
||||
class="monospace"
|
||||
v-model="defaultValue"
|
||||
:label="defaultValue ? $t('true') : $t('false')"
|
||||
block
|
||||
/>
|
||||
<v-input
|
||||
v-else
|
||||
class="monospace"
|
||||
v-model="defaultValue"
|
||||
disabled
|
||||
:placeholder="$t('add_a_default_value')"
|
||||
/>
|
||||
</div>
|
||||
@@ -201,23 +235,22 @@ export default defineComponent({
|
||||
return i18n.t('choose_a_type');
|
||||
});
|
||||
|
||||
return { fieldData: state.fieldData, typesWithLabels, setType, typeDisabled, typePlaceholder };
|
||||
const defaultValue = computed({
|
||||
get() {
|
||||
return state.fieldData.schema.default_value;
|
||||
},
|
||||
set(newVal: any) {
|
||||
state.fieldData.schema.default_value = newVal;
|
||||
},
|
||||
});
|
||||
|
||||
function setType(value: typeof types[number]) {
|
||||
if (value === 'uuid') {
|
||||
state.fieldData.meta.special = 'uuid';
|
||||
} else {
|
||||
state.fieldData.meta.special = null;
|
||||
}
|
||||
|
||||
// We'll reset the interface/display as they most likely won't work for the newly selected
|
||||
// type
|
||||
state.fieldData.meta.interface = null;
|
||||
state.fieldData.meta.options = null;
|
||||
state.fieldData.meta.display = null;
|
||||
state.fieldData.meta.display_options = null;
|
||||
state.fieldData.type = value;
|
||||
}
|
||||
return {
|
||||
fieldData: state.fieldData,
|
||||
typesWithLabels,
|
||||
typeDisabled,
|
||||
typePlaceholder,
|
||||
defaultValue,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -291,6 +291,34 @@ function initLocalStore(
|
||||
delete state.fieldData.type;
|
||||
state.fieldData.meta.special = 'alias';
|
||||
}
|
||||
|
||||
if (type === 'standard') {
|
||||
watch(
|
||||
() => state.fieldData.type,
|
||||
() => {
|
||||
state.fieldData.meta.interface = null;
|
||||
state.fieldData.meta.options = null;
|
||||
state.fieldData.meta.display = null;
|
||||
state.fieldData.meta.display_options = null;
|
||||
state.fieldData.meta.special = null;
|
||||
state.fieldData.schema.default_value = undefined;
|
||||
|
||||
switch (state.fieldData.type) {
|
||||
case 'uuid':
|
||||
state.fieldData.meta.special = 'uuid';
|
||||
break;
|
||||
case 'json':
|
||||
state.fieldData.meta.special = 'json';
|
||||
break;
|
||||
case 'boolean':
|
||||
state.fieldData.meta.special = 'boolean';
|
||||
state.fieldData.schema.is_nullable = false;
|
||||
state.fieldData.schema.default_value = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function clearLocalStore() {
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
transition: all var(--fast) var(--transition);
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-placeholder{
|
||||
color: var(--foreground-subdued);
|
||||
}
|
||||
|
||||
.CodeMirror:hover {
|
||||
border-color: var(--border-normal-alt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user