Add support for Conditional Fields (#6864)

* Add conditions field to directus_fields

* Add conditions configuration

* Apply conditional overrides

* Handle conditions in nested groups

* Fix reverse mutating conditions

* Start on filter setup interface

* Move field types/constants to shared

* [WIP] Updated client side filter validation

* Support logical operators in client validation step

* Use new validation util in conditions check

* Add nesting in filter seutp

* Add filter rule setup configurator

* Fixes that should've been done in the merge

* Strip out filter-settings interface

TBD in a new PR

* Move browser to index
This commit is contained in:
Rijk van Zanten
2021-07-27 00:02:24 +02:00
committed by GitHub
parent 47e9d2f1fe
commit 92e1ee77bd
121 changed files with 792 additions and 261 deletions

View File

@@ -1,4 +1,4 @@
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import ActivityCollection from './routes/collection.vue';
import ActivityItem from './routes/item.vue';

View File

@@ -1,4 +1,4 @@
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import { addQueryToPath } from '@/utils/add-query-to-path';
import RouterPass from '@/utils/router-passthrough';
import { NavigationGuard } from 'vue-router';

View File

@@ -1,4 +1,4 @@
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import docs, { DocsRoutes } from '@directus/docs';
import { RouteRecordRaw } from 'vue-router';
import NotFound from './routes/not-found.vue';

View File

@@ -1,4 +1,4 @@
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import AddNew from './routes/add-new.vue';
import Collection from './routes/collection.vue';
import Item from './routes/item.vue';

View File

@@ -1,6 +1,6 @@
import api from '@/api';
import { useCollection } from '@/composables/use-collection';
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import { useCollectionsStore, useFieldsStore } from '@/stores';
import RouterPass from '@/utils/router-passthrough';
import { ref } from 'vue';

View File

@@ -0,0 +1,101 @@
<template>
<div>
<interface-list :fields="repeaterFields" template="{{ name }}" :value="value" @input="value = $event" />
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { Field, Condition, DeepPartial } from '@directus/shared/types';
import { useI18n } from 'vue-i18n';
import { state } from '../store';
import { get, set } from 'lodash';
export default defineComponent({
props: {
type: {
type: String,
required: true,
},
collection: {
type: String,
required: true,
},
},
setup() {
const { t } = useI18n();
const value = computed({
get() {
return get(state, 'fieldData.meta.conditions', []);
},
set(value: Condition[]) {
set(state, 'fieldData.meta.conditions', value);
},
});
const repeaterFields = computed<DeepPartial<Field>[]>(() => [
{
field: 'name',
name: t('name'),
type: 'string',
meta: {
interface: 'input',
options: {
iconLeft: 'label',
placeholder: t('enter_a_value'),
},
},
},
{
field: 'rule',
name: t('rule'),
type: 'json',
meta: {
interface: 'input-code',
options: {
language: 'json',
},
},
},
{
field: 'readonly',
name: t('readonly'),
type: 'boolean',
meta: {
interface: 'boolean',
options: {
label: t('disabled_editing_value'),
},
width: 'half',
},
},
{
field: 'hidden',
name: t('hidden'),
type: 'boolean',
meta: {
interface: 'boolean',
options: {
label: t('hidden_on_detail'),
},
width: 'half',
},
},
{
field: 'options',
name: t('interface_options'),
type: 'json',
meta: {
interface: 'system-interface-options',
options: {
interface: state?.fieldData.meta?.interface,
},
},
},
]);
return { repeaterFields, value, state };
},
});
</script>

View File

@@ -83,6 +83,8 @@
:collection="collection"
:type="localType"
/>
<setup-conditions v-if="currentTab[0] === 'conditions'" :collection="collection" :type="localType" />
</div>
<template #actions>
@@ -125,6 +127,7 @@ import SetupRelationship from './components/relationship.vue';
import SetupTranslations from './components/translations.vue';
import SetupInterface from './components/interface.vue';
import SetupDisplay from './components/display.vue';
import SetupConditions from './components/conditions.vue';
import { isEmpty, cloneDeep } from 'lodash';
import api from '@/api';
import { useFieldsStore, useRelationsStore, useCollectionsStore } from '@/stores/';
@@ -149,6 +152,7 @@ export default defineComponent({
SetupTranslations,
SetupInterface,
SetupDisplay,
SetupConditions,
},
props: {
collection: {
@@ -284,6 +288,12 @@ export default defineComponent({
);
}
tabs.push({
text: t('conditions'),
value: 'conditions',
disabled: interfaceDisplayDisabled(),
});
return tabs;
});

View File

@@ -1,4 +1,4 @@
import { defineModule } from '@directus/shared/utils/browser';
import { defineModule } from '@directus/shared/utils';
import Collection from './routes/collection.vue';
import Item from './routes/item.vue';