Add support for actual renaming of files, and UI on plain tree.

This commit is contained in:
Leo Vasanko
2023-11-02 17:37:28 +00:00
parent 68a701538b
commit f99d92b217
12 changed files with 724 additions and 20 deletions

View File

@@ -24,6 +24,7 @@ declare module 'vue' {
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
FileCarousel: typeof import('./src/components/FileCarousel.vue')['default']
FileExplorer: typeof import('./src/components/FileExplorer.vue')['default']
FileRenameInput: typeof import('./src/components/FileRenameInput.vue')['default']
FileViewer: typeof import('./src/components/FileViewer.vue')['default']
HeaderMain: typeof import('./src/components/HeaderMain.vue')['default']
LoginModal: typeof import('./src/components/LoginModal.vue')['default']

View File

@@ -19,7 +19,11 @@
<tr v-for="doc of sorted(documentStore.mainDocument as FolderDocument[])" :key="doc.key" :class="doc.type === 'folder' ? 'folder' : 'file'">
<td class="selection"><input type="checkbox" v-model="doc.selected"></td>
<td class="name">
<a :href="url_for(doc)">{{doc.name}}</a>
<template v-if="editing === doc"><FileRenameInput :doc="doc" :rename="rename" :exit="() => { editing = null}"/></template>
<template v-else>
<a :href="url_for(doc)">{{doc.name}}</a>
<button @click="() => editing = doc">🖊</button>
</template>
</td>
<td class="right">{{doc.modified}}</td>
<td class="right">{{doc.sizedisp}}</td>
@@ -38,6 +42,8 @@
import { message } from 'ant-design-vue';
import type { Document, FolderDocument } from '@/repositories/Document';
import FileCarousel from './FileCarousel.vue';
import FileRenameInput from './FileRenameInput.vue'
import createWebSocket from '@/repositories/WS';
const [messageApi, contextHolder] = message.useMessage();
@@ -57,6 +63,30 @@
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
const url_for = (doc: FolderDocument) => doc.type === "folder" ? `#${linkBasePath.value}/${doc.name}` : `${filesBasePath}/${doc.name}`
// File rename
const editing = ref<FolderDocument | null>(null)
const rename = (doc: FolderDocument, newName: string) => {
const oldName = doc.name
const control = createWebSocket("/api/control", (ev: MessageEvent) => {
const msg = JSON.parse(ev.data)
if ("error" in msg) {
console.error("Rename failed", msg.error.message, msg.error)
doc.name = oldName
} else {
console.log("Rename succeeded", msg)
}
})
control.onopen = () => {
control.send(JSON.stringify({
"op": "rename",
"path": `${linkBasePath.value}/${oldName}`,
"to": newName
}))
}
doc.name = newName // We should get an update from watch but this is quicker
}
// Column sort
const toggleSort = (name: string) => { sort.value = sort.value === name ? "" : name }
const sort = ref<string>("")
const sortCompare = {
@@ -107,6 +137,23 @@
overflow: hidden;
text-overflow: ellipsis;
}
.name {
white-space: nowrap;
text-overflow: initial;
overflow: initial;
}
.name button {
visibility: hidden;
padding-left: 1em;
}
.name:hover button {
visibility: visible;
}
.name button {
cursor: pointer;
border: 0;
background: transparent;
}
thead tr {
border: 1px solid #ddd;
background: #ddd;
@@ -157,9 +204,6 @@
display: flex;
align-items: center;
}
.name{
max-width: 70%;
}
.edit-action{
min-width: 5%;
}
@@ -177,11 +221,4 @@
content: '📁 ';
font-size: 1.5em;
}
.editable-cell-text-wrapper .editable-cell-icon {
visibility: hidden; /* Oculta el ícono de manera predeterminada */
}
.editable-cell-text-wrapper:hover .editable-cell-icon {
visibility: visible; /* Muestra el ícono al hacer hover en el contenedor */
}
</style>

View File

@@ -0,0 +1,47 @@
<template>
<input
ref="input"
id="FileRenameInput"
type="text"
:value="doc.name"
@keyup.esc="exit"
@keyup.enter="apply"
>
</template>
<script setup lang="ts">
import type { FolderDocument } from '@/repositories/Document'
import { ref, onMounted } from 'vue'
const input = ref<HTMLInputElement | null>(null)
onMounted(() => {
const ext = input.value!.value.lastIndexOf('.')
input.value!.focus()
input.value!.setSelectionRange(0, ext > 0 ? ext : input.value!.value.length)
})
const props = defineProps < {
doc: FolderDocument
rename: (doc: FolderDocument, newName: string) => void
exit: () => void
} > ()
const apply = () => {
const name = input.value!.value
props.exit()
if (name === props.doc.name || name.length === 0) return
props.rename(props.doc, name)
}
</script>
<style>
input#FileRenameInput {
color: #8f8;
border: 0;
padding: 0;
width: 90%;
outline: none;
background: transparent;
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<object
<object
v-if="props.type === 'pdf'"
:data= "dataURL"
type="application/pdf" width="100%"
:data= "dataURL"
type="application/pdf" width="100%"
height="100%"
>
>
</object>
<a-image
v-else-if="props.type === 'image'"
@@ -31,12 +31,12 @@ import { url_document_get } from '@/repositories/Document';
const dataURL = ref('')
watchEffect(()=>{
dataURL.value = new URL(
url_document_get + Router.currentRoute.value.path,
url_document_get + Router.currentRoute.value.path,
location.origin
).toString();
})
const emit = defineEmits({
visibleImg(value: boolean){
visibleImg(value: boolean){
return value
}
})
@@ -52,4 +52,4 @@ const props = defineProps < {
} > ()
</script>
<style></style>
<style></style>