Merge branch 'main' into save-new-fix

This commit is contained in:
rijkvanzanten
2020-10-26 10:47:35 +01:00
51 changed files with 661 additions and 196 deletions

View File

@@ -328,9 +328,7 @@ export default defineComponent({
useShortcut('meta+shift+s', saveAndAddNew, form);
const navigationGuard: NavigationGuard = (to, from, next) => {
const hasEdits = Object.keys(edits.value).length > 0;
if (hasEdits) {
if (hasEdits.value) {
confirmLeave.value = true;
leaveTo.value = to.fullPath;
return next(false);
@@ -474,6 +472,12 @@ export default defineComponent({
return { deleteAllowed, saveAllowed, archiveAllowed, updateAllowed };
}
},
beforeRouteLeave(to, from, next) {
return (this as any).navigationGuard(to, from, next);
},
beforeRouteUpdate(to, from, next) {
return (this as any).navigationGuard(to, from, next);
},
});
</script>

View File

@@ -54,12 +54,9 @@ export default defineComponent({
},
});
htmlString = htmlString.replaceAll(
hintRegex,
(match: string, type: string, title: string, body: string) => {
return `<div class="hint ${type}"><p class="hint-title">${title}</p><p class="hint-body">${body}</p></div>`;
}
);
htmlString = htmlString.replace(hintRegex, (match: string, type: string, title: string, body: string) => {
return `<div class="hint ${type}"><p class="hint-title">${title}</p><p class="hint-body">${body}</p></div>`;
});
html.value = htmlString;
}

View File

@@ -31,14 +31,14 @@ export default defineModule(({ i18n }) => {
for (const doc of directory.children) {
if (doc.type === 'file') {
routes.push({
path: '/' + doc.path.replace('.md', '').replaceAll('\\', '/'),
path: '/' + doc.path.replace('.md', '').replace(/\\/g, '/'),
component: StaticDocs,
});
} else if (doc.type === 'directory') {
if (doc.path && doc.children && doc.children.length > 0)
routes.push({
path: '/' + doc.path.replaceAll('\\', '/'),
redirect: '/' + doc.children![0].path.replace('.md', '').replaceAll('\\', '/'),
path: '/' + doc.path.replace(/\\/g, '/'),
redirect: '/' + doc.children![0].path.replace('.md', '').replace(/\\/g, '/'),
});
routes.push(...parseRoutes(doc));

View File

@@ -64,10 +64,17 @@
</dd>
</div>
<div>
<dt>{{ $t('file') }}</dt>
<dd>
<a :href="`${getRootPath()}assets/${file.id}`" target="_blank">{{ $t('open') }}</a>
</dd>
</div>
<div>
<dt>{{ $t('folder') }}</dt>
<dd>
<button @click="$emit('move-folder')">{{ folder ? folder.name : $t('file_library') }}</button>
<router-link :to="folderLink">{{ folder ? folder.name : $t('file_library') }}</router-link>
</dd>
</div>
@@ -115,6 +122,7 @@ import i18n from '@/lang';
import marked from 'marked';
import localizedFormat from '@/utils/localized-format';
import api from '@/api';
import getRootPath from '@/utils/get-root-path';
import { userName } from '@/utils/user-name';
export default defineComponent({
@@ -140,9 +148,20 @@ export default defineComponent({
const { creationDate, modificationDate } = useDates();
const { userCreated, userModified } = useUser();
const { folder } = useFolder();
const { folder, folderLink } = useFolder();
return { readableMimeType, size, creationDate, modificationDate, userCreated, userModified, folder, marked };
return {
readableMimeType,
size,
creationDate,
modificationDate,
userCreated,
userModified,
folder,
marked,
folderLink,
getRootPath,
};
function useDates() {
const creationDate = ref<string | null>(null);
@@ -230,16 +249,23 @@ export default defineComponent({
function useFolder() {
type Folder = {
id: number;
id: string;
name: string;
};
const loading = ref(false);
const folder = ref<Folder | null>(null);
const folderLink = computed(() => {
if (folder.value === null) {
return `/files`;
}
return `/files/?folder=${folder.value.id}`;
});
watch(() => props.file, fetchFolder, { immediate: true });
return { folder };
return { folder, folderLink };
async function fetchFolder() {
if (!props.file) return null;

View File

@@ -0,0 +1,57 @@
<template>
<v-dialog :active="active" @toggle="$emit('toggle', false)" @esc="$emit('toggle', false)">
<v-card v-if="file">
<v-card-title>{{ $t('replace_file') }}</v-card-title>
<v-card-text>
<v-upload :preset="preset" :file-id="file.id" @input="uploaded" from-url />
</v-card-text>
<v-card-actions>
<v-button secondary @click="$emit('toggle', false)">{{ $t('done') }}</v-button>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api';
import api from '@/api';
import router from '@/router';
import { PropType } from 'vue';
export default defineComponent({
model: {
prop: 'active',
event: 'toggle',
},
props: {
active: {
type: Boolean,
default: false,
},
file: {
type: Object,
default: () => ({}),
},
preset: {
type: Object,
default: () => ({}),
},
},
setup(props, { emit }) {
return { uploaded };
function uploaded() {
emit('toggle', false);
emit('replaced');
}
},
});
</script>
<style lang="scss" scoped>
.add-new {
--v-button-background-color: var(--primary-25);
--v-button-color: var(--primary);
--v-button-background-color-hover: var(--primary-50);
--v-button-color-hover: var(--primary);
}
</style>

View File

@@ -119,15 +119,13 @@
:width="item.width"
:height="item.height"
:title="item.title"
@click="previewActive = true"
@click="replaceFileDialogActive = true"
/>
<file-lightbox v-if="item" :id="item.id" v-model="previewActive" />
<image-editor
v-if="item && item.type.startsWith('image')"
:id="item.id"
@refresh="changeCacheBuster"
@refresh="refresh"
v-model="editActive"
/>
@@ -156,7 +154,7 @@
</v-dialog>
<template #sidebar>
<file-info-sidebar-detail :file="item" @move-folder="moveToDialogActive = true" />
<file-info-sidebar-detail :file="item" />
<revisions-drawer-detail
v-if="isBatch === false && isNew === false"
collection="directus_files"
@@ -169,6 +167,8 @@
:primary-key="primaryKey"
/>
</template>
<replace-file v-model="replaceFileDialogActive" @replaced="refresh" :file="item" />
</private-view>
</template>
@@ -184,7 +184,6 @@ import SaveOptions from '@/views/private/components/save-options';
import FilePreview from '@/views/private/components/file-preview';
import ImageEditor from '@/views/private/components/image-editor';
import { nanoid } from 'nanoid';
import FileLightbox from '@/views/private/components/file-lightbox';
import { useFieldsStore } from '@/stores/';
import { Field } from '@/types';
import FileInfoSidebarDetail from '../components/file-info-sidebar-detail.vue';
@@ -194,6 +193,7 @@ import api from '@/api';
import getRootPath from '@/utils/get-root-path';
import FilesNotFound from './not-found.vue';
import useShortcut from '@/composables/use-shortcut';
import ReplaceFile from '../components/replace-file.vue';
type Values = {
[field: string]: any;
@@ -220,10 +220,10 @@ export default defineComponent({
SaveOptions,
FilePreview,
ImageEditor,
FileLightbox,
FileInfoSidebarDetail,
FolderPicker,
FilesNotFound,
ReplaceFile,
},
props: {
primaryKey: {
@@ -236,6 +236,7 @@ export default defineComponent({
const { primaryKey } = toRefs(props);
const { breadcrumb } = useBreadcrumb();
const fieldsStore = useFieldsStore();
const replaceFileDialogActive = ref(false);
const revisionsDrawerDetail = ref<Vue | null>(null);
@@ -256,13 +257,15 @@ export default defineComponent({
const hasEdits = computed<boolean>(() => Object.keys(edits.value).length > 0);
const confirmDelete = ref(false);
const cacheBuster = ref(nanoid());
const editActive = ref(false);
const previewActive = ref(false);
const fileSrc = computed(() => {
return (
getRootPath() + `assets/${props.primaryKey}?cache-buster=${cacheBuster.value}&key=system-large-contain`
);
if (item.value && item.value.modified_on) {
return (
getRootPath() +
`assets/${props.primaryKey}?cache-buster=${item.value.modified_on}&key=system-large-contain`
);
}
return getRootPath() + `assets/${props.primaryKey}?key=system-large-contain`;
});
// These are the fields that will be prevented from showing up in the form because they'll be shown in the sidebar
@@ -318,10 +321,7 @@ export default defineComponent({
saveAndStay,
saveAsCopyAndNavigate,
isBatch,
changeCacheBuster,
cacheBuster,
editActive,
previewActive,
revisionsDrawerDetail,
formFields,
confirmLeave,
@@ -335,12 +335,10 @@ export default defineComponent({
fileSrc,
form,
to,
replaceFileDialogActive,
refresh,
};
function changeCacheBuster() {
cacheBuster.value = nanoid();
}
function useBreadcrumb() {
const breadcrumb = computed(() => {
if (!item?.value?.folder) {
@@ -405,7 +403,7 @@ export default defineComponent({
const selectedFolder = ref<number | null>();
watch(item, () => {
selectedFolder.value = item.value.folder;
selectedFolder.value = item.value?.folder || null;
});
return { moveToDialogActive, moving, moveToFolder, selectedFolder };

View File

@@ -67,6 +67,7 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
if (inter.system === true) return false;
const matchesType = inter.types.includes(state.fieldData?.type || 'alias');
const matchesLocalType = inter.localTypes?.includes(type);
let matchesRelation = false;
if (type === 'standard' || type === 'presentation') {
@@ -81,7 +82,7 @@ function initLocalStore(collection: string, field: string, type: typeof localTyp
matchesRelation = inter.relationship === type;
}
return matchesType && matchesRelation;
return matchesType && matchesRelation && (matchesLocalType === undefined || matchesLocalType);
})
.sort((a, b) => (a.name > b.name ? 1 : -1));
});

View File

@@ -304,7 +304,6 @@ export default defineComponent({
type: 'string',
meta: {
width: 'full',
required: true,
options: {
choices: [
{
@@ -342,6 +341,7 @@ export default defineComponent({
},
schema: {
default_value: 'draft',
is_nullable: false,
},
});

View File

@@ -133,7 +133,7 @@ export default defineComponent({
const values = {
...item.value,
...edits.value,
};
} as Record<string, any>;
return !!values.admin_access;
});

View File

@@ -115,7 +115,7 @@ export default defineComponent({
const title = computed(() => {
if (loading.value) return i18n.t('loading');
if (isNew.value) return i18n.t('creating_webhook');
return item.value.name;
return item.value?.name;
});
return {

View File

@@ -384,7 +384,7 @@ export default defineComponent({
}
async function refreshCurrentUser() {
if (userStore.state.currentUser!.id === item.value.id) {
if (userStore.state.currentUser!.id === item.value?.id) {
await userStore.hydrate();
}
}