Collection display template (#487)

* Add translation strings for adding/editing item

* Add display_template to collection type

* Dont use functional for skeleton loader

* Make title optional and add title slot

* Make title prop optional in private view

* Render -- for null values in render template

* Render display template in header bar

* Render null values in template as subdued --

* Render status dot aligned in the middle

* Fetch latest collections on settings save
This commit is contained in:
Rijk van Zanten
2020-04-27 10:50:38 -04:00
committed by GitHub
parent 7fde68d8f0
commit 9e28932a42
15 changed files with 61 additions and 19 deletions

View File

@@ -356,7 +356,7 @@ body {
.interface {
position: relative;
::v-deep .v-skeleton-loader {
.v-skeleton-loader {
position: absolute;
top: 0;
left: 0;

View File

@@ -1,7 +1,7 @@
<template functional>
<template>
<transition name="fade">
<div class="v-skeleton-loader" :class="props.type">
<template v-if="props.type === 'list-item-icon'">
<div :class="type" class="v-skeleton-loader">
<template v-if="type === 'list-item-icon'">
<div class="icon" />
<div class="text" />
</template>

View File

@@ -43,6 +43,7 @@ export default defineComponent({
width: 12px;
height: 12px;
margin: 0 4px;
vertical-align: middle;
border-radius: 6px;
}
</style>

View File

@@ -147,6 +147,7 @@
"3": "Only super admins have access to this",
"4": "Super Admin Token not provided",
"11": "Can't Reach Database",
"12": "Field has invalid regular expression",
"100": "Incorrect Email/Password",
"101": "Logged-out from Inactivity",
"102": "Logged-out from Inactivity",
@@ -375,6 +376,9 @@
"statuses_not_configured": "Status mapping option configured incorrectly",
"status_mapping": "Status Mapping",
"adding_in": "Adding New Item in {collection}",
"editing_in": "Editing Item in {collection}",
"about_directus": "About Directus",
"activity_log": "Activity Log",
"add_field_filter": "Add a field filter",
@@ -535,7 +539,6 @@
"drop_files": "Can't Drop Files | Drop file here... | Drop files here...",
"duplicate": "Duplicate",
"duplicating_field": "Duplicating Field",
"editing": "Editing Item: {collection}",
"editing_item": "Editing Item",
"editing_items": "Batch Editing {count} Items",
"editing_my_profile": "Editing My Profile",

View File

@@ -200,7 +200,7 @@ export default defineComponent({
--v-icon-color: var(--foreground-subdued);
}
::v-deep .v-skeleton-loader {
.v-skeleton-loader {
position: absolute;
top: 0;
left: 0;

View File

@@ -25,6 +25,7 @@ describe('Modules / Collections / Compositions / useNavigation', () => {
managed: true,
single: false,
translation: null,
display_template: null,
},
];
@@ -60,6 +61,7 @@ describe('Modules / Collections / Compositions / useNavigation', () => {
managed: true,
single: false,
translation: null,
display_template: null,
},
{
collection: 'test2',
@@ -70,6 +72,7 @@ describe('Modules / Collections / Compositions / useNavigation', () => {
managed: true,
single: false,
translation: null,
display_template: null,
},
{
collection: 'test3',
@@ -80,6 +83,7 @@ describe('Modules / Collections / Compositions / useNavigation', () => {
managed: true,
single: false,
translation: null,
display_template: null,
},
];

View File

@@ -3,11 +3,22 @@
<private-view
v-else
:title="
$t(collectionInfo.single ? 'editing_single' : 'editing', {
collection: collectionInfo.name,
})
isNew
? $t('adding_in', { collection: collectionInfo.name })
: $t('editing_in', { collection: collectionInfo.name })
"
>
<template #title v-if="isNew === false && collectionInfo.display_template">
<v-skeleton-loader class="title-loader" type="text" v-if="loading" />
<h1 class="type-title" v-else>
<render-template
:collection="collectionInfo.collection"
:item="templateValues"
:template="collectionInfo.display_template"
/>
</h1>
</template>
<template #title-outer:prepend>
<v-button
v-if="collectionInfo.single"
@@ -190,6 +201,13 @@ export default defineComponent({
() => `/${currentProjectKey.value}/collections/${collection.value}/`
);
const templateValues = computed(() => {
return {
...(item.value || {}),
...edits.value,
};
});
return {
item,
loading,
@@ -211,6 +229,7 @@ export default defineComponent({
saveAsCopyAndNavigate,
isBatch,
softDeleteStatus,
templateValues,
};
async function saveAndQuit() {
@@ -268,4 +287,8 @@ export default defineComponent({
.v-form {
padding: var(--content-padding);
}
.title-loader {
width: 260px;
}
</style>

View File

@@ -52,7 +52,7 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
::v-deep .v-skeleton-loader {
.v-skeleton-loader {
--v-skeleton-loader-background-color: var(--background-normal-alt);
}

View File

@@ -82,6 +82,7 @@ import useProjectsStore from '@/stores/projects';
import { i18n } from '@/lang';
import useItem from '@/compositions/use-item';
import router from '@/router';
import useCollectionsStore from '@/stores/collections';
export default defineComponent({
components: { SettingsNavigation, FieldsManagement },
@@ -96,6 +97,7 @@ export default defineComponent({
const { collection } = toRefs(props);
const { info: collectionInfo, fields } = useCollection(collection);
const { currentProjectKey } = toRefs(projectsStore.state);
const collectionsStore = useCollectionsStore();
const breadcrumb = computed(() => {
return [
@@ -152,6 +154,7 @@ export default defineComponent({
async function saveAndQuit() {
await save();
await collectionsStore.hydrate();
router.push(`/${currentProjectKey.value}/settings/data-model`);
}
},

View File

@@ -36,7 +36,7 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
::v-deep .v-skeleton-loader {
.v-skeleton-loader {
--v-skeleton-loader-background-color: var(--background-normal-alt);
}

View File

@@ -146,7 +146,7 @@ export default defineComponent({
<style lang="scss" scoped>
.v-notice,
::v-deep .v-skeleton-loader {
.v-skeleton-loader {
margin-bottom: 12px;
}
</style>

View File

@@ -13,6 +13,7 @@ export interface CollectionRaw {
managed: boolean;
icon: string | null;
translation: Translation[] | null;
display_template: string | null;
}
export interface Collection extends CollectionRaw {

View File

@@ -11,9 +11,11 @@
<div class="title-container">
<slot name="headline" />
<div class="title">
<slot name="title:prepend" />
<h1 class="type-title">{{ title }}</h1>
<slot name="title:append" />
<slot name="title">
<slot name="title:prepend" />
<h1 class="type-title">{{ title }}</h1>
<slot name="title:append" />
</slot>
</div>
</div>
@@ -38,7 +40,7 @@ export default defineComponent({
props: {
title: {
type: String,
required: true,
default: null,
},
},
setup() {

View File

@@ -1,11 +1,12 @@
<template>
<div class="render-template">
<template v-for="(part, index) in parts">
<span :key="index" v-if="part === null || part.value === null" class="subdued">--</span>
<component
v-if="part !== null && typeof part === 'object'"
v-else-if="typeof part === 'object'"
:is="`display-${part.component}`"
:key="index"
:value="part.value"
:value="part.value === null ? '--' : part.value"
:interface="part.interface"
:interface-options="part.interfaceOptions"
v-bind="part.options"
@@ -91,4 +92,8 @@ export default defineComponent({
.render-template {
display: contents;
}
.subdued {
color: var(--foreground-subdued);
}
</style>

View File

@@ -94,7 +94,7 @@ export default defineComponent({
props: {
title: {
type: String,
required: true,
default: null,
},
},
setup() {