Users nav (#400)

* Add filters-to-query util

* Add all users string

* Suppot filters in tabular layout

* Sync filters with collection presets

* Support filters in use-items composition

* Render users nav + use skeleton loader

* Add list-item-icon type to skeleton loader

* Fix missing loader indicator on table

* Cleanup has click check

* Dont route based on id

* Fix loading state in table

* Revert "Dont route based on id"

This reverts commit 6de7cbe1b801d5e5e267f09a6e77dc73dcc60a37.

* Fix table loading state

* Fix routing for users module

* Force role field to be fetched

* Add roles store

* Dont render avatar until user is known

* Speed up hydration absurd much

* Rely on roles store to prevent nav from loading

* Fix tests
This commit is contained in:
Rijk van Zanten
2020-04-13 15:18:54 -04:00
committed by GitHub
parent a41824a95a
commit 7cba8a8de1
21 changed files with 314 additions and 35 deletions

View File

@@ -1,3 +1,32 @@
<template>
<div>users nav</div>
<v-list nav>
<v-list-item to="/my-project/users/all">
<v-list-item-icon><v-icon name="people" /></v-list-item-icon>
<v-list-item-content>{{ $t('all_users') }}</v-list-item-content>
</v-list-item>
<v-list-item v-for="{ name, id } in roles" :key="id" :to="`/my-project/users/${id}`">
<v-list-item-icon><v-icon name="people" /></v-list-item-icon>
<v-list-item-content>{{ name }}</v-list-item-content>
</v-list-item>
</v-list>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import useRolesStore from '@/stores/roles';
export default defineComponent({
setup() {
const rolesStore = useRolesStore();
return { roles: rolesStore.state.roles };
},
});
</script>
<style lang="scss" scoped>
::v-deep .v-skeleton-loader {
--v-skeleton-loader-background-color: var(--background-normal-alt);
}
</style>

View File

@@ -1,4 +1,5 @@
import { defineModule } from '@/modules/define';
import UsersBrowse from './routes/browse/';
import UsersDetail from './routes/detail/';
@@ -8,14 +9,31 @@ export default defineModule(({ i18n }) => ({
icon: 'people',
routes: [
{
name: 'users-browse',
path: '/',
redirect: '/all',
},
{
name: 'users-browse-all',
path: '/all',
component: UsersBrowse,
},
{
name: 'users-detail-add-new',
path: '/+',
component: UsersDetail,
props: {
primaryKey: '+',
},
},
{
name: 'users-browse-role',
path: '/:role',
component: UsersBrowse,
props: true,
},
{
name: 'users-detail',
path: '/:primaryKey',
path: '/:role/:primaryKey',
component: UsersDetail,
props: true,
},

View File

@@ -56,7 +56,9 @@
:selection.sync="selection"
:view-options.sync="viewOptions"
:view-query.sync="viewQuery"
:detail-route="'/{{project}}/users/{{primaryKey}}'"
:detail-route="'/{{project}}/users/{{item.role}}/{{primaryKey}}'"
:filters="_filters"
@update:filters="filters = $event"
/>
</private-view>
</template>
@@ -78,18 +80,50 @@ type Item = {
export default defineComponent({
name: 'users-browse',
components: { UsersNavigation },
props: {},
setup() {
props: {
role: {
type: String,
default: null,
},
},
setup(props) {
const layout = ref<LayoutComponent>(null);
const projectsStore = useProjectsStore();
const selection = ref<Item[]>([]);
const { viewOptions, viewQuery } = useCollectionPreset(ref('directus_users'));
const { viewOptions, viewQuery, filters } = useCollectionPreset(ref('directus_users'));
const { addNewLink, batchLink } = useLinks();
const { confirmDelete, deleting, batchDelete } = useBatchDelete();
const { breadcrumb } = useBreadcrumb();
const _filters = computed(() => {
if (props.role !== null) {
return [
{
locked: 1,
field: 'role',
operator: 'eq',
value: props.role,
},
...filters.value,
];
}
return [
// This filter is basically a no-op. Every user has a role. However, by filtering on
// this field, we can ensure that the field data is fetched, which is needed to build
// out the navigation links
{
locked: 1,
field: 'role',
operator: 'nnull',
value: 1,
},
...filters.value,
];
});
return {
addNewLink,
batchLink,
@@ -101,6 +135,7 @@ export default defineComponent({
layout,
viewOptions,
viewQuery,
_filters,
};
function useBatchDelete() {