Frontend created and rewritten a few times, with some backend fixes #1
1
cista-front/components.d.ts
vendored
1
cista-front/components.d.ts
vendored
|
@ -24,6 +24,7 @@ declare module 'vue' {
|
||||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||||
FileCarousel: typeof import('./src/components/FileCarousel.vue')['default']
|
FileCarousel: typeof import('./src/components/FileCarousel.vue')['default']
|
||||||
FileExplorer: typeof import('./src/components/FileExplorer.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']
|
FileViewer: typeof import('./src/components/FileViewer.vue')['default']
|
||||||
HeaderMain: typeof import('./src/components/HeaderMain.vue')['default']
|
HeaderMain: typeof import('./src/components/HeaderMain.vue')['default']
|
||||||
LoginModal: typeof import('./src/components/LoginModal.vue')['default']
|
LoginModal: typeof import('./src/components/LoginModal.vue')['default']
|
||||||
|
|
|
@ -19,7 +19,11 @@
|
||||||
<tr v-for="doc of sorted(documentStore.mainDocument as FolderDocument[])" :key="doc.key" :class="doc.type === 'folder' ? 'folder' : 'file'">
|
<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="selection"><input type="checkbox" v-model="doc.selected"></td>
|
||||||
<td class="name">
|
<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>
|
||||||
<td class="right">{{doc.modified}}</td>
|
<td class="right">{{doc.modified}}</td>
|
||||||
<td class="right">{{doc.sizedisp}}</td>
|
<td class="right">{{doc.sizedisp}}</td>
|
||||||
|
@ -38,6 +42,8 @@
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import type { Document, FolderDocument } from '@/repositories/Document';
|
import type { Document, FolderDocument } from '@/repositories/Document';
|
||||||
import FileCarousel from './FileCarousel.vue';
|
import FileCarousel from './FileCarousel.vue';
|
||||||
|
import FileRenameInput from './FileRenameInput.vue'
|
||||||
|
import createWebSocket from '@/repositories/WS';
|
||||||
|
|
||||||
const [messageApi, contextHolder] = message.useMessage();
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
|
||||||
|
@ -57,6 +63,30 @@
|
||||||
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
|
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
|
||||||
const url_for = (doc: FolderDocument) => doc.type === "folder" ? `#${linkBasePath.value}/${doc.name}` : `${filesBasePath}/${doc.name}`
|
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 toggleSort = (name: string) => { sort.value = sort.value === name ? "" : name }
|
||||||
const sort = ref<string>("")
|
const sort = ref<string>("")
|
||||||
const sortCompare = {
|
const sortCompare = {
|
||||||
|
@ -107,6 +137,23 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
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 {
|
thead tr {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
background: #ddd;
|
background: #ddd;
|
||||||
|
@ -157,9 +204,6 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.name{
|
|
||||||
max-width: 70%;
|
|
||||||
}
|
|
||||||
.edit-action{
|
.edit-action{
|
||||||
min-width: 5%;
|
min-width: 5%;
|
||||||
}
|
}
|
||||||
|
@ -177,11 +221,4 @@
|
||||||
content: '📁 ';
|
content: '📁 ';
|
||||||
font-size: 1.5em;
|
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>
|
</style>
|
||||||
|
|
47
cista-front/src/components/FileRenameInput.vue
Normal file
47
cista-front/src/components/FileRenameInput.vue
Normal 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>
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<object
|
<object
|
||||||
v-if="props.type === 'pdf'"
|
v-if="props.type === 'pdf'"
|
||||||
:data= "dataURL"
|
:data= "dataURL"
|
||||||
type="application/pdf" width="100%"
|
type="application/pdf" width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
>
|
>
|
||||||
</object>
|
</object>
|
||||||
<a-image
|
<a-image
|
||||||
v-else-if="props.type === 'image'"
|
v-else-if="props.type === 'image'"
|
||||||
|
@ -31,12 +31,12 @@ import { url_document_get } from '@/repositories/Document';
|
||||||
const dataURL = ref('')
|
const dataURL = ref('')
|
||||||
watchEffect(()=>{
|
watchEffect(()=>{
|
||||||
dataURL.value = new URL(
|
dataURL.value = new URL(
|
||||||
url_document_get + Router.currentRoute.value.path,
|
url_document_get + Router.currentRoute.value.path,
|
||||||
location.origin
|
location.origin
|
||||||
).toString();
|
).toString();
|
||||||
})
|
})
|
||||||
const emit = defineEmits({
|
const emit = defineEmits({
|
||||||
visibleImg(value: boolean){
|
visibleImg(value: boolean){
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -52,4 +52,4 @@ const props = defineProps < {
|
||||||
} > ()
|
} > ()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
|
486
cista/wwwroot/assets/index-0332a49a.js
Normal file
486
cista/wwwroot/assets/index-0332a49a.js
Normal file
File diff suppressed because one or more lines are too long
1
cista/wwwroot/assets/index-2503e4fd.css
Normal file
1
cista/wwwroot/assets/index-2503e4fd.css
Normal file
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-06f39339.js"></script>
|
<script type="module" crossorigin src="/assets/index-0332a49a.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-38d160e9.css">
|
<link rel="stylesheet" href="/assets/index-2503e4fd.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
21
node_modules/locale-includes/LICENSE
generated
vendored
Executable file
21
node_modules/locale-includes/LICENSE
generated
vendored
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 idmadj
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
59
node_modules/locale-includes/README.md
generated
vendored
Executable file
59
node_modules/locale-includes/README.md
generated
vendored
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
# localeIncludes()
|
||||||
|
[![npm](https://img.shields.io/npm/v/locale-includes.svg)](https://www.npmjs.com/package/locale-includes)
|
||||||
|
![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/locale-includes.svg)
|
||||||
|
|
||||||
|
[`String.prototype.includes()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes) but using [`localeCompare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare).
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
```sh
|
||||||
|
npm i locale-includes
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
```js
|
||||||
|
localeIncludes(string, searchString[, options])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
+ `string` (string)
|
||||||
|
A string to be searched within.
|
||||||
|
|
||||||
|
+ `searchString` (string)
|
||||||
|
A string to be searched for within `string`.
|
||||||
|
|
||||||
|
+ `options` (object) - *Optional*
|
||||||
|
An object with some or all of the following properties:
|
||||||
|
|
||||||
|
+ `position` (number) - *Default: 0*
|
||||||
|
The position within `string` at which to begin searching for `searchString`.
|
||||||
|
|
||||||
|
+ `locales` (string|array)
|
||||||
|
Passed through as the `locales` parameter to [`String.prototype.localeCompare()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters).
|
||||||
|
|
||||||
|
+ *Any other property*
|
||||||
|
Passed through in the `options` parameter to [`String.prototype.localeCompare()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#Parameters).
|
||||||
|
|
||||||
|
### Return value
|
||||||
|
+ (bool)
|
||||||
|
Whether the search string is found anywhere within the given string or not.
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
```js
|
||||||
|
import {localeIncludes} from `locale-includes`;
|
||||||
|
|
||||||
|
localeIncludes("Abcdef", "cde");
|
||||||
|
// true
|
||||||
|
|
||||||
|
localeIncludes("Abcdef", "cde", {position: 3});
|
||||||
|
// false
|
||||||
|
|
||||||
|
localeIncludes("àḃḉdÉf", "bCde", {usage: "search", sensitivity: "base"});
|
||||||
|
// true
|
||||||
|
```
|
||||||
|
|
||||||
|
## See also
|
||||||
|
[`String.prototype.includes()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)
|
||||||
|
[`String.prototype.localeCompare()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare)
|
1
node_modules/locale-includes/lib/index.js
generated
vendored
Executable file
1
node_modules/locale-includes/lib/index.js
generated
vendored
Executable file
|
@ -0,0 +1 @@
|
||||||
|
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.localeIncludes=void 0;var _excluded=["position","locales"];function _objectWithoutProperties(source,excluded){if(source==null)return{};var target=_objectWithoutPropertiesLoose(source,excluded);var key,i;if(Object.getOwnPropertySymbols){var sourceSymbolKeys=Object.getOwnPropertySymbols(source);for(i=0;i<sourceSymbolKeys.length;i++){key=sourceSymbolKeys[i];if(excluded.indexOf(key)>=0)continue;if(!Object.prototype.propertyIsEnumerable.call(source,key))continue;target[key]=source[key]}}return target}function _objectWithoutPropertiesLoose(source,excluded){if(source==null)return{};var target={};var sourceKeys=Object.keys(source);var key,i;for(i=0;i<sourceKeys.length;i++){key=sourceKeys[i];if(excluded.indexOf(key)>=0)continue;target[key]=source[key]}return target}var localeIncludes=function localeIncludes(string,searchString){var _ref=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{},_ref$position=_ref.position,position=_ref$position===void 0?0:_ref$position,locales=_ref.locales,options=_objectWithoutProperties(_ref,_excluded);if(string===undefined||string===null||searchString===undefined||searchString===null){throw new Error("localeIncludes requires at least 2 parameters")}var stringLength=string.length;var searchStringLength=searchString.length;var lengthDiff=stringLength-searchStringLength;for(var i=position;i<=lengthDiff;i++){if(string.substring(i,i+searchStringLength).localeCompare(searchString,locales,options)===0){return true}}return false};exports.localeIncludes=localeIncludes;
|
46
node_modules/locale-includes/package.json
generated
vendored
Executable file
46
node_modules/locale-includes/package.json
generated
vendored
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"name": "locale-includes",
|
||||||
|
"version": "1.0.5",
|
||||||
|
"description": "String.prototype.includes() but using localeCompare.",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"directories": {
|
||||||
|
"lib": "lib"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "babel src -d lib",
|
||||||
|
"build:watch": "babel src -d lib -w",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/idmadj/locale-includes.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/idmadj/locale-includes/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/idmadj/locale-includes#readme",
|
||||||
|
"keywords": [
|
||||||
|
"localeincludes",
|
||||||
|
"locale",
|
||||||
|
"includes",
|
||||||
|
"contains",
|
||||||
|
"string",
|
||||||
|
"localecompare",
|
||||||
|
"search",
|
||||||
|
"filter",
|
||||||
|
"match",
|
||||||
|
"diacritics",
|
||||||
|
"accents",
|
||||||
|
"case",
|
||||||
|
"insensitive",
|
||||||
|
"i18n",
|
||||||
|
"esm",
|
||||||
|
"module"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.20.7",
|
||||||
|
"@babel/core": "^7.20.12",
|
||||||
|
"@babel/preset-env": "^7.20.2"
|
||||||
|
}
|
||||||
|
}
|
5
package.json
Normal file
5
package.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"locale-includes": "^1.0.5"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user