Use notices instead of drawer heading

This commit is contained in:
rijkvanzanten
2020-10-16 15:10:27 -04:00
parent c8a176cdb1
commit d65af41258
26 changed files with 217 additions and 328 deletions

View File

@@ -23,7 +23,6 @@ import VItemGroup, { VItem } from './v-item-group';
import VList, { VListGroup, VListItem, VListItemContent, VListItemHint, VListItemIcon, VListItemText } from './v-list/';
import VMenu from './v-menu/';
import VDrawer from './v-drawer/';
import VDrawerHeading from './v-drawer/v-drawer-heading.vue';
import VNotice from './v-notice/';
import VOverlay from './v-overlay/';
import VPagination from './v-pagination/';
@@ -74,7 +73,6 @@ Vue.component('v-list-item', VListItem);
Vue.component('v-list', VList);
Vue.component('v-menu', VMenu);
Vue.component('v-drawer', VDrawer);
Vue.component('v-drawer-heading', VDrawerHeading);
Vue.component('v-notice', VNotice);
Vue.component('v-overlay', VOverlay);
Vue.component('v-pagination', VPagination);

View File

@@ -1,34 +0,0 @@
<template>
<div class="v-drawer-heading">
<div class="type-title">{{ heading }}</div>
<div v-if="subheading" class="subheading">{{ subheading }}</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
export default defineComponent({
props: {
heading: {
type: String,
required: true,
},
subheading: {
type: String,
default: null,
},
},
});
</script>
<style lang="scss" scoped>
.v-drawer-heading {
margin-bottom: 48px;
.subheading {
margin-top: 4px;
color: var(--foreground-subdued);
}
}
</style>

View File

