Add custom interface for presets (#4870)

* add custom interface for presets

* add defaults and change naming

* Fix type issue, put current selection on top

* Fetch email as name fallback

* Opinionated code changes

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
Nitwel
2021-04-14 00:33:36 +02:00
committed by GitHub
parent c41b5a8179
commit c2bc3ea330
4 changed files with 143 additions and 90 deletions

View File

@@ -0,0 +1,11 @@
import { defineInterface } from '@/interfaces/define';
import Scope from './scope.vue';
export default defineInterface({
id: 'scope',
name: '$t:scope',
icon: 'arrow_drop_down_circle',
component: Scope,
types: ['string'],
options: [],
});

View File

@@ -0,0 +1,125 @@
<template>
<div>
<v-skeleton-loader v-if="loading"></v-skeleton-loader>
<v-select v-else :value="value" @input="onSelect" :items="options" />
<drawer-collection
v-if="collection !== null"
:active="collection !== null"
@update:active="collection = null"
@input="onSelectItem"
:collection="collection"
/>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from '@vue/composition-api';
import i18n from '@/lang';
import DrawerCollection from '@/views/private/components/drawer-collection';
import api from '@/api';
import { userName } from '@/utils/user-name';
export default defineComponent({
components: {
DrawerCollection,
},
props: {
value: {
type: String,
default: null,
},
},
setup(props, { emit }) {
const collection = ref<string | null>(null);
const itemName = ref<string | null>(null);
const loading = ref(false);
const isItem = computed(
() => props.value !== null && (props.value.startsWith('role_') || props.value.startsWith('user_'))
);
watch(() => props.value, loadItemName);
loadItemName();
const options = computed(() => {
let options: any[] = [
{
text: i18n.t('global') + ': ' + i18n.t('all_users'),
value: 'all',
},
{
text: i18n.t('user') + ': ' + i18n.t('select'),
value: 'directus_users',
},
{
text: i18n.t('role') + ': ' + i18n.t('select'),
value: 'directus_roles',
},
];
if (isItem.value) {
const [type, id] = props.value.split('_');
options = [
{
text: i18n.t(type) + ': ' + (itemName.value || id),
value: props.value,
},
{ divider: true },
...options,
];
}
return options;
});
return { options, collection, onSelect, onSelectItem, loading };
function onSelect(value: string) {
if (value === 'all') {
collection.value = null;
return emit('input', 'all');
}
collection.value = value;
}
function onSelectItem(value: string[]) {
if (collection.value === 'directus_users') return emit('input', 'user_' + value[0]);
if (collection.value === 'directus_roles') return emit('input', 'role_' + value[0]);
}
async function loadItemName() {
if (!isItem.value) {
itemName.value = null;
return;
}
loading.value = true;
const [endpoint, id] = props.value.split('_');
if (endpoint === 'role') {
const result = await api.get('/roles/' + id, {
params: {
fields: ['id', 'name'],
},
});
itemName.value = result.data.data.name;
} else if (endpoint === 'user') {
const result = await api.get('/users/' + id, {
params: {
fields: ['id', 'first_name', 'last_name', 'email'],
},
});
itemName.value = userName(result.data.data);
}
loading.value = false;
}
},
});
</script>

View File

@@ -603,10 +603,11 @@ settings_project: Project Settings
settings_webhooks: Webhooks
settings_presets: Presets & Bookmarks
scope: Scope
select: Select...
layout: Layout
tree_view: Tree View
changes_are_permanent: Changes are permanent
preset_name_placeholder: Name of bookmark...
preset_name_placeholder: Serves as default when empty...
preset_search_placeholder: Search query...
editing_preset: Editing Preset
layout_preview: Layout Preview

View File

@@ -160,9 +160,7 @@ export default defineComponent({
const isNew = computed(() => props.id === '+');
const { loading: usersLoading, users } = useUsers();
const { loading: rolesLoading, roles } = useRoles();
const { loading: presetLoading, preset } = usePreset();
const { loading, preset } = usePreset();
const { fields } = useForm();
const {
edits,
@@ -177,8 +175,6 @@ export default defineComponent({
const { save, saving } = useSave();
const { deleting, deleteAndQuit, confirmDelete } = useDelete();
const loading = computed(() => usersLoading.value || presetLoading.value || rolesLoading.value);
return {
backLink,
loading,
@@ -275,8 +271,9 @@ export default defineComponent({
const hasEdits = computed(() => Object.keys(edits.value).length > 0);
const initialValues = computed(() => {
if (isNew.value === true) return {};
if (preset.value === null) return {};
const defaultValues = { scope: 'all', layout: 'tabular' };
if (isNew.value === true) return defaultValues;
if (preset.value === null) return defaultValues;
let scope = 'all';
@@ -400,85 +397,7 @@ export default defineComponent({
return { backLink };
}
function useUsers() {
const loading = ref(false);
const users = ref<User[] | null>(null);
fetchUsers();
return { loading, users };
async function fetchUsers() {
loading.value = true;
try {
const response = await api.get(`/users`, {
params: {
fields: ['email', 'first_name', 'last_name', 'id'],
},
});
users.value = response.data.data.map((user: any) => ({
name: userName(user),
id: user.id,
}));
} catch (err) {
unexpectedError(err);
} finally {
loading.value = false;
}
}
}
function useRoles() {
const loading = ref(false);
const roles = ref<Role[] | null>(null);
fetchRoles();
return { loading, roles };
async function fetchRoles() {
loading.value = true;
try {
const response = await api.get(`/roles`, {
params: {
fields: ['name', 'id'],
},
});
roles.value = response.data.data;
} catch (err) {
unexpectedError(err);
} finally {
loading.value = false;
}
}
}
function useForm() {
const scopeChoices = computed(() => {
if (usersLoading.value || rolesLoading.value) return [];
const options = [
{
text: i18n.t('global') + ': ' + i18n.t('all'),
value: 'all',
},
];
roles.value?.forEach((role) => {
options.push({ text: i18n.t('role') + ': ' + role.name, value: `role_${role.id}` });
});
users.value?.forEach((user) => {
options.push({ text: i18n.t('user') + ': ' + user.name, value: `user_${user.id}` });
});
return options;
});
const systemCollectionWhiteList = ['directus_users', 'directus_files', 'directus_activity'];
const fields = computed(() => [
@@ -508,10 +427,7 @@ export default defineComponent({
name: i18n.t('scope'),
type: 'string',
meta: {
interface: 'dropdown',
options: {
choices: scopeChoices.value,
},
interface: 'scope',
width: 'half',
},
},