Add new advanced filters experience (#8570)

* Remove advanced filter sidebar detail

So long, and thanks for all the fish.

* Remove filter conversion logic

* Start replacing/removing old skool filters

* Add inline mode for usages in search bar

* Make filter work in header bar

* Emit empty string as null in filter

* Move shared filter types to shared

* Upgrade use-items

* Fix manual sort on tabular

* Cleanup styling in search bar usage

* Tweak styling

* Fix filtering issues

* Update cards

* Remove activeFilterCount from tabular

* Update maps to work with new filters

* Update calendar to new filter/sort structure

* Fix activity module nav/search

* Fix no-results message

* Update file library filtering

* Finalize user search

* Allow filtering in drawer-collection

* Handle cancelled responses semi-gracefully

* Add loading start state timeout

* Replace sort type in api

* Last commit before redoing a bunch

* Finish new visual style

* Remove unused rounded prop from v-menu

* Tweak sizing

* Enough size tweaking for now

* Count all filter operators instead of top

* Fix archive casting

* Fix api build

* Add merge filters util

* Split filter in user vs system

* Fix export sidebar detail

* Show field label on permissions configuration

* Add migration for filter/sort

* Use filters in insights
This commit is contained in:
Rijk van Zanten
2021-10-07 18:06:03 -04:00
committed by GitHub
parent 046cc8539c
commit f64a5bef7e
99 changed files with 1375 additions and 1760 deletions

View File

@@ -4,8 +4,8 @@
v-slot="{ layoutState }"
v-model:layout-options="layoutOptions"
v-model:layout-query="layoutQuery"
v-model:filters="layoutFilters"
v-model:search-query="searchQuery"
:filter="layoutFilter"
:search="search"
:collection="values.collection"
readonly
>
@@ -66,7 +66,12 @@
<v-form v-model="edits" :fields="fields" :loading="loading" :initial-values="initialValues" :primary-key="id" />
<div class="layout">
<component :is="`layout-${values.layout}`" v-if="values.layout && values.collection" v-bind="layoutState">
<component
:is="`layout-${values.layout}`"
v-if="values.layout && values.collection"
v-bind="layoutState"
:collection="values.collection"
>
<template #no-results>
<v-info :title="t('no_results')" icon="search" center>
{{ t('no_results_copy') }}
@@ -93,7 +98,7 @@
<div class="layout-sidebar">
<sidebar-detail icon="search" :title="t('search')">
<v-input v-model="searchQuery" :placeholder="t('preset_search_placeholder')"></v-input>
<v-input v-model="search" :placeholder="t('preset_search_placeholder')"></v-input>
</sidebar-detail>
<component
@@ -156,7 +161,7 @@ type FormattedPreset = {
layout_query: Record<string, any> | null;
layout_options: Record<string, any> | null;
filters: readonly Filter[] | null;
filter: Filter | null;
};
export default defineComponent({
@@ -181,14 +186,13 @@ export default defineComponent({
const { loading, preset } = usePreset();
const { fields } = useForm();
const { edits, hasEdits, initialValues, values, layoutQuery, layoutOptions, updateFilters, searchQuery } =
useValues();
const { edits, hasEdits, initialValues, values, layoutQuery, layoutOptions, updateFilters, search } = useValues();
const { save, saving } = useSave();
const { deleting, deleteAndQuit, confirmDelete } = useDelete();
const layoutFilters = computed<any>({
const layoutFilter = computed<any>({
get() {
return values.value.filters || [];
return values.value.filter ?? null;
},
set(newFilters) {
updateFilters(newFilters);
@@ -237,13 +241,13 @@ export default defineComponent({
layoutWrapper,
layoutQuery,
layoutOptions,
layoutFilters,
layoutFilter,
hasEdits,
deleting,
deleteAndQuit,
confirmDelete,
updateFilters,
searchQuery,
search,
isSavable,
confirmLeave,
leaveTo,
@@ -266,7 +270,7 @@ export default defineComponent({
if (edits.value.layout) editsParsed.layout = edits.value.layout;
if (edits.value.layout_query) editsParsed.layout_query = edits.value.layout_query;
if (edits.value.layout_options) editsParsed.layout_options = edits.value.layout_options;
if (edits.value.filters) editsParsed.filters = edits.value.filters;
if (edits.value.filter) editsParsed.filter = edits.value.filter;
editsParsed.search = edits.value.search;
if (edits.value.scope) {
@@ -334,7 +338,7 @@ export default defineComponent({
scope: 'all',
layout_query: null,
layout_options: null,
filters: null,
filter: null,
};
if (isNew.value === true) return defaultValues;
if (preset.value === null) return defaultValues;
@@ -357,7 +361,7 @@ export default defineComponent({
scope: scope,
layout_query: preset.value.layout_query,
layout_options: preset.value.layout_options,
filters: preset.value.filters,
filter: preset.value.filter,
};
return value;
@@ -406,7 +410,7 @@ export default defineComponent({
},
});
const searchQuery = computed<string | null>({
const search = computed<string | null>({
get() {
return values.value.search;
},
@@ -418,12 +422,12 @@ export default defineComponent({
},
});
return { edits, initialValues, values, layoutQuery, layoutOptions, hasEdits, updateFilters, searchQuery };
return { edits, initialValues, values, layoutQuery, layoutOptions, hasEdits, updateFilters, search };
function updateFilters(newFilters: Filter) {
function updateFilters(newFilter: Filter) {
edits.value = {
...edits.value,
filters: newFilters,
filter: newFilter,
};
}
}

View File

@@ -9,11 +9,7 @@
}}
</v-notice>
<interface-system-filter
:value="permissions"
:collection-name="permission.collection"
@input="permissions = $event"
/>
<v-form v-model="permissionSync" :fields="fields" />
<div v-if="appMinimal" class="app-minimal">
<v-divider />
@@ -48,21 +44,23 @@ export default defineComponent({
setup(props, { emit }) {
const { t } = useI18n();
const internalPermission = useSync(props, 'permission', emit);
const permissionSync = useSync(props, 'permission', emit);
const permissions = computed({
get() {
return internalPermission.value.permissions;
const fields = computed(() => [
{
field: 'permissions',
name: t('rule'),
type: 'json',
meta: {
interface: 'system-filter',
options: {
collectionName: permissionSync.value.collection,
},
},
},
set(newPermissions: Record<string, any> | null) {
internalPermission.value = {
...internalPermission.value,
permissions: newPermissions,
};
},
});
]);
return { t, permissions };
return { t, fields, permissionSync };
},
});
</script>

View File

@@ -9,11 +9,7 @@
}}
</v-notice>
<interface-system-filter
:value="validation"
:collection-name="permission.collection"
@input="validation = $event"
/>
<v-form v-model="permissionSync" :fields="fields" />
</div>
</template>
@@ -38,21 +34,23 @@ export default defineComponent({
setup(props, { emit }) {
const { t } = useI18n();
const internalPermission = useSync(props, 'permission', emit);
const permissionSync = useSync(props, 'permission', emit);
const validation = computed({
get() {
return internalPermission.value.validation;
const fields = computed(() => [
{
field: 'permissions',
name: t('rule'),
type: 'json',
meta: {
interface: 'system-filter',
options: {
collectionName: permissionSync.value.collection,
},
},
},
set(newValidation: Record<string, any> | null) {
internalPermission.value = {
...internalPermission.value,
validation: newValidation,
};
},
});
]);
return { t, validation };
return { t, permissionSync, fields };
},
});
</script>

View File

@@ -6,8 +6,8 @@
v-model:selection="selection"
v-model:layout-options="layoutOptions"
v-model:layout-query="layoutQuery"
v-model:filters="filters"
v-model:search-query="searchQuery"
:filter="filter"
:search="search"
collection="directus_webhooks"
>
<private-view :title="t('webhooks')">
@@ -24,7 +24,7 @@
</template>
<template #actions>
<search-input v-model="searchQuery" />
<search-input v-model="search" collection="directus_webhooks" />
<v-dialog v-if="selection.length > 0" v-model="confirmDelete" @esc="confirmDelete = false">
<template #activator="{ on }">
@@ -121,7 +121,7 @@ export default defineComponent({
const layoutRef = ref();
const selection = ref<Item[]>([]);
const { layout, layoutOptions, layoutQuery, filters, searchQuery } = usePreset(ref('directus_webhooks'));
const { layout, layoutOptions, layoutQuery, filter, search } = usePreset(ref('directus_webhooks'));
const { addNewLink, batchLink } = useLinks();
const { confirmDelete, deleting, batchDelete } = useBatchDelete();
@@ -136,12 +136,12 @@ export default defineComponent({
deleting,
layoutRef,
layoutWrapper,
filters,
filter,
selection,
layoutOptions,
layoutQuery,
layout,
searchQuery,
search,
clearFilters,
};
@@ -186,8 +186,8 @@ export default defineComponent({
}
function clearFilters() {
filters.value = [];
searchQuery.value = null;
filter.value = null;
search.value = null;
}
},
});