mirror of
https://github.com/45Drives/cockpit-navigator.git
synced 2025-07-30 00:55:30 +02:00
contextmenu gets selection not entry
This commit is contained in:
parent
4a779f2198
commit
5e5e4ea64b
@ -28,6 +28,7 @@ If not, see <https://www.gnu.org/licenses/>.
|
|||||||
v-if="show"
|
v-if="show"
|
||||||
class="fixed inset-0 bg-transparent"
|
class="fixed inset-0 bg-transparent"
|
||||||
@click="$emit('hide')"
|
@click="$emit('hide')"
|
||||||
|
@contextmenu.prevent="$emit('hide')"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="fixed z-20 max-w-sm flex flex-col items-stretch bg-default shadow-lg divide-y divide-default position-contextmenu">
|
class="fixed z-20 max-w-sm flex flex-col items-stretch bg-default shadow-lg divide-y divide-default position-contextmenu">
|
||||||
@ -54,51 +55,152 @@ If not, see <https://www.gnu.org/licenses/>.
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-stretch">
|
<div class="flex flex-col items-stretch">
|
||||||
<!-- general actions -->
|
<!-- Non-selection actions -->
|
||||||
<button
|
|
||||||
v-if="entry?.path !== '/'"
|
|
||||||
class="context-menu-button"
|
|
||||||
@click="$emit('browserAction', 'editPermissions', entry)"
|
|
||||||
>
|
|
||||||
Edit permissions
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="entry?.resolvedType === 'f'"
|
|
||||||
class="flex flex-col items-stretch"
|
|
||||||
>
|
|
||||||
<!-- regular file actions -->
|
|
||||||
<button
|
<button
|
||||||
class="context-menu-button"
|
class="context-menu-button"
|
||||||
@click="$emit('browserAction', 'edit', entry)"
|
@click="$emit('browserAction', 'createFile', selection[0])"
|
||||||
>
|
>
|
||||||
Edit contents
|
<DocumentAddIcon class="size-icon icon-default" />
|
||||||
|
<span>New file</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="context-menu-button"
|
class="context-menu-button"
|
||||||
@click="$emit('browserAction', 'download', entry)"
|
@click="$emit('browserAction', 'createDirectory', selection[0])"
|
||||||
>
|
>
|
||||||
Download
|
<FolderAddIcon class="size-icon icon-default" />
|
||||||
|
<span>New directory</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="entry?.resolvedType === 'd'"
|
|
||||||
class="flex flex-col items-stretch"
|
|
||||||
>
|
|
||||||
<!-- directory actions -->
|
|
||||||
<button
|
<button
|
||||||
class="context-menu-button"
|
class="context-menu-button"
|
||||||
@click="$emit('browserAction', 'cd', entry)"
|
@click="$emit('browserAction', 'createLink', selection[0])"
|
||||||
>
|
>
|
||||||
Open
|
<LinkIcon class="size-icon icon-default" />
|
||||||
|
<span>New link</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<template v-if="selection.length === 0">
|
||||||
v-if="entry?.type === 'l'"
|
<!-- Current directory actions -->
|
||||||
class="flex flex-col items-stretch"
|
<div class="flex flex-col items-stretch">
|
||||||
>
|
<button
|
||||||
<!-- link actions -->
|
class="context-menu-button"
|
||||||
</div>
|
@click="$emit('browserAction', 'download', currentDirEntry)"
|
||||||
|
>
|
||||||
|
<FolderDownloadIcon class="size-icon icon-default" />
|
||||||
|
<span>Zip and download directory</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-stretch">
|
||||||
|
<button
|
||||||
|
v-if="currentDirEntry?.path !== '/'"
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'editPermissions', currentDirEntry)"
|
||||||
|
>
|
||||||
|
<KeyIcon class="size-icon icon-default" />
|
||||||
|
<span>Edit permissions</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="selection.length === 1">
|
||||||
|
<!-- Single entry selection actions -->
|
||||||
|
<div
|
||||||
|
v-if="selection[0]?.resolvedType === 'f'"
|
||||||
|
class="flex flex-col items-stretch"
|
||||||
|
>
|
||||||
|
<!-- regular file actions -->
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'edit', selection[0])"
|
||||||
|
>
|
||||||
|
<PencilAltIcon class="size-icon icon-default" />
|
||||||
|
<span>Edit contents</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'download', selection[0])"
|
||||||
|
>
|
||||||
|
<DocumentDownloadIcon class="size-icon icon-default" />
|
||||||
|
<span>Download</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="selection[0]?.resolvedType === 'd'"
|
||||||
|
class="flex flex-col items-stretch"
|
||||||
|
>
|
||||||
|
<!-- directory actions -->
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'cd', selection[0])"
|
||||||
|
>
|
||||||
|
<FolderOpenIcon class="size-icon icon-default" />
|
||||||
|
<span>Open</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'download', selection[0])"
|
||||||
|
>
|
||||||
|
<FolderDownloadIcon class="size-icon icon-default" />
|
||||||
|
<span>Zip and download directory</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="selection[0]?.type === 'l'"
|
||||||
|
class="flex flex-col items-stretch"
|
||||||
|
>
|
||||||
|
<!-- link actions -->
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'editLink', selection[0])"
|
||||||
|
>
|
||||||
|
<LinkIcon class="size-icon icon-default" />
|
||||||
|
<span>Edit link target</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-stretch">
|
||||||
|
<!-- general actions -->
|
||||||
|
<button
|
||||||
|
v-if="selection[0]?.path !== '/'"
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'editPermissions', selection[0])"
|
||||||
|
>
|
||||||
|
<KeyIcon class="size-icon icon-default" />
|
||||||
|
<span>Edit permissions</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="selection[0]?.path !== '/'"
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'rename', selection[0])"
|
||||||
|
>
|
||||||
|
<PencilIcon class="size-icon icon-default" />
|
||||||
|
<span>Rename</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'delete', selection[0])"
|
||||||
|
>
|
||||||
|
<TrashIcon class="size-icon icon-default" />
|
||||||
|
<span>Delete</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<tempalte v-else>
|
||||||
|
<!-- Multi-entry selection actions -->
|
||||||
|
<div class="flex flex-col items-stretch">
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'download', [...selection])"
|
||||||
|
>
|
||||||
|
<DownloadIcon class="size-icon-sm icon-default" />
|
||||||
|
<span>Zip and download {{ selection.length }} items</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="context-menu-button"
|
||||||
|
@click="$emit('browserAction', 'delete', [...selection])"
|
||||||
|
>
|
||||||
|
<TrashIcon class="size-icon-sm icon-default" />
|
||||||
|
<span>Delete {{ selection.length }} items</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</tempalte>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
@ -106,14 +208,30 @@ If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { inject } from 'vue'
|
import { inject } from 'vue'
|
||||||
import { ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon } from '@heroicons/vue/solid';
|
import {
|
||||||
|
ArrowLeftIcon,
|
||||||
|
ArrowRightIcon,
|
||||||
|
ArrowUpIcon,
|
||||||
|
DocumentAddIcon,
|
||||||
|
DocumentDownloadIcon,
|
||||||
|
TrashIcon,
|
||||||
|
FolderAddIcon,
|
||||||
|
FolderDownloadIcon,
|
||||||
|
FolderOpenIcon,
|
||||||
|
LinkIcon,
|
||||||
|
PencilAltIcon,
|
||||||
|
PencilIcon,
|
||||||
|
KeyIcon,
|
||||||
|
DownloadIcon,
|
||||||
|
} from '@heroicons/vue/solid';
|
||||||
import { pathHistoryInjectionKey } from '../keys';
|
import { pathHistoryInjectionKey } from '../keys';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
event: Object,
|
event: Object,
|
||||||
entry: Object,
|
selection: Array,
|
||||||
|
currentDirEntry: Object,
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const pathHistory = inject(pathHistoryInjectionKey);
|
const pathHistory = inject(pathHistoryInjectionKey);
|
||||||
@ -126,6 +244,17 @@ export default {
|
|||||||
ArrowLeftIcon,
|
ArrowLeftIcon,
|
||||||
ArrowRightIcon,
|
ArrowRightIcon,
|
||||||
ArrowUpIcon,
|
ArrowUpIcon,
|
||||||
|
DocumentAddIcon,
|
||||||
|
DocumentDownloadIcon,
|
||||||
|
TrashIcon,
|
||||||
|
FolderAddIcon,
|
||||||
|
FolderDownloadIcon,
|
||||||
|
FolderOpenIcon,
|
||||||
|
LinkIcon,
|
||||||
|
PencilAltIcon,
|
||||||
|
PencilIcon,
|
||||||
|
KeyIcon,
|
||||||
|
DownloadIcon,
|
||||||
},
|
},
|
||||||
emits: [
|
emits: [
|
||||||
'hide',
|
'hide',
|
||||||
@ -141,7 +270,7 @@ div.position-contextmenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button.context-menu-button {
|
button.context-menu-button {
|
||||||
@apply text-default font-normal px-4 py-2 text-sm text-left;
|
@apply text-default font-normal pl-1 pr-2 text-sm text-left flex items-center gap-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.context-menu-button:hover {
|
button.context-menu-button:hover {
|
||||||
|
@ -163,8 +163,9 @@
|
|||||||
/>
|
/>
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
:show="contextMenu.show"
|
:show="contextMenu.show"
|
||||||
:entry="contextMenu.entry"
|
:selection="contextMenu.selection"
|
||||||
:event="contextMenu.event"
|
:event="contextMenu.event"
|
||||||
|
:currentDirEntry="{...pathHistory.current(), name: `Current directory (${pathHistory.current().path.split('/').pop()})`}"
|
||||||
@browserAction="handleAction"
|
@browserAction="handleAction"
|
||||||
@hide="contextMenu.close"
|
@hide="contextMenu.close"
|
||||||
/>
|
/>
|
||||||
@ -307,19 +308,19 @@ export default {
|
|||||||
});
|
});
|
||||||
const contextMenu = reactive({
|
const contextMenu = reactive({
|
||||||
show: false,
|
show: false,
|
||||||
entry: null,
|
selection: [],
|
||||||
event: null,
|
event: null,
|
||||||
resetTimeoutHandle: null,
|
resetTimeoutHandle: null,
|
||||||
open: (entry, event) => {
|
open: (event) => {
|
||||||
clearTimeout(contextMenu.resetTimeoutHandle);
|
clearTimeout(contextMenu.resetTimeoutHandle);
|
||||||
contextMenu.entry = entry;
|
contextMenu.selection = getSelected();
|
||||||
contextMenu.event = event;
|
contextMenu.event = event;
|
||||||
contextMenu.show = true;
|
contextMenu.show = true;
|
||||||
},
|
},
|
||||||
close: () => {
|
close: () => {
|
||||||
contextMenu.show = false;
|
contextMenu.show = false;
|
||||||
contextMenu.resetTimeoutHandle = setTimeout(() => {
|
contextMenu.resetTimeoutHandle = setTimeout(() => {
|
||||||
contextMenu.resetTimeoutHandle = contextMenu.entry = null;
|
contextMenu.resetTimeoutHandle = contextMenu.selection = [];
|
||||||
contextMenu.resetTimeoutHandle = contextMenu.event = null;
|
contextMenu.resetTimeoutHandle = contextMenu.event = null;
|
||||||
}, 500);
|
}, 500);
|
||||||
},
|
},
|
||||||
@ -349,9 +350,12 @@ export default {
|
|||||||
router.push(`/edit/${newHost}${newPath}`);
|
router.push(`/edit/${newHost}${newPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const download = ({ path, name, host }) => {
|
const download = (selection) => {
|
||||||
fileDownload(path, name, host);
|
const items = [].concat(selection); // forces to be array
|
||||||
console.log('download', `${host}:${path}`);
|
if (items.length === 1 && items[0].resolvedType === 'f') {
|
||||||
|
let { path, name, host } = items[0];
|
||||||
|
fileDownload(path, name, host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSelected = () => directoryViewRef.value?.getSelected?.() ?? [];
|
const getSelected = () => directoryViewRef.value?.getSelected?.() ?? [];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user