move options to v-upload

This commit is contained in:
Nitwel
2020-09-18 10:37:51 +02:00
committed by rijkvanzanten
parent 1abba79c9f
commit dae1a9ca51
5 changed files with 149 additions and 120 deletions

View File

@@ -29,15 +29,66 @@
<p class="type-label">{{ $t('drag_file_here') }}</p>
<p class="type-text">{{ $t('click_to_browse') }}</p>
<input class="browse" type="file" @input="onBrowseSelect" />
<template v-if="fromUrl !== false || fromLibrary !== false">
<v-menu showArrow placement="bottom-end">
<template #activator="{ toggle }">
<v-icon @click="toggle" class="options" name="more_vert" />
</template>
<v-list>
<v-list-item @click="activeDialog = 'choose'" v-if="fromLibrary">
<v-list-item-icon><v-icon name="folder_open" /></v-list-item-icon>
<v-list-item-content>
{{ $t('choose_from_library') }}
</v-list-item-content>
</v-list-item>
<v-list-item @click="activeDialog = 'url'" v-if="fromUrl">
<v-list-item-icon><v-icon name="link" /></v-list-item-icon>
<v-list-item-content>
{{ $t('import_from_url') }}
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
<modal-browse
collection="directus_files"
:active="activeDialog === 'choose'"
@update:active="activeDialog = null"
@input="setSelection"
/>
<v-dialog :active="activeDialog === 'url'" @toggle="activeDialog = null" :persistent="urlLoading">
<v-card>
<v-card-title>{{ $t('import_from_url') }}</v-card-title>
<v-card-text>
<v-input :placeholder="$t('url')" v-model="url" :disabled="urlLoading" />
</v-card-text>
<v-card-actions>
<v-button :disabled="urlLoading" @click="activeDialog = null" secondary>
{{ $t('cancel') }}
</v-button>
<v-button :loading="urlLoading" @click="importFromURL" :disabled="isValidURL === false">
{{ $t('import') }}
</v-button>
</v-card-actions>
</v-card>
</v-dialog>
</template>
</template>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api';
import { defineComponent, ref, computed, watch } from '@vue/composition-api';
import uploadFiles from '@/utils/upload-files';
import ModalBrowse from '@/views/private/components/modal-browse';
import api from '@/api';
import useItem from '@/composables/use-item';
export default defineComponent({
components: { ModalBrowse },
props: {
multiple: {
type: Boolean,
@@ -47,10 +98,21 @@ export default defineComponent({
type: Object,
default: () => ({}),
},
fromUrl: {
type: Boolean,
default: false,
},
fromLibrary: {
type: Boolean,
default: false,
},
},
setup(props, { emit }) {
const { uploading, progress, error, upload, onBrowseSelect, done, numberOfFiles } = useUpload();
const { onDragEnter, onDragLeave, onDrop, dragging } = useDragging();
const { url, isValidURL, loading: urlLoading, error: urlError, importFromURL } = useURLImport();
const { setSelection } = useSelection();
const activeDialog = ref<'choose' | 'url' | null>(null);
return {
uploading,
@@ -63,6 +125,12 @@ export default defineComponent({
onBrowseSelect,
done,
numberOfFiles,
activeDialog,
url,
isValidURL,
urlLoading,
importFromURL,
setSelection,
};
function useUpload() {
@@ -146,6 +214,67 @@ export default defineComponent({
}
}
}
function useSelection() {
const collection = ref('directus_files');
const image = ref<string | null>(null);
const { item, error, loading } = useItem(collection, image);
function setSelection(selection: string[]) {
if (selection[0]) {
image.value = selection[0];
} else {
image.value = null;
emit('upload', null);
}
}
watch(
() => item.value,
(id) => {
if (error.value === null && loading.value === false) {
emit('upload', item.value);
}
}
);
return { setSelection };
}
function useURLImport() {
const url = ref('');
const loading = ref(false);
const error = ref(null);
const isValidURL = computed(() => {
try {
new URL(url.value);
return true;
} catch {
return false;
}
});
return { url, loading, error, isValidURL, importFromURL };
async function importFromURL() {
loading.value = true;
try {
const response = await api.post(`/files/import`, {
url: url.value,
});
emit('upload', response.data.data);
activeDialog.value = null;
url.value = '';
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
}
},
});
</script>
@@ -214,4 +343,17 @@ export default defineComponent({
width: calc(100% - 64px);
}
}
.options {
position: absolute;
top: 12px;
right: 12px;
color: var(--foreground-subdued);
cursor: pointer;
transition: color var(--medium) var(--transition);
}
.v-upload:hover .options {
color: var(--primary);
}
</style>

View File

@@ -71,7 +71,7 @@
<v-card>
<v-card-title>{{ $t('upload_from_device') }}</v-card-title>
<v-card-text>
<v-upload @upload="onUpload" />
<v-upload @upload="onUpload" fromUrl />
</v-card-text>
<v-card-actions>
<v-button @click="activeDialog = null" secondary>{{ $t('cancel') }}</v-button>

View File

@@ -59,7 +59,7 @@
<v-dialog v-model="showUpload">
<v-card>
<v-card-title>{{ $t('upload_file') }}</v-card-title>
<v-card-text><v-upload @upload="onUpload" multiple /></v-card-text>
<v-card-text><v-upload @upload="onUpload" multiple fromUrl /></v-card-text>
<v-card-actions>
<v-button @click="showUpload = false">{{ $t('done') }}</v-button>
</v-card-actions>

View File

@@ -45,53 +45,7 @@
/>
<file-lightbox v-model="lightboxActive" :id="image.id" />
</div>
<template v-else>
<v-upload @upload="setImage" />
<v-menu showArrow placement="bottom-end">
<template #activator="{ toggle }">
<v-icon @click="toggle" class="options" name="more_vert" />
</template>
<v-list>
<v-list-item @click="activeDialog = 'choose'">
<v-list-item-icon><v-icon name="folder_open" /></v-list-item-icon>
<v-list-item-content>
{{ $t('choose_from_library') }}
</v-list-item-content>
</v-list-item>
<v-list-item @click="activeDialog = 'url'">
<v-list-item-icon><v-icon name="link" /></v-list-item-icon>
<v-list-item-content>
{{ $t('import_from_url') }}
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
<modal-browse
collection="directus_files"
:active="activeDialog === 'choose'"
@update:active="activeDialog = null"
@input="setSelection"
/>
<v-dialog :active="activeDialog === 'url'" @toggle="activeDialog = null" :persistent="urlLoading">
<v-card>
<v-card-title>{{ $t('import_from_url') }}</v-card-title>
<v-card-text>
<v-input :placeholder="$t('url')" v-model="url" :disabled="urlLoading" />
</v-card-text>
<v-card-actions>
<v-button :disabled="urlLoading" @click="activeDialog = null" secondary>
{{ $t('cancel') }}
</v-button>
<v-button :loading="urlLoading" @click="importFromURL" :disabled="isValidURL === false">
{{ $t('import') }}
</v-button>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<v-upload v-else @upload="setImage" fromLibrary fromUrl />
</div>
</template>
@@ -102,7 +56,7 @@ import formatFilesize from '@/utils/format-filesize';
import i18n from '@/lang';
import FileLightbox from '@/views/private/components/file-lightbox';
import ImageEditor from '@/views/private/components/image-editor';
import ModalBrowse from '@/views/private/components/modal-browse';
import { nanoid } from 'nanoid';
import getRootPath from '@/utils/get-root-path';
@@ -116,7 +70,7 @@ type Image = {
};
export default defineComponent({
components: { FileLightbox, ImageEditor, ModalBrowse },
components: { FileLightbox, ImageEditor },
props: {
value: {
type: String,
@@ -128,7 +82,6 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const activeDialog = ref<'choose' | 'url' | null>(null);
const loading = ref(false);
const image = ref<Image | null>(null);
const error = ref(null);
@@ -180,8 +133,6 @@ export default defineComponent({
}
);
const { url, isValidURL, loading: urlLoading, error: urlError, importFromURL } = useURLImport();
return {
loading,
image,
@@ -194,12 +145,6 @@ export default defineComponent({
setImage,
deselect,
downloadSrc,
activeDialog,
setSelection,
url,
isValidURL,
urlLoading,
importFromURL,
};
async function fetchImage() {
@@ -238,51 +183,6 @@ export default defineComponent({
lightboxActive.value = false;
editorActive.value = false;
}
function setSelection(selection: number[]) {
if (selection[0]) {
emit('input', selection[0]);
} else {
emit('input', null);
}
}
function useURLImport() {
const url = ref('');
const loading = ref(false);
const error = ref(null);
const isValidURL = computed(() => {
try {
new URL(url.value);
return true;
} catch {
return false;
}
});
return { url, loading, error, isValidURL, importFromURL };
async function importFromURL() {
loading.value = true;
try {
const response = await api.post(`/files/import`, {
url: url.value,
});
image.value = response.data.data;
activeDialog.value = null;
url.value = '';
emit('input', image.value?.id);
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
}
}
},
});
</script>
@@ -402,17 +302,4 @@ img {
.disabled-placeholder {
height: var(--input-height-tall);
}
.options {
position: absolute;
top: 13px;
right: 13px;
color: var(--foreground-subdued);
cursor: pointer;
transition: color var(--medium) var(--transition);
}
.image:hover .options {
color: var(--primary);
}
</style>

View File

@@ -3,7 +3,7 @@
<v-card>
<v-card-title>{{ $t('add_file') }}</v-card-title>
<v-card-text>
<v-upload :preset="preset" multiple @upload="close" />
<v-upload :preset="preset" multiple @upload="close" fromUrl />
</v-card-text>
<v-card-actions>
<v-button secondary @click="close">{{ $t('done') }}</v-button>