Open current folder in library / detail

This commit is contained in:
rijkvanzanten
2020-08-11 17:13:13 -04:00
parent 830b8a514b
commit 400c4291cd
12 changed files with 128 additions and 28 deletions

View File

@@ -126,7 +126,11 @@ export default defineComponent({
if (notEmpty(props.to)) return 'router-link';
return 'button';
});
const { active, toggle } = useGroupable(props.value, 'button-group');
const { active, toggle } = useGroupable({
value: props.value,
group: 'button-group',
});
return { sizeClass, onClick, component, active, toggle };

View File

@@ -20,7 +20,11 @@ export default defineComponent({
},
},
setup(props) {
const { active, toggle } = useGroupable(props.value, props.scope);
const { active, toggle } = useGroupable({
value: props.value,
group: props.scope,
});
return { active, toggle };
},
});

View File

@@ -17,7 +17,7 @@
</template>
<script lang="ts">
import { defineComponent, toRefs } from '@vue/composition-api';
import { defineComponent, toRefs, watch } from '@vue/composition-api';
import { useGroupableParent, useGroupable } from '@/composables/groupable';
export default defineComponent({
@@ -42,9 +42,17 @@ export default defineComponent({
type: Boolean,
default: false,
},
open: {
type: Boolean,
default: false,
},
},
setup(props, { listeners, emit }) {
const { active: groupActive, toggle } = useGroupable();
const { active: groupActive, toggle, activate, deactivate } = useGroupable({
active: toRefs(props).open,
});
// watch(() => props.open, () => props.open ? activate() : deactivate(), { immediate: true });
useGroupableParent(
{},

View File

@@ -16,7 +16,7 @@ export default defineComponent({
},
},
setup(props) {
const { active, toggle } = useGroupable(props.value);
const { active, toggle } = useGroupable({ value: props.value });
return { active, toggle };
},
});

View File

@@ -23,7 +23,11 @@ export default defineComponent({
},
},
setup(props) {
const { active, toggle } = useGroupable(props.value, 'v-tabs');
const { active, toggle } = useGroupable({
value: props.value,
group: 'v-tabs',
});
const vertical = inject('v-tabs-vertical', ref(false));
return { active, toggle, onClick, vertical };

View File

@@ -40,7 +40,7 @@ describe('Groupable', () => {
mountComposable(() => {
provide('item-group', { register, unregister, toggle });
useGroupable('custom-value');
useGroupable({ value: 'custom-value' });
});
expect(register).toHaveBeenCalledWith({
@@ -56,7 +56,7 @@ describe('Groupable', () => {
mountComposable(() => {
provide('item-group', { register, unregister, toggle });
const result = useGroupable('custom-value');
const result = useGroupable({ value: 'custom-value' });
expect(result!.active).toEqual({ value: false });
expect(result!.toggle).toBeInstanceOf(Function);
});
@@ -69,7 +69,7 @@ describe('Groupable', () => {
mountComposable(() => {
provide('item-group', { register, unregister, toggle });
const result = useGroupable('custom-value');
const result = useGroupable({ value: 'custom-value' });
result!.toggle();
expect(toggle).toHaveBeenCalled();
});
@@ -82,7 +82,7 @@ describe('Groupable', () => {
mountComposable(() => {
provide('item-group', { register, unregister, toggle });
const result = useGroupable('custom-value');
const result = useGroupable({ value: 'custom-value' });
result!.toggle();
expect(result!.active).toEqual({ value: true });
});

View File

@@ -11,15 +11,25 @@ type GroupableInstance = {
* Used to make child item part of the group context. Needs to be used in a component that is a child
* of a component that has the `useGroupableParent` composition enabled
*/
export function useGroupable(value?: string | number, group = 'item-group') {
type GroupableOptions = {
value?: string | number;
group?: string;
active?: Ref<boolean>;
};
export function useGroupable(options?: GroupableOptions) {
// Injects the registration / toggle functions from the parent scope
const parentFunctions = inject(group, null);
const parentFunctions = inject(options?.group || 'item-group', null);
if (isEmpty(parentFunctions)) {
return {
active: ref(false),
// eslint-disable-next-line @typescript-eslint/no-empty-function
toggle: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
activate: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
deactivate: () => {},
};
}
@@ -34,9 +44,28 @@ export function useGroupable(value?: string | number, group = 'item-group') {
} = parentFunctions;
const active = ref(false);
const item = { active, value };
const item = { active, value: options?.value };
register(item);
if (options?.active) {
if (options.active.value === true) toggle(item);
watch(options.active, () => {
if (options.active === undefined) return;
if (options.active.value === true) {
if (active.value === false) toggle(item);
active.value = true;
}
if (options.active.value === false) {
if (active.value === true) toggle(item);
active.value = false;
}
});
}
onBeforeUnmount(() => unregister(item));
return {
@@ -45,6 +74,14 @@ export function useGroupable(value?: string | number, group = 'item-group') {
active.value = !active.value;
toggle(item);
},
activate: () => {
if (active.value === false) toggle(item);
active.value = true;
},
deactivate: () => {
if (active.value === true) toggle(item);
active.value = false;
},
};
}

View File

@@ -17,10 +17,11 @@
:active="currentFolder === folder.id"
exact
@contextmenu.native.prevent="$refs.contextMenu.activate"
:open="isOpen"
>
<template #activator="{ active }">
<template #activator>
<v-list-item-icon>
<v-icon :name="active ? 'folder_open' : 'folder'" />
<v-icon name="folder" />
</v-list-item-icon>
<v-list-item-content>{{ folder.name }}</v-list-item-content>
</template>
@@ -30,6 +31,7 @@
:folder="childFolder"
:current-folder="currentFolder"
:click-handler="clickHandler"
:start-open-folders="startOpenFolders"
/>
</v-list-group>
@@ -106,7 +108,7 @@
</template>
<script lang="ts">
import { defineComponent, PropType, ref } from '@vue/composition-api';
import { defineComponent, PropType, ref, watch, computed } from '@vue/composition-api';
import useFolders, { Folder } from '../../composables/use-folders';
import notify from '@/utils/notify';
import api from '@/api';
@@ -129,6 +131,10 @@ export default defineComponent({
type: Function,
default: () => undefined,
},
startOpenFolders: {
type: Array as PropType<string[]>,
default: () => [],
},
},
setup(props) {
const { renameActive, renameValue, renameSave, renameSaving } = useRenameFolder();
@@ -137,6 +143,10 @@ export default defineComponent({
const { fetchFolders } = useFolders();
const isOpen = computed(() => {
return props.startOpenFolders.includes(props.folder.id);
});
return {
renameActive,
renameValue,
@@ -149,6 +159,7 @@ export default defineComponent({
deleteActive,
deleteSave,
deleteSaving,
isOpen,
};
function useRenameFolder() {

View File

@@ -5,9 +5,9 @@
<v-list-item-content>{{ $t('all_files') }}</v-list-item-content>
</v-list-item>
<v-divider v-if="loading || folders.length > 0" />
<v-divider v-if="loading || nestedFolders.length > 0" />
<template v-if="loading && (folders === null || folders.length === 0)">
<template v-if="loading && (nestedFolders === null || nestedFolders.length === 0)">
<v-list-item v-for="n in 4" :key="n">
<v-skeleton-loader type="list-item-icon" />
</v-list-item>
@@ -15,17 +15,18 @@
<div class="folders">
<navigation-folder
v-for="folder in folders"
v-for="folder in nestedFolders"
:key="folder.id"
:folder="folder"
:current-folder="currentFolder"
:start-open-folders="startOpenFolders"
/>
</div>
</v-list>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import { defineComponent, computed } from '@vue/composition-api';
import useFolders from '../../composables/use-folders';
import NavigationFolder from './navigation-folder.vue';
@@ -41,10 +42,31 @@ export default defineComponent({
default: null,
},
},
setup() {
const { folders, error, loading } = useFolders();
setup(props) {
const { nestedFolders, folders, error, loading } = useFolders();
return { folders, error, loading };
const startOpenFolders = computed(() => {
if (!folders.value) return [];
const openFolders: string[] = [];
parseFolder(props.currentFolder);
return openFolders;
function parseFolder(id: string) {
if (!folders.value) return;
openFolders.push(id);
const folder = folders.value.find((folder) => folder.id === id);
if (folder && folder.parent_folder) {
parseFolder(folder.parent_folder);
}
}
});
return { folders, nestedFolders, error, loading, startOpenFolders };
},
});
</script>

View File

@@ -16,23 +16,26 @@ export type Folder = {
let loading: Ref<boolean> | null = null;
let folders: Ref<Folder[] | null> | null = null;
let nestedFolders: Ref<Folder[] | null> | null = null;
let error: Ref<any> | null = null;
export default function useFolders() {
if (loading === null) loading = ref(false);
if (folders === null) folders = ref<Folder[] | null>(null);
if (nestedFolders === null) nestedFolders = ref<Folder[] | null>(null);
if (error === null) error = ref(null);
if (folders.value === null && loading.value === false) {
fetchFolders();
}
return { loading, folders, error, fetchFolders };
return { loading, folders, nestedFolders, error, fetchFolders };
async function fetchFolders() {
if (loading === null) return;
if (folders === null) return;
if (nestedFolders === null) return;
if (error === null) return;
loading.value = true;
@@ -45,7 +48,8 @@ export default function useFolders() {
},
});
folders.value = nestFolders(response.data.data);
folders.value = response.data.data;
nestedFolders.value = nestFolders(response.data.data);
} catch (err) {
error.value = err;
} finally {

View File

@@ -84,7 +84,7 @@
</template>
<template #navigation>
<files-navigation />
<files-navigation :current-folder="queryFilters && queryFilters.folder" />
</template>
<component
@@ -130,6 +130,7 @@ import marked from 'marked';
import FolderPicker from '../../components/folder-picker';
import emitter, { Events } from '@/events';
import router from '@/router';
import Vue from 'vue';
type Item = {
[field: string]: any;
@@ -287,11 +288,13 @@ export default defineComponent({
});
selection.value = [];
await layout.value?.refresh();
if (selectedFolder.value) {
router.push(`/files?folder=${selectedFolder.value}`);
}
await Vue.nextTick();
await refresh();
} catch (err) {
console.error(err);
} finally {

View File

@@ -48,7 +48,10 @@ export default defineComponent({
},
},
setup(props) {
const { active, toggle } = useGroupable(props.title, 'drawer-detail');
const { active, toggle } = useGroupable({
value: props.title,
group: 'drawer-detail',
});
const appStore = useAppStore();
const { drawerOpen } = toRefs(appStore.state);
return { active, toggle, drawerOpen };