Update system-filter interface to use v-field-list (#12320)

* update system filter to use v-field-list

* remove unused code

* use v-field-list in nodes

* prevent node name wrapping

* use prepend as the correct term

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
Azri Kahar
2022-03-26 00:27:25 +08:00
committed by GitHub
parent d26332d012
commit 6acd0b31a2
3 changed files with 64 additions and 68 deletions

View File

@@ -1,5 +1,6 @@
<template>
<v-list :mandatory="false" @toggle="loadFieldRelations($event.value)">
<slot name="prepend" />
<v-list-item v-if="fieldsCount > 20">
<v-list-item-content>
<v-input v-model="search" autofocus small :placeholder="t('search')">

View File

@@ -16,22 +16,15 @@
<div v-if="filterInfo[index].isField" block class="node field">
<div class="header" :class="{ inline }">
<v-icon name="drag_indicator" class="drag-handle" small></v-icon>
<v-select
inline
class="name"
item-text="name"
item-value="key"
placement="bottom-start"
:full-width="false"
:model-value="filterInfo[index].field"
:items="fieldOptions"
:mandatory="false"
:groups-clickable="true"
@group-toggle="loadFieldRelations($event.value)"
@update:modelValue="updateField(index, $event)"
>
<template #preview>{{ getFieldPreview(element) }}</template>
</v-select>
<v-menu placement="bottom-start" show-arrow>
<template #activator="{ toggle }">
<button class="name" @click="toggle">
<span>{{ getFieldPreview(element) }}</span>
</button>
</template>
<v-field-list :collection="collectionName" @select-field="updateField(index, $event)" />
</v-menu>
<v-select
inline
class="comparator"
@@ -98,7 +91,6 @@
</template>
<script lang="ts">
import { useFieldTree } from '@/composables/use-field-tree';
import { computed, defineComponent, PropType, toRefs } from 'vue';
import InputGroup from './input-group.vue';
import Draggable from 'vuedraggable';
@@ -153,9 +145,8 @@ export default defineComponent({
},
emits: ['remove-node', 'update:filter', 'change'],
setup(props, { emit }) {
const { collection } = toRefs(props);
const { collection: collectionName } = toRefs(props);
const filterSync = useSync(props, 'filter', emit);
const { treeList: fieldOptions, loadFieldRelations } = useFieldTree(collection);
const fieldsStore = useFieldsStore();
const { t } = useI18n();
@@ -186,14 +177,13 @@ export default defineComponent({
});
return {
fieldOptions,
collectionName,
getCompareOptions,
updateField,
updateComparator,
t,
replaceNode,
toggleLogic,
loadFieldRelations,
getNodeName,
getField,
getComparator,
@@ -385,6 +375,10 @@ export default defineComponent({
}
}
.name {
white-space: nowrap;
}
.name,
.comparator {
position: relative;

View File

@@ -21,25 +21,26 @@
/>
</v-list>
<div class="buttons">
<v-select
:inline="!inline"
item-text="name"
item-value="key"
placement="bottom-start"
class="add-filter"
:placeholder="t('interfaces.filter.add_filter')"
:full-width="inline"
:model-value="null"
:items="fieldOptions"
:mandatory="false"
:groups-clickable="true"
@group-toggle="loadFieldRelations($event.value)"
@update:modelValue="addNode($event)"
>
<template v-if="inline" #prepend>
<v-icon name="add" small />
<v-menu placement="bottom-start" show-arrow>
<template #activator="{ toggle, active }">
<button class="add-filter" :class="{ active }" @click="toggle">
<v-icon v-if="inline" name="add" class="add" small />
<span>{{ t('interfaces.filter.add_filter') }}</span>
<v-icon name="expand_more" class="expand_more" />
</button>
</template>
</v-select>
<v-field-list :collection="collectionName" @select-field="addNode($event)">
<template #prepend>
<v-list-item clickable @click="addNode('$group')">
<v-list-item-content>
<v-text-overflow :text="t('interfaces.filter.add_group')" />
</v-list-item-content>
</v-list-item>
<v-divider />
</template>
</v-field-list>
</v-menu>
</div>
</div>
</template>
@@ -51,7 +52,6 @@ import { useI18n } from 'vue-i18n';
import { Filter } from '@directus/shared/types';
import Nodes from './nodes.vue';
import { getNodeName } from './utils';
import { useFieldTree } from '@/composables/use-field-tree';
import { getFilterOperatorsForType } from '@directus/shared/utils';
import { useFieldsStore } from '@/stores';
@@ -96,8 +96,6 @@ export default defineComponent({
const fieldsStore = useFieldsStore();
const { treeList, loadFieldRelations } = useFieldTree(collection);
const innerValue = computed<Filter[]>({
get() {
if (!props.value || isEmpty(props.value)) return [];
@@ -119,17 +117,11 @@ export default defineComponent({
},
});
const fieldOptions = computed(() => {
return [{ key: '$group', name: t('interfaces.filter.add_group') }, { divider: true }, ...treeList.value];
});
return {
t,
addNode,
removeNode,
innerValue,
fieldOptions,
loadFieldRelations,
emitValue,
collection,
};
@@ -163,7 +155,7 @@ export default defineComponent({
let list = get(innerValue.value, ids.join('.')) as Filter[];
list = list.filter((node, index) => index !== Number(id));
list = list.filter((_node, index) => index !== Number(id));
innerValue.value = set(innerValue.value, ids.join('.'), list);
}
@@ -218,7 +210,7 @@ export default defineComponent({
}
.add-filter {
--v-select-placeholder-color: var(--primary);
color: var(--primary);
}
&.inline {
@@ -238,29 +230,38 @@ export default defineComponent({
}
.add-filter {
display: flex;
align-items: center;
width: 100%;
height: 30px;
padding: 0;
color: var(--foreground-subdued);
background-color: var(--background-page);
border: var(--border-width) solid var(--border-subdued);
border-radius: 100px;
transition: border-color var(--fast) var(--transition);
:deep(.v-input) {
position: relative;
width: 100%;
height: 30px;
padding: 0;
background-color: var(--background-page);
border: var(--border-width) solid var(--border-subdued);
border-radius: 100px;
transition: border-color var(--fast) var(--transition);
&:hover,
&.active {
border-color: var(--border-normal);
}
.input {
padding-right: 5px;
padding-left: 6px;
background: transparent;
border: 0;
.prepend {
margin-right: 4px;
}
&.active {
.expand_more {
transform: scaleY(-1);
transition-timing-function: var(--transition-in);
}
}
.add {
margin-left: 6px;
margin-right: 4px;
}
.expand_more {
margin-left: auto;
margin-right: 6px;
transition: transform var(--medium) var(--transition-out);
}
}
}
}