feat: render CSVs as table (#5569)
Co-authored-by: Henrique Dias <mail@hacdias.com>
This commit is contained in:
@@ -69,6 +69,12 @@ const currentView = computed(() => {
|
||||
|
||||
if (fileStore.req.isDir) {
|
||||
return FileListing;
|
||||
} else if (fileStore.req.extension.toLowerCase() === ".csv") {
|
||||
// CSV files use Preview for table view, unless ?edit=true
|
||||
if (route.query.edit === "true") {
|
||||
return Editor;
|
||||
}
|
||||
return Preview;
|
||||
} else if (
|
||||
fileStore.req.type === "text" ||
|
||||
fileStore.req.type === "textImmutable"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
@mousemove="toggleNavigation"
|
||||
@touchstart="toggleNavigation"
|
||||
>
|
||||
<header-bar v-if="isPdf || isEpub || showNav">
|
||||
<header-bar v-if="isPdf || isEpub || isCsv || showNav">
|
||||
<action icon="close" :label="$t('buttons.close')" @action="close()" />
|
||||
<title>{{ name }}</title>
|
||||
<action
|
||||
@@ -24,6 +24,13 @@
|
||||
:label="$t('buttons.rename')"
|
||||
show="rename"
|
||||
/>
|
||||
<action
|
||||
:disabled="layoutStore.loading"
|
||||
v-if="isCsv && authStore.user?.perm.modify"
|
||||
icon="edit_note"
|
||||
:label="t('buttons.editAsText')"
|
||||
@action="editAsText"
|
||||
/>
|
||||
<action
|
||||
:disabled="layoutStore.loading"
|
||||
v-if="authStore.user?.perm.delete"
|
||||
@@ -87,6 +94,7 @@
|
||||
<span>{{ size }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
<CsvViewer v-else-if="isCsv" :content="csvContent" :error="csvError" />
|
||||
<ExtendedImage
|
||||
v-else-if="fileStore.req?.type == 'image'"
|
||||
:src="previewUrl"
|
||||
@@ -176,11 +184,17 @@ import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||
import Action from "@/components/header/Action.vue";
|
||||
import ExtendedImage from "@/components/files/ExtendedImage.vue";
|
||||
import VideoPlayer from "@/components/files/VideoPlayer.vue";
|
||||
import CsvViewer from "@/components/files/CsvViewer.vue";
|
||||
import { VueReader } from "vue-reader";
|
||||
import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import type { Rendition } from "epubjs";
|
||||
import { getTheme } from "@/utils/theme";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
// CSV file size limit for preview (5MB)
|
||||
// Prevents browser memory issues with large files
|
||||
const CSV_MAX_SIZE = 5 * 1024 * 1024;
|
||||
|
||||
const location = useStorage("book-progress", 0, undefined, {
|
||||
serializer: {
|
||||
@@ -239,6 +253,8 @@ const hoverNav = ref<boolean>(false);
|
||||
const autoPlay = ref<boolean>(false);
|
||||
const previousRaw = ref<string>("");
|
||||
const nextRaw = ref<string>("");
|
||||
const csvContent = ref<string>("");
|
||||
const csvError = ref<string>("");
|
||||
|
||||
const player = ref<HTMLVideoElement | HTMLAudioElement | null>(null);
|
||||
|
||||
@@ -248,6 +264,8 @@ const authStore = useAuthStore();
|
||||
const fileStore = useFileStore();
|
||||
const layoutStore = useLayoutStore();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -279,6 +297,7 @@ const isPdf = computed(() => fileStore.req?.extension.toLowerCase() == ".pdf");
|
||||
const isEpub = computed(
|
||||
() => fileStore.req?.extension.toLowerCase() == ".epub"
|
||||
);
|
||||
const isCsv = computed(() => fileStore.req?.extension.toLowerCase() == ".csv");
|
||||
|
||||
const isResizeEnabled = computed(() => resizePreview);
|
||||
|
||||
@@ -366,6 +385,18 @@ const updatePreview = async () => {
|
||||
const dirs = route.fullPath.split("/");
|
||||
name.value = decodeURIComponent(dirs[dirs.length - 1]);
|
||||
|
||||
// Load CSV content if it's a CSV file
|
||||
if (isCsv.value && fileStore.req) {
|
||||
csvContent.value = "";
|
||||
csvError.value = "";
|
||||
|
||||
if (fileStore.req.size > CSV_MAX_SIZE) {
|
||||
csvError.value = t("files.csvTooLarge");
|
||||
} else {
|
||||
csvContent.value = fileStore.req.content ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
if (!listing.value) {
|
||||
try {
|
||||
const path = url.removeLastDir(route.path);
|
||||
@@ -435,4 +466,8 @@ const close = () => {
|
||||
};
|
||||
|
||||
const download = () => window.open(downloadUrl.value);
|
||||
|
||||
const editAsText = () => {
|
||||
router.push({ path: route.path, query: { edit: "true" } });
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user