Prettier file listing, using browser instead of viewer for file display (for now), sorting improved, modified timestamps improved.
This commit is contained in:
parent
63bbe84859
commit
0d186726b5
|
@ -9,7 +9,7 @@
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import HeaderMain from './components/HeaderMain.vue'
|
import HeaderMain from './components/HeaderMain.vue'
|
||||||
import AppNavigation from './components/AppNavigation.vue'
|
import AppNavigation from './components/AppNavigation.vue'
|
||||||
import Router from './router/index';
|
import Router from './router/index';
|
||||||
|
|
||||||
interface Path {
|
interface Path {
|
||||||
path: string;
|
path: string;
|
||||||
|
@ -26,15 +26,16 @@
|
||||||
pathList
|
pathList
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// Update human-readable x seconds ago messages from mtimes
|
||||||
|
setInterval(documentStore.updateModified, 1000)
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const documentHandler = new DocumentHandler()
|
const documentHandler = new DocumentHandler()
|
||||||
const documentUploadHandler = new DocumentUploadHandler()
|
const documentUploadHandler = new DocumentUploadHandler()
|
||||||
const wsWatch = createWebSocket(url_document_watch_ws, documentHandler.handleWebSocketMessage)
|
const wsWatch = createWebSocket(url_document_watch_ws, documentHandler.handleWebSocketMessage)
|
||||||
const wsUpload = createWebSocket(url_document_upload_ws, documentUploadHandler.handleWebSocketMessage)
|
const wsUpload = createWebSocket(url_document_upload_ws, documentUploadHandler.handleWebSocketMessage)
|
||||||
|
|
||||||
documentStore.wsWatch = wsWatch;
|
documentStore.wsWatch = wsWatch;
|
||||||
documentStore.wsUpload = wsUpload;
|
documentStore.wsUpload = wsUpload;
|
||||||
})
|
})
|
||||||
|
|
||||||
export type { Path }
|
export type { Path }
|
||||||
|
@ -45,14 +46,14 @@
|
||||||
<HeaderMain WS="WS"></HeaderMain>
|
<HeaderMain WS="WS"></HeaderMain>
|
||||||
<AppNavigation :path="path.pathList"></AppNavigation>
|
<AppNavigation :path="path.pathList"></AppNavigation>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<RouterView class="page-container" />
|
<RouterView class="page-container" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.wrapper{
|
.wrapper{
|
||||||
background-color: var(--primary-background);
|
background-color: var(--primary-background);
|
||||||
padding: 0.2em 0.5em;
|
padding: 0.2em 0.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|
|
@ -2,30 +2,31 @@
|
||||||
<main>
|
<main>
|
||||||
<!-- <h2 v-if="!documentStore.loading && documentStore.error"> {{ documentStore.error }} </h2> -->
|
<!-- <h2 v-if="!documentStore.loading && documentStore.error"> {{ documentStore.error }} </h2> -->
|
||||||
<div class="carousel-container" v-if="!documentStore.loading && documentStore.mainDocument[0] && documentStore.mainDocument[0].type === 'file'">
|
<div class="carousel-container" v-if="!documentStore.loading && documentStore.mainDocument[0] && documentStore.mainDocument[0].type === 'file'">
|
||||||
<FileCarousel></FileCarousel>
|
<FileCarousel></FileCarousel>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
v-else-if="!documentStore.loading && documentStore.mainDocument"
|
v-else-if="!documentStore.loading && documentStore.mainDocument"
|
||||||
:pagination=false
|
:pagination=false
|
||||||
:row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
|
:row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data-source="documentStore.mainDocument"
|
:data-source="documentStore.mainDocument"
|
||||||
>
|
>
|
||||||
<template #headerCell="{column}"></template>
|
<template #headerCell="{column}"></template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'name'">
|
<template v-if="column.key === 'name'">
|
||||||
<div class="editable-cell">
|
<div class="editable-cell" :class="record.type === 'folder' ? 'folder' : 'file'">
|
||||||
<div v-if="editableData[record.key]" class="action-container editable-cell-input-wrapper">
|
<div v-if="editableData[record.key]" class="action-container editable-cell-input-wrapper">
|
||||||
<a-input class="name" v-model:value="editableData[record.key].name" @pressEnter="save(record.key)" />
|
<a-input class="name" v-model:value="editableData[record.key].name" @pressEnter="save(record.key)" />
|
||||||
<CheckOutlined class="edit-action editable-cell-icon-check" @click="save(record.key)" />
|
<CheckOutlined class="edit-action editable-cell-icon-check" @click="save(record.key)" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="action-container editable-cell-text-wrapper">
|
<div v-else class="action-container editable-cell-text-wrapper">
|
||||||
<a class="name" :href="`#${linkBasePath}/${record.name}`">{{record.name}}</a>
|
<a v-if="record.type === 'folder'" class="name" :href="`#${linkBasePath}/${record.name}`">{{record.name}}</a>
|
||||||
|
<a v-else class="name" :href="`${filesBasePath}/${record.name}`">{{record.name}}</a>
|
||||||
<edit-outlined class="edit-action editable-cell-icon" @click="edit(record.key)" />
|
<edit-outlined class="edit-action editable-cell-icon" @click="edit(record.key)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'action'">
|
<template v-if="column.key === 'action'">
|
||||||
<a-popover trigger="click">
|
<a-popover trigger="click">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
@ -34,19 +35,19 @@
|
||||||
<a-button type="text" class="action-button" :icon="h(ImportOutlined)"/>Open
|
<a-button type="text" class="action-button" :icon="h(ImportOutlined)"/>Open
|
||||||
</div>
|
</div>
|
||||||
<div class="action-container">
|
<div class="action-container">
|
||||||
<a-button type="text" class="action-button" :icon="h(EditOutlined)"/> Rename
|
<a-button type="text" class="action-button" :icon="h(EditOutlined)"/> Rename
|
||||||
</div>
|
</div>
|
||||||
<div class="action-container">
|
<div class="action-container">
|
||||||
<a-button type="text" class="action-button" :icon="h(LinkOutlined)"/> Share
|
<a-button type="text" class="action-button" :icon="h(LinkOutlined)"/> Share
|
||||||
</div>
|
</div>
|
||||||
<div class="action-container">
|
<div class="action-container">
|
||||||
<a-button type="text" class="action-button" :icon="h(CopyOutlined)"/> Copy
|
<a-button type="text" class="action-button" :icon="h(CopyOutlined)"/> Copy
|
||||||
</div>
|
</div>
|
||||||
<div class="action-container">
|
<div class="action-container">
|
||||||
<a-button type="text" class="action-button" :icon="h(ScissorOutlined)"/> Cut
|
<a-button type="text" class="action-button" :icon="h(ScissorOutlined)"/> Cut
|
||||||
</div>
|
</div>
|
||||||
<div class="action-container">
|
<div class="action-container">
|
||||||
<a-button type="text" class="action-button" :icon="h(DeleteOutlined)"/> Delete
|
<a-button type="text" class="action-button" :icon="h(DeleteOutlined)"/> Delete
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -54,12 +55,12 @@
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, h, computed, reactive, watchEffect } from 'vue'
|
import { ref, h, computed, reactive, watchEffect } from 'vue'
|
||||||
import type { UnwrapRef } from 'vue'
|
import type { UnwrapRef } from 'vue'
|
||||||
|
@ -82,12 +83,13 @@
|
||||||
}>({
|
}>({
|
||||||
selectedRowKeys: [],
|
selectedRowKeys: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const linkBasePath = computed(()=>{
|
const linkBasePath = computed(()=>{
|
||||||
if(Router.currentRoute.value.path === '/') return ''
|
const path = Router.currentRoute.value.path
|
||||||
return Router.currentRoute.value.path
|
return path === '/' ? '' : path
|
||||||
})
|
})
|
||||||
|
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
|
||||||
|
|
||||||
const columns = ref<TableColumnsType>([
|
const columns = ref<TableColumnsType>([
|
||||||
{
|
{
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
|
@ -95,34 +97,26 @@
|
||||||
width: '70%',
|
width: '70%',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: (a: Document, b: Document, sortOrder) => {
|
sorter: (a: Document, b: Document) => a.name.localeCompare(b.name),
|
||||||
return b.name.localeCompare(a.name)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Modified',
|
title: 'Modified',
|
||||||
dataIndex: 'modified',
|
dataIndex: 'modified',
|
||||||
|
className: 'column-date',
|
||||||
responsive: ['lg'],
|
responsive: ['lg'],
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
defaultSortOrder: 'descend',
|
defaultSortOrder: 'descend',
|
||||||
sorter: (a: FolderDocument, b: FolderDocument) => {
|
sorter: (a: FolderDocument, b: FolderDocument) => a.mtime - b.mtime,
|
||||||
const dateA = new Date(a.modified),
|
|
||||||
dateB = new Date(b.modified);
|
|
||||||
if (dateA < dateB) return -1
|
|
||||||
if (dateA > dateB) return 1
|
|
||||||
return 0
|
|
||||||
},
|
|
||||||
key: 'modified',
|
key: 'modified',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// TODO BETTER SORT FOR MULTPLE SIZE OR CUSTOM PIPE TO kB to MB / GB
|
// TODO BETTER SORT FOR MULTPLE SIZE OR CUSTOM PIPE TO kB to MB / GB
|
||||||
title: 'Size',
|
title: 'Size',
|
||||||
dataIndex: 'size',
|
dataIndex: 'size',
|
||||||
|
className: 'column-size',
|
||||||
responsive: ['lg'],
|
responsive: ['lg'],
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
sorter: (a: FolderDocument, b: FolderDocument) => {
|
sorter: (a: FolderDocument, b: FolderDocument) => a.size - b.size,
|
||||||
return a.size - b.size
|
|
||||||
},
|
|
||||||
key: 'size',
|
key: 'size',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -130,12 +124,12 @@
|
||||||
key: 'action',
|
key: 'action',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const onSelectChange = (selectedRowKeys: Key[]) => {
|
const onSelectChange = (selectedRowKeys: Key[]) => {
|
||||||
const newSelectedRowKeys: Document[] = []
|
const newSelectedRowKeys: Document[] = []
|
||||||
selectedRowKeys.forEach( key => {
|
selectedRowKeys.forEach( key => {
|
||||||
if(documentStore.mainDocument){
|
if(documentStore.mainDocument){
|
||||||
const found = documentStore.mainDocument.find( e=> e.key === key )
|
const found = documentStore.mainDocument.find( e=> e.key === key )
|
||||||
if(found) newSelectedRowKeys.push(found)
|
if(found) newSelectedRowKeys.push(found)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -151,8 +145,11 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
|
.column-date, .column-size {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
main {
|
main {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -175,11 +172,19 @@
|
||||||
.carousel-container{
|
.carousel-container{
|
||||||
height: inherit;
|
height: inherit;
|
||||||
}
|
}
|
||||||
|
.file .name::before {
|
||||||
|
content: '📄 ';
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.folder .name::before {
|
||||||
|
content: '📁 ';
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
.editable-cell-text-wrapper .editable-cell-icon {
|
.editable-cell-text-wrapper .editable-cell-icon {
|
||||||
visibility: hidden; /* Oculta el ícono de manera predeterminada */
|
visibility: hidden; /* Oculta el ícono de manera predeterminada */
|
||||||
}
|
}
|
||||||
|
|
||||||
.editable-cell-text-wrapper:hover .editable-cell-icon {
|
.editable-cell-text-wrapper:hover .editable-cell-icon {
|
||||||
visibility: visible; /* Muestra el ícono al hacer hover en el contenedor */
|
visibility: visible; /* Muestra el ícono al hacer hover en el contenedor */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -6,13 +6,14 @@ import Client from '@/repositories/Client'
|
||||||
|
|
||||||
type BaseDocument = {
|
type BaseDocument = {
|
||||||
name: string;
|
name: string;
|
||||||
key?: number;
|
key?: number | string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FolderDocument = BaseDocument & {
|
export type FolderDocument = BaseDocument & {
|
||||||
|
type: 'folder' | 'folder-file';
|
||||||
size: number;
|
size: number;
|
||||||
|
mtime: number;
|
||||||
modified: string;
|
modified: string;
|
||||||
type: 'folder';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FileDocument = BaseDocument & {
|
export type FileDocument = BaseDocument & {
|
||||||
|
@ -84,4 +85,4 @@ export async function fetchFile(path: string): Promise<FileDocument>{
|
||||||
type: 'file',
|
type: 'file',
|
||||||
ext: getFileExtension(name)
|
ext: getFileExtension(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import type { Document } from '@/repositories/Document';
|
import type { Document, FolderDocument } from '@/repositories/Document';
|
||||||
import type { ISimpleError } from '@/repositories/Client';
|
import type { ISimpleError } from '@/repositories/Client';
|
||||||
import { fetchFile } from '@/repositories/Document'
|
import { fetchFile } from '@/repositories/Document'
|
||||||
import { formatUnixDate } from '@/utils';
|
import { formatUnixDate } from '@/utils';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
|
||||||
type FileData = { mtime: number, size: number, dir: DirectoryData};
|
type FileData = { id: string, mtime: number, size: number, dir: DirectoryData};
|
||||||
type DirectoryData = {
|
type DirectoryData = {
|
||||||
[filename: string]: FileData;
|
[filename: string]: FileData;
|
||||||
};
|
};
|
||||||
export type FileStructure = {mtime: number, size: number, dir: DirectoryData};
|
export type FileStructure = {id: string, mtime: number, size: number, dir: DirectoryData};
|
||||||
|
|
||||||
export type DocumentStore = {
|
export type DocumentStore = {
|
||||||
root: FileStructure,
|
root: FileStructure,
|
||||||
|
@ -36,7 +36,7 @@ export const useDocumentStore = defineStore({
|
||||||
selectedDocuments: [] as Document[],
|
selectedDocuments: [] as Document[],
|
||||||
error: '' as string,
|
error: '' as string,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
setActualDocument(location: string){
|
setActualDocument(location: string){
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
@ -54,18 +54,20 @@ export const useDocumentStore = defineStore({
|
||||||
})
|
})
|
||||||
|
|
||||||
// Transform data
|
// Transform data
|
||||||
let count = 0
|
for (const [name, attr] of Object.entries(data.dir)) {
|
||||||
for (const key in data.dir) {
|
const {id, size, mtime, dir} = attr
|
||||||
const element: Document = {
|
const element: Document = {
|
||||||
name: key,
|
name,
|
||||||
key: count,
|
key: id,
|
||||||
size: data.dir[key].size,
|
size,
|
||||||
modified: formatUnixDate(data.dir[key].mtime),
|
mtime,
|
||||||
type: 'folder',
|
modified: formatUnixDate(mtime),
|
||||||
|
type: dir === undefined ? 'folder-file' : 'folder',
|
||||||
}
|
}
|
||||||
count++
|
|
||||||
dataMapped.push(element)
|
dataMapped.push(element)
|
||||||
}
|
}
|
||||||
|
// Pre sort directory entries folders first then files, names in natural ordering
|
||||||
|
dataMapped.sort((a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "folder" ? -1 : 1)
|
||||||
this.document = dataMapped
|
this.document = dataMapped
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
|
@ -79,15 +81,13 @@ export const useDocumentStore = defineStore({
|
||||||
this.selectedDocuments = document
|
this.selectedDocuments = document
|
||||||
},
|
},
|
||||||
deleteDocument(document: Document){
|
deleteDocument(document: Document){
|
||||||
this.document = this.document.filter(e => document.key !== e.key)
|
this.document = this.document.filter(e => document.key !== e.key)
|
||||||
this.selectedDocuments = this.selectedDocuments.filter(e => document.key !== e.key)
|
this.selectedDocuments = this.selectedDocuments.filter(e => document.key !== e.key)
|
||||||
},
|
},
|
||||||
updateUploadingDocuments(key: number, progress: number){
|
updateUploadingDocuments(key: number, progress: number){
|
||||||
this.uploadingDocuments.forEach((document) => {
|
for (const d of this.uploadingDocuments) {
|
||||||
if(document.key === key) {
|
if(d.key === key) d.progress = progress
|
||||||
document.progress = progress
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
pushUploadingDocuments(name: string){
|
pushUploadingDocuments(name: string){
|
||||||
this.uploadCount++;
|
this.uploadCount++;
|
||||||
|
@ -100,7 +100,7 @@ export const useDocumentStore = defineStore({
|
||||||
return document
|
return document
|
||||||
},
|
},
|
||||||
deleteUploadingDocument(key: number){
|
deleteUploadingDocument(key: number){
|
||||||
this.uploadingDocuments = this.uploadingDocuments.filter((e)=> e.key !== key)
|
this.uploadingDocuments = this.uploadingDocuments.filter((e)=> e.key !== key)
|
||||||
},
|
},
|
||||||
getNextDocumentInRoute(direction: number, path: string){
|
getNextDocumentInRoute(direction: number, path: string){
|
||||||
const locations = path.split('/').slice(1)
|
const locations = path.split('/').slice(1)
|
||||||
|
@ -116,7 +116,7 @@ export const useDocumentStore = defineStore({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//Store in a temporary array
|
//Store in a temporary array
|
||||||
for (const key in data.dir) {
|
for (const key in data.dir) {
|
||||||
actualDirArr.push({
|
actualDirArr.push({
|
||||||
name: key,
|
name: key,
|
||||||
|
@ -125,7 +125,7 @@ export const useDocumentStore = defineStore({
|
||||||
}
|
}
|
||||||
const actualFileName = decodeURIComponent(this.mainDocument[0].name).split('/').pop()
|
const actualFileName = decodeURIComponent(this.mainDocument[0].name).split('/').pop()
|
||||||
let index = actualDirArr.findIndex(e => e.name === actualFileName)
|
let index = actualDirArr.findIndex(e => e.name === actualFileName)
|
||||||
|
|
||||||
if(index < 1 && direction === -1 ){
|
if(index < 1 && direction === -1 ){
|
||||||
index = actualDirArr.length -1
|
index = actualDirArr.length -1
|
||||||
}else if(index >= actualDirArr.length - 1 && direction === 1){
|
}else if(index >= actualDirArr.length - 1 && direction === 1){
|
||||||
|
@ -134,9 +134,13 @@ export const useDocumentStore = defineStore({
|
||||||
index = index + direction
|
index = index + direction
|
||||||
}
|
}
|
||||||
return actualDirArr[index].name
|
return actualDirArr[index].name
|
||||||
|
},
|
||||||
|
updateModified() {
|
||||||
|
for (const d of this.document) {
|
||||||
|
if ("mtime" in d) d.modified = formatUnixDate(d.mtime)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
mainDocument(): Document[] {
|
mainDocument(): Document[] {
|
||||||
return this.document;
|
return this.document;
|
||||||
|
|
|
@ -12,7 +12,9 @@ export function formatUnixDate(t: number) {
|
||||||
const diff = date.getTime() - now.getTime()
|
const diff = date.getTime() - now.getTime()
|
||||||
const formatter = new Intl.RelativeTimeFormat('en', { numeric:
|
const formatter = new Intl.RelativeTimeFormat('en', { numeric:
|
||||||
'auto' })
|
'auto' })
|
||||||
|
if (Math.abs(diff) <= 5000) {
|
||||||
|
return 'now'
|
||||||
|
}
|
||||||
if (Math.abs(diff) <= 60000) {
|
if (Math.abs(diff) <= 60000) {
|
||||||
return formatter.format(Math.round(diff / 1000), 'second')
|
return formatter.format(Math.round(diff / 1000), 'second')
|
||||||
}
|
}
|
||||||
|
@ -29,7 +31,7 @@ export function formatUnixDate(t: number) {
|
||||||
return formatter.format(Math.round(diff / 86400000), 'day')
|
return formatter.format(Math.round(diff / 86400000), 'day')
|
||||||
}
|
}
|
||||||
|
|
||||||
return date.toLocaleDateString()
|
return date.toLocaleDateString(undefined, { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFileExtension(filename: string) {
|
export function getFileExtension(filename: string) {
|
||||||
|
@ -54,4 +56,4 @@ export function getFileType(extension: string): string {
|
||||||
} else {
|
} else {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,8 +5,8 @@
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<title>Vite Vasanko</title>
|
<title>Vite Vasanko</title>
|
||||||
<script type="module" crossorigin src="/assets/index-1dc06db1.js"></script>
|
<script type="module" crossorigin src="/assets/index-dfc6f58a.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-09b10238.css">
|
<link rel="stylesheet" href="/assets/index-ee545ab1.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user