@@ -9,7 +9,7 @@
<v-icon name="close" />
</v-button>
<div class="content" :class="{ 'no-padding': noPadding }">
<div class="content">
<v-overlay v-if="$slots.sidebar" absolute :active="sidebarActive" @click="sidebarActive = false" />
<nav
v-if="$slots.sidebar"
@@ -20,7 +20,7 @@
<slot name="sidebar" />
</nav>
<main ref="mainEl" class="main">
<header-bar ref="headerBarEl" :title="title">
<header-bar :title="title">
<template #headline>
<slot name="subtitle">
<p v-if="subtitle" class="subtitle">{{ subtitle }}</p>
@@ -39,9 +39,7 @@
<template #title:append><slot name="header:append" /></template>
</header-bar>
<div class="padding-box">
<slot />
</div>
<slot />
</main>
</div>
</article>
@@ -51,7 +49,6 @@
<script lang="ts">
import { defineComponent, ref, computed, provide } from '@vue/composition-api';
import HeaderBar from '@/views/private/components/header-bar/header-bar.vue';
import useElementSize from '@/composables/use-element-size';
export default defineComponent({
components: {
@@ -78,10 +75,6 @@ export default defineComponent({
type: Boolean,
default: false,
},
noPadding: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: 'box',
@@ -91,7 +84,6 @@ export default defineComponent({
const sidebarActive = ref(false);
const localActive = ref(false);
const headerBarEl = ref<Vue>();
const mainEl = ref<Element>();
provide('main-element', mainEl);
@@ -106,9 +98,7 @@ export default defineComponent({
},
});
const { height } = useElementSize(mainEl);
return { sidebarActive, _active, mainEl, headerBarEl, headerHeight: height };
return { sidebarActive, _active, mainEl };
},
});
</script>
@@ -189,30 +179,16 @@ body {
}
.main {
flex-grow: 1;
overflow: auto;
}
.padding-box {
--content-padding: 16px;
--content-padding-bottom: 32px;
height: 1px; // allow height: 100% children
min-height: calc(100% - (65px + 24px + 24px)); // header height + 2x margin
padding: 16px 16px 32px;
padding-top: 0;
flex-grow: 1;
overflow: auto;
@include breakpoint(medium) {
--content-padding: 32px;
padding: 32px;
padding-top: 0;
}
}
&.no-padding .padding-box {
padding: 0px !important;
}
}
@include breakpoint(medium) {

View File

@@ -139,10 +139,10 @@ export default defineComponent({
const gridClass = computed<string | null>(() => {
if (el.value === null) return null;
if (width.value > 588 && width.value <= 792) {
return 'grid';
} else {
if (width.value > 792) {
return 'grid with-fill';
} else {
return 'grid';
}
return null;

View File

@@ -1,7 +1,6 @@
import { Ref, ref, isRef, onMounted, onUnmounted } from '@vue/composition-api';
import { notEmpty } from '@/utils/is-empty';
import { ResizeObserver as ResizeObserverPolyfill } from 'resize-observer';
import Vue from 'vue';
declare global {
interface Window {
@@ -9,7 +8,7 @@ declare global {
}
}
export default function useElementSize<T extends Element>(target: T | Ref<undefined | null | T | Vue>) {
export default function useElementSize<T extends Element>(target: T | Ref<T> | Ref<null>) {
const width = ref(0);
const height = ref(0);
@@ -25,19 +24,10 @@ export default function useElementSize<T extends Element>(target: T | Ref<undefi
});
onMounted(() => {
const deref = isRef(target) ? target.value : target;
console.log(deref);
const t = isRef(target) ? target.value : target;
let targetElement: Element;
if (deref instanceof Vue) {
targetElement = (deref as Vue).$el;
} else {
targetElement = deref as Element;
}
if (notEmpty(targetElement)) {
resizeObserver.observe(targetElement);
if (notEmpty(t)) {
resizeObserver.observe(t);
}
});

View File

@@ -1,6 +1,6 @@
<template>
<div>
<h2 class="type-title">{{ $t('display_setup_title') }}</h2>
<v-notice type="info">{{ $t('display_setup_title') }}</v-notice>
<v-fancy-select class="select" :items="selectItems" v-model="fieldData.meta.display" />
@@ -130,4 +130,8 @@ export default defineComponent({
text-decoration: underline;
}
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<h2 class="type-title">{{ $t('schema_field_title') }}</h2>
<v-notice type="info">{{ $t('schema_field_title') }}</v-notice>
<div class="form">
<div class="field half-left" v-if="fieldData.meta">
@@ -103,4 +103,8 @@ export default defineComponent({
.required {
--v-icon-color: var(--primary);
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div>
<h2 class="type-title">{{ $t('interface_setup_title') }}</h2>
<v-notice type="info">{{ $t('interface_setup_title') }}</v-notice>
<v-fancy-select class="select" :items="selectItems" v-model="fieldData.meta.interface" />
@@ -139,4 +139,8 @@ export default defineComponent({
text-decoration: underline;
}
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,145 +0,0 @@
<template>
<div>
<h2 class="type-title">{{ $t('configure_languages') }}</h2>
<div class="grid">
<div class="field">
<div class="type-label">{{ $t('translations_collection') }}</div>
<v-input disabled :value="relations[1].many_collection" />
</div>
<div class="field">
<div class="type-label">{{ $t('languages_collection') }}</div>
<v-input :class="{ matches: languagesCollectionExists }" db-safe key="languages-collection" v-model="relations[1].one_collection" :disabled="isExisting" :placeholder="$t('collection') + '...'">
<template #append>
<v-menu show-arrow placement="bottom-end">
<template #activator="{ toggle }">
<v-icon name="list_alt" @click="toggle" v-tooltip="$t('select_existing')" :disabled="isExisting" />
</template>
<v-list class="monospace">
<v-list-item
v-for="item in items"
:key="item.value"
:active="relations[1].one_collection === item.value"
:disabled="item.disabled"
@click="relations[1].one_collection = item.value"
>
<v-list-item-content>
{{ item.text }}
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
</template>
</v-input>
</div>
<v-input :value="relations[1].many_field" :placeholder="$t('foreign_key') + '...'"/>
<v-input db-safe :disabled="languagesCollectionExists" v-model="relations[1].one_primary" :placeholder="$t('primary_key') + '...'" />
<v-icon class="arrow" name="arrow_back" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, watch } from '@vue/composition-api';
import { Relation } from '@/types';
import { Field } from '@/types';
import { orderBy } from 'lodash';
import useSync from '@/composables/use-sync';
import { useCollectionsStore, useFieldsStore } from '@/stores';
import i18n from '@/lang';
import { state } from '../store';
export default defineComponent({
props: {
type: {
type: String,
required: true,
},
collection: {
type: String,
required: true,
},
isExisting: {
type: Boolean,
default: false,
},
},
setup(props, { emit }) {
const collectionsStore = useCollectionsStore();
const fieldsStore = useFieldsStore();
const { items } = useRelation();
const languagesCollectionExists = computed(() => {
return !!collectionsStore.getCollection(state.relations[1].one_collection);
});
return {
relations: state.relations,
items,
fieldData: state.fieldData,
languagesCollectionExists,
};
function useRelation() {
const availableCollections = computed(() => {
return orderBy(
collectionsStore.state.collections.filter((collection) => {
return collection.collection.startsWith('directus_') === false;
}),
['collection'],
['asc']
);
});
const items = computed(() =>
availableCollections.value.map((collection) => ({
text: collection.collection,
value: collection.collection,
}))
);
return { items };
}
},
});
</script>
<style lang="scss" scoped>
.grid {
--v-select-font-family: var(--family-monospace);
--v-input-font-family: var(--family-monospace);
position: relative;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px 32px;
margin-top: 48px;
.v-input.matches {
--v-input-color: var(--primary);
}
.arrow {
--v-icon-color: var(--primary);
position: absolute;
bottom: 14px;
left: 50%;
transform: translateX(-50%);
}
}
.v-list {
--v-list-item-content-font-family: var(--family-monospace);
}
.v-divider {
margin: 48px 0;
}
.type-label {
margin-bottom: 8px;
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div>
<h2 class="type-title">{{ $t('configure_m2m') }}</h2>
<v-notice type="info">{{ $t('configure_m2m') }}</v-notice>
<div class="grid">
<div class="field">
<div class="type-label">{{ $t('this_collection') }}</div>
@@ -452,4 +453,8 @@ export default defineComponent({
transform: translateX(-50%);
}
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div>
<h2 class="type-title">{{ $t('configure_m2o') }}</h2>
<v-notice type="info">{{ $t('configure_m2o') }}</v-notice>
<div class="grid">
<div class="field">
<div class="type-label">{{ $t('this_collection') }}</div>
@@ -255,4 +256,8 @@ export default defineComponent({
.type-label {
margin-bottom: 8px;
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div>
<h2 class="type-title">{{ $t('configure_o2m') }}</h2>
<v-notice type="info">{{ $t('configure_o2m') }}</v-notice>
<div class="grid">
<div class="field">
<div class="type-label">{{ $t('this_collection') }}</div>
@@ -380,4 +381,8 @@ export default defineComponent({
transform: translateX(-50%);
}
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,8 @@
<template>
<div>
<h2 class="type-title">{{ $t('schema_setup_title') }}</h2>
<v-notice type="info">
{{ $t('schema_setup_title') }}
</v-notice>
<div class="form">
<div class="field">
@@ -392,10 +394,6 @@ export default defineComponent({
@import '@/styles/mixins/breakpoint';
@import '@/styles/mixins/form-grid';
.type-title {
margin-bottom: 32px;
}
.form {
--v-form-vertical-gap: 32px;
--v-form-horizontal-gap: 32px;
@@ -416,4 +414,8 @@ export default defineComponent({
grid-gap: 12px;
grid-template-columns: 1fr 1fr;
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div>
<h2 class="type-title">{{ $t('configure_m2m') }}</h2>
<v-notice type="info">{{ $t('configure_m2m') }}</v-notice>
<div class="grid">
<div class="field">
<div class="type-label">{{ $t('this_collection') }}</div>
@@ -349,4 +350,8 @@ export default defineComponent({
.v-list {
--v-list-item-content-font-family: var(--family-monospace);
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -45,47 +45,49 @@
<setup-tabs :current.sync="currentTab" :tabs="tabs" :type="localType" />
</template>
<setup-schema
v-if="currentTab[0] === 'schema'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<div class="content">
<setup-schema
v-if="currentTab[0] === 'schema'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-field
v-if="currentTab[0] === 'field'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-field
v-if="currentTab[0] === 'field'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-relationship
v-if="currentTab[0] === 'relationship'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-relationship
v-if="currentTab[0] === 'relationship'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-translations
v-if="currentTab[0] === 'translations'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-translations
v-if="currentTab[0] === 'translations'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-interface
v-if="currentTab[0] === 'interface'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-interface
v-if="currentTab[0] === 'interface'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-display
v-if="currentTab[0] === 'display'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
<setup-display
v-if="currentTab[0] === 'display'"
:is-existing="field !== '+'"
:collection="collection"
:type="localType"
/>
</div>
<template #actions>
<setup-actions
@@ -404,4 +406,10 @@ export default defineComponent({
color: var(--primary);
}
}
.content {
padding: var(--content-padding);
padding-top: 0;
padding-bottom: var(--content-padding);
}
</style>

View File

@@ -29,9 +29,10 @@
</v-tabs>
</template>
<v-tabs-items v-model="currentTab">
<v-tabs-items class="content" v-model="currentTab">
<v-tab-item value="collection">
<h2 class="type-title">{{ $t('creating_collection_info') }}</h2>
<v-notice type="info">{{ $t('creating_collection_info') }}</v-notice>
<div class="grid">
<div>
<div class="type-label">
@@ -83,7 +84,8 @@
</div>
</v-tab-item>
<v-tab-item value="system">
<h2 class="type-title">{{ $t('creating_collection_system') }}</h2>
<v-notice type="info">{{ $t('creating_collection_system') }}</v-notice>
<div class="grid system">
<div v-for="(info, field) in systemFields" :key="field">
<div class="type-label">{{ $t(info.label) }}</div>
@@ -475,4 +477,14 @@ export default defineComponent({
.required {
color: var(--primary);
}
.content {
padding: var(--content-padding);
padding-top: 0;
padding-bottom: var(--content-padding);
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,13 +1,14 @@
<template>
<div>
<v-drawer-heading
:heading="
<v-notice type="info">
{{
$t('fields_for_role', {
role: role ? role.name : $t('public'),
action: $t(permission.action).toLowerCase(),
})
"
/>
}}
</v-notice>
<p class="type-label">{{ $tc('field', 0) }}</p>
<interface-checkboxes v-model="fields" type="json" :choices="fieldsInCollection" />
</div>
@@ -83,4 +84,8 @@ export default defineComponent({
.type-label {
margin-bottom: 8px;
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,13 +1,14 @@
<template>
<div>
<v-drawer-heading
:heading="
<v-notice type="info">
{{
$t('permissions_for_role', {
action: $t(permission.action).toLowerCase(),
role: role ? role.name : $t('public'),
})
"
/>
}}
</v-notice>
<interface-code v-model="permissions" language="json" type="json" />
</div>
</template>
@@ -47,3 +48,9 @@ export default defineComponent({
},
});
</script>
<style lang="scss" scoped>
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,13 +1,13 @@
<template>
<div>
<v-drawer-heading
:heading="
<v-notice type="info">
{{
$t('presets_for_role', {
action: $t(permission.action).toLowerCase(),
role: role ? role.name : $t('public'),
})
"
/>
}}
</v-notice>
<interface-code v-model="presets" language="json" type="json" />
</div>
</template>
@@ -47,3 +47,9 @@ export default defineComponent({
},
});
</script>
<style lang="scss" scoped>
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,13 +1,14 @@
<template>
<div>
<v-drawer-heading
:heading="
<v-notice type="info">
{{
$t('validation_for_role', {
action: $t(permission.action).toLowerCase(),
role: role ? role.name : $t('public'),
})
"
/>
}}
</v-notice>
<interface-code v-model="validation" language="json" type="json" />
</div>
</template>
@@ -47,3 +48,9 @@ export default defineComponent({
},
});
</script>
<style lang="scss" scoped>
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<v-drawer v-model="_active" :title="$t('select_item')" no-padding @cancel="cancel">
<v-drawer v-model="_active" :title="$t('select_item')" @cancel="cancel">
<component
:is="`layout-${localLayout}`"
:collection="collection"

View File

@@ -1,31 +1,33 @@
<template>
<v-drawer v-model="_active" :title="title" persistent @cancel="cancel">
<template v-if="junctionField">
<v-form
:loading="loading"
:initial-values="item && item[junctionField]"
:collection="junctionRelatedCollection"
:primary-key="relatedPrimaryKey"
:edits="_edits[junctionField]"
@input="setJunctionEdits"
/>
<v-divider v-if="showDivider" />
</template>
<v-form
:loading="loading"
:initial-values="item"
:collection="collection"
:primary-key="primaryKey"
v-model="_edits"
/>
<template #actions>
<v-button @click="save" icon rounded v-tooltip.bottom="$t('save')">
<v-icon name="check" />
</v-button>
</template>
<div class="drawer-item-content">
<template v-if="junctionField">
<v-form
:loading="loading"
:initial-values="item && item[junctionField]"
:collection="junctionRelatedCollection"
:primary-key="relatedPrimaryKey"
:edits="_edits[junctionField]"
@input="setJunctionEdits"
/>
<v-divider v-if="showDivider" />
</template>
<v-form
:loading="loading"
:initial-values="item"
:collection="collection"
:primary-key="primaryKey"
v-model="_edits"
/>
</div>
</v-drawer>
</template>
@@ -289,4 +291,9 @@ export default defineComponent({
.v-divider {
margin: 52px 0;
}
.drawer-item-content {
padding: var(--content-padding);
padding-bottom: var(--content-padding-bottom);
}
</style>

View File

@@ -1,12 +1,5 @@
<template>
<v-drawer
v-model="_active"
class="modal"
:title="$t('editing_image')"
persistent
no-padding
@cancel="_active = false"
>
<v-drawer v-model="_active" class="modal" :title="$t('editing_image')" persistent @cancel="_active = false">
<template #activator="activatorBinding">
<slot name="activator" v-bind="activatorBinding" />
</template>
@@ -439,7 +432,7 @@ export default defineComponent({
.editor-container {
width: 100%;
height: 100%;
height: calc(100% - (65px + 24px + 24px)); // header height + 2x margin
overflow: hidden;
background-color: var(--background-subdued);

View File

@@ -1,6 +1,11 @@
<template>
<div>
<v-drawer-heading :heading="$t('revision_post_update')" :subheading="$t('no_relational_data')" />
<v-notice type="info">
{{ $t('revision_post_update') }}
<br />
{{ $t('no_relational_data') }}
</v-notice>
<v-form
disabled
:collection="revision.collection"
@@ -23,3 +28,9 @@ export default defineComponent({
},
});
</script>
<style lang="scss" scoped>
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -1,6 +1,10 @@
<template>
<div class="updates">
<v-drawer-heading :heading="$t('changes_made')" :subheading="$t('no_relational_data')" />
<v-notice type="info">
{{ $t('changes_made') }}
<br />
{{ $t('no_relational_data') }}
</v-notice>
<div class="change" v-for="change in changes" :key="change.name">
<div class="type-label">{{ change.name }}</div>
@@ -92,4 +96,8 @@ export default defineComponent({
.change-line {
margin-bottom: 4px;
}
.v-notice {
margin-bottom: 36px;
}
</style>

View File

@@ -141,4 +141,10 @@ export default defineComponent({
--v-button-background-color: var(--warning);
--v-button-background-color-hover: var(--warning-125);
}
.content {
padding: var(--content-padding);
padding-top: 0;
padding-bottom: var(--content-padding);
}
</style>