Compare commits

...

6 Commits

Author SHA1 Message Date
f52d58d645 Big changes...
- Added Droppy SVG icons
- Implemented Droppy-style Breadcrumb component
- Implemented a Dialog component
- Attempted transition effects on file explorer (not yet functional)
- Changed FileExplorer to take list of documents and current path via props.
- Various other cleanup etc.
2023-11-03 16:19:21 +00:00
6cba674b30 Build down to 90 kB, 1.5 MB less after removing ant-design. 2023-11-02 22:34:57 +00:00
831b2716f7 Removing stuff, refactoring for simplicity 2023-11-02 21:52:21 +00:00
7e5901a2cf Fix indent 2023-11-02 18:51:34 +00:00
a4f95d730b Fix file links 2023-11-02 17:58:36 +00:00
56082cba15 Faster animation to match the fast update 2023-11-02 17:56:55 +00:00
85 changed files with 872 additions and 1459 deletions

View File

@ -7,22 +7,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
AButton: typeof import('ant-design-vue/es')['Button']
ACol: typeof import('ant-design-vue/es')['Col']
AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem']
AImage: typeof import('ant-design-vue/es')['Image']
AInput: typeof import('ant-design-vue/es')['Input']
AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
AModal: typeof import('ant-design-vue/es')['Modal']
APageHeader: typeof import('ant-design-vue/es')['PageHeader']
AppNavigation: typeof import('./src/components/AppNavigation.vue')['default']
AProgress: typeof import('ant-design-vue/es')['Progress']
ARow: typeof import('ant-design-vue/es')['Row']
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']

View File

@ -1,13 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Vite Vasanko</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
<html lang=en>
<meta charset=UTF-8>
<title>Cista</title>
<link rel="icon" href="/favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script type="module" src="/src/main.ts"></script>
<div id="app"></div>

View File

@ -8,10 +8,7 @@
"name": "front",
"version": "0.0.0",
"dependencies": {
"@ant-design/icons-vue": "^7.0.0",
"@vueuse/core": "^10.4.1",
"ant-design-vue": "^4.0.3",
"axios": "^1.5.0",
"esbuild": "^0.19.5",
"locale-includes": "^1.0.5",
"lodash": "^4.17.21",
@ -19,6 +16,7 @@
"pinia": "^2.1.6",
"unplugin-vue-components": "^0.25.2",
"vite-plugin-rewrite-all": "^1.0.1",
"vite-svg-loader": "^4.0.0",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
@ -53,31 +51,6 @@
"node": ">=0.10.0"
}
},
"node_modules/@ant-design/colors": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz",
"integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==",
"dependencies": {
"@ctrl/tinycolor": "^3.4.0"
}
},
"node_modules/@ant-design/icons-svg": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz",
"integrity": "sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g=="
},
"node_modules/@ant-design/icons-vue": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-7.0.0.tgz",
"integrity": "sha512-VEb0r/Jqo2qi9olfBephYlyxbmhQVZ5+tJ3Zw5VaBd5h0wV1zdjGt5mJxSbRRs2mnnOWpsa1s4PeoLwNnkLV/w==",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-svg": "^4.2.1"
},
"peerDependencies": {
"vue": ">=3.0.3"
}
},
"node_modules/@antfu/utils": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.6.tgz",
@ -275,35 +248,6 @@
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
"integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
"engines": {
"node": ">=10"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
"integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"node_modules/@esbuild/android-arm": {
"version": "0.19.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz",
@ -825,15 +769,6 @@
"integrity": "sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==",
"dev": true
},
"node_modules/@simonwep/pickr": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.8.2.tgz",
"integrity": "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==",
"dependencies": {
"core-js": "^3.15.1",
"nanopop": "^2.1.0"
}
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -849,6 +784,14 @@
"node": ">= 10"
}
},
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/@tsconfig/node18": {
"version": "18.2.2",
"resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.2.tgz",
@ -1664,45 +1607,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/ant-design-vue": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.0.3.tgz",
"integrity": "sha512-fbgZbbirLx7rc19ytaGxApwS01CKLRzvEZmH0TVF06niQA9ekx7xkvfQGlmiSaCs4b8nWZi4Bo7gUzRNRt5YJA==",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^7.0.0",
"@babel/runtime": "^7.10.5",
"@ctrl/tinycolor": "^3.5.0",
"@emotion/hash": "^0.9.0",
"@emotion/unitless": "^0.8.0",
"@simonwep/pickr": "~1.8.0",
"array-tree-filter": "^2.1.0",
"async-validator": "^4.0.0",
"csstype": "^3.1.1",
"dayjs": "^1.10.5",
"dom-align": "^1.12.1",
"dom-scroll-into-view": "^2.0.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.15",
"resize-observer-polyfill": "^1.5.1",
"scroll-into-view-if-needed": "^2.2.25",
"shallow-equal": "^1.0.0",
"stylis": "^4.1.3",
"throttle-debounce": "^5.0.0",
"vue-types": "^3.0.0",
"warning": "^4.0.0"
},
"engines": {
"node": ">=12.22.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ant-design-vue"
},
"peerDependencies": {
"vue": ">=3.2.0"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@ -1721,11 +1625,6 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/array-tree-filter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
},
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@ -1744,25 +1643,11 @@
"node": "*"
}
},
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
"node_modules/balanced-match": {
"version": "1.0.2",
@ -1789,8 +1674,7 @@
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"dev": true
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"node_modules/bplist-parser": {
"version": "0.2.0",
@ -1960,6 +1844,7 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@ -1976,11 +1861,6 @@
"node": ">=14"
}
},
"node_modules/compute-scroll-into-view": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
"integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -2005,16 +1885,6 @@
"node": ">=0.8"
}
},
"node_modules/core-js": {
"version": "3.32.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.32.2.tgz",
"integrity": "sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -2029,6 +1899,44 @@
"node": ">= 8"
}
},
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-tree": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -2041,6 +1949,36 @@
"node": ">=4"
}
},
"node_modules/csso": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
"dependencies": {
"css-tree": "~2.2.0"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/css-tree": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
"dependencies": {
"mdn-data": "2.0.28",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/mdn-data": {
"version": "2.0.28",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="
},
"node_modules/cssstyle": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz",
@ -2072,11 +2010,6 @@
"node": ">=14"
}
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
},
"node_modules/de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@ -2173,6 +2106,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
@ -2210,15 +2144,29 @@
"node": ">=6.0.0"
}
},
"node_modules/dom-align": {
"version": "1.12.4",
"resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz",
"integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw=="
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/dom-scroll-into-view": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
"integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domexception": {
"version": "4.0.0",
@ -2232,6 +2180,33 @@
"node": ">=12"
}
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/editorconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
@ -2278,7 +2253,6 @@
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"engines": {
"node": ">=0.12"
},
@ -2691,29 +2665,11 @@
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@ -3115,14 +3071,6 @@
"node": ">=8"
}
},
"node_modules/is-plain-object": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
"integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@ -3197,7 +3145,8 @@
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/js-yaml": {
"version": "4.1.0",
@ -3364,17 +3313,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/loupe": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
@ -3404,6 +3342,11 @@
"node": ">=12"
}
},
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
},
"node_modules/memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@ -3443,6 +3386,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@ -3451,6 +3395,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@ -3522,11 +3467,6 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/nanopop": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/nanopop/-/nanopop-2.3.0.tgz",
"integrity": "sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw=="
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -3662,7 +3602,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
"dependencies": {
"boolbase": "^1.0.0"
},
@ -4073,11 +4012,6 @@
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@ -4165,22 +4099,12 @@
"node": ">=8.10.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"dev": true
},
"node_modules/resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"node_modules/resolve": {
"version": "1.22.6",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz",
@ -4415,14 +4339,6 @@
"node": ">=v12.22.7"
}
},
"node_modules/scroll-into-view-if-needed": {
"version": "2.2.31",
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
"integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
"dependencies": {
"compute-scroll-into-view": "^1.0.20"
}
},
"node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
@ -4450,11 +4366,6 @@
"node": ">=10"
}
},
"node_modules/shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -4606,11 +4517,6 @@
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/stylis": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
"integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -4634,6 +4540,37 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svgo": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz",
"integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==",
"dependencies": {
"@trysound/sax": "0.2.0",
"commander": "^7.2.0",
"css-select": "^5.1.0",
"css-tree": "^2.2.1",
"csso": "^5.0.5",
"picocolors": "^1.0.0"
},
"bin": {
"svgo": "bin/svgo"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/svgo"
}
},
"node_modules/svgo/node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"engines": {
"node": ">= 10"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
@ -4662,14 +4599,6 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"node_modules/throttle-debounce": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
"integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==",
"engines": {
"node": ">=12.22"
}
},
"node_modules/tinybench": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz",
@ -5027,6 +4956,15 @@
"vite": "^2.0.0 || ^3.0.0 || ^4.0.0"
}
},
"node_modules/vite-svg-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-4.0.0.tgz",
"integrity": "sha512-0MMf1yzzSYlV4MGePsLVAOqXsbF5IVxbn4EEzqRnWxTQl8BJg/cfwIzfQNmNQxZp5XXwd4kyRKF1LytuHZTnqA==",
"dependencies": {
"@vue/compiler-sfc": "^3.2.20",
"svgo": "^3.0.2"
}
},
"node_modules/vite/node_modules/@esbuild/android-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@ -5553,20 +5491,6 @@
"typescript": "*"
}
},
"node_modules/vue-types": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/vue-types/-/vue-types-3.0.2.tgz",
"integrity": "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==",
"dependencies": {
"is-plain-object": "3.0.1"
},
"engines": {
"node": ">=10.15.0"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@ -5579,14 +5503,6 @@
"node": ">=14"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",

View File

@ -13,10 +13,7 @@
"format": "prettier --write src/"
},
"dependencies": {
"@ant-design/icons-vue": "^7.0.0",
"@vueuse/core": "^10.4.1",
"ant-design-vue": "^4.0.3",
"axios": "^1.5.0",
"esbuild": "^0.19.5",
"locale-includes": "^1.0.5",
"lodash": "^4.17.21",
@ -24,6 +21,7 @@
"pinia": "^2.1.6",
"unplugin-vue-components": "^0.25.2",
"vite-plugin-rewrite-all": "^1.0.1",
"vite-svg-loader": "^4.0.0",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},

View File

@ -7,9 +7,9 @@
import { useDocumentStore } from '@/stores/documents'
import { computed } from 'vue'
import HeaderMain from './components/HeaderMain.vue'
import AppNavigation from './components/AppNavigation.vue'
import Router from './router/index';
import HeaderMain from '@/components/HeaderMain.vue'
import AppNavigation from '@/components/AppNavigation.vue'
import Router from '@/router/index';
interface Path {
path: string;
@ -43,8 +43,8 @@
<template>
<header class="wrapper">
<HeaderMain WS="WS"></HeaderMain>
<AppNavigation :path="path.pathList"></AppNavigation>
<HeaderMain WS="WS"></HeaderMain>
<AppNavigation :path="path.pathList"></AppNavigation>
</header>
<RouterView class="page-container" />
@ -52,8 +52,7 @@
<style scoped>
.wrapper{
background-color: var(--primary-background);
padding: 0.2em 0.5em;
background-color: var(--header-background);
display: flex;
flex-direction: column;
gap: 10px;

View File

@ -1,7 +1,10 @@
@charset "UTF-8";
:root {
--primary-background: #181818;
--secondary-background: #ffffff;
--font-color: #333333;
--font-color: #333;
--header-background: #000;
--table-background: #535353;
--primary-color: #ffffff;
--secondary-color: #ccc;
@ -10,9 +13,9 @@
}
@media (prefers-color-scheme: dark) {
:root {
--primary-background: #181818;
--secondary-background: #333333;
--font-color: #ffffff;
--primary-background: #333;
--secondary-background: #666;
--font-color: #ddd;
--table-background: #535353;
--primary-color: #ffffff;
--secondary-color: #ccc;
@ -21,85 +24,22 @@
}
}
body {
background-color: var(--table-background);
background-color: var(--primary-background);
font-family: 'Roboto', sans-serif;
color: var(--font-color);
margin: 0;
}
.ant-breadcrumb-separator, .ant-breadcrumb-link, .ant-breadcrumb .anticon {
color: var(--primary-color) !important;
font-size: 1.2em !important;
a:link, a:visited, a:active, a:hover {
color: var(--primary-color);
text-decoration: none;
}
table {
border-collapse: collapse;
border: 0;
gap: 0;
}
#app{
height: 100%;
display: flex;
flex-direction: column;
background-color: var(--secondary-background);
}
.ant-image-preview-mask{
background-color: rgba(0, 0, 0, 0.6) !important;
backdrop-filter: blur(15px) !important;
}
.ant-table-cell:hover{
background-color: initial !important;
}
.ant-table-wrapper .ant-table-tbody >tr.ant-table-row-selected >td,
.ant-table-wrapper .ant-table-tbody >tr.ant-table-row-selected:hover>td {
background-color: transparent;
}
.ant-form-item .ant-form-item-label >label{
color: var(--font-color);
}
@media (prefers-color-scheme: dark) {
.ant-input-group >.ant-input-group-addon:last-child .ant-input-search-button:not(.ant-btn-primary):hover{
color : var(--blue-color) !important
}
.ant-input-search .ant-input:hover,
.ant-input-search .ant-input:focus {
border-color: var(--blue-color);
}
.ant-input{
background-color:var(--table-background);
border-color: var(--table-background);
color: var(--font-color)
}
.ant-table-wrapper .ant-table-thead>tr>th {
background-color: var(--table-background);
}
.ant-table-wrapper .ant-table-thead th.ant-table-column-has-sorters:hover {
background-color: var(--table-background);
}
.ant-table-content {
background-color: var(--secondary-background);
}
.ant-table-cell-row-hover,
.ant-table-wrapper .ant-table-tbody>tr.ant-table-row:hover>td {
background-color: var(--primary-background) !important;
}
.ant-table-column-title,
.ant-table-column-sorter,
.ant-table-column-sort,
.ant-table-cell,
a {
color: var(--primary-color) !important;
}
.ant-table-cell>button>.anticon {
color: var(--primary-color);
}
.ant-notification-close-x{
color: var(--secondary-background);
}
.ant-empty-description{
color: var(--primary-color);
}
.ant-modal .ant-modal-content{
background-color: var(--secondary-background);
}
.ant-modal .ant-modal-close-x{
color: var(--font-color);
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zM18.5 16v7.1h-5.3V16H8.7l7.1-7.1L23 16h-4.5z"/></svg>

After

Width:  |  Height:  |  Size: 180 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm18.3 9.5V27h-5.6v-7.5H8l7.5-7.5 7.5 7.5h-4.7z"/></svg>

After

Width:  |  Height:  |  Size: 191 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="640" viewBox="0 -32 640 640"><path d="M495.46 365.98c-13.03-13.37-150.24-144.06-150.24-144.06A35.16 35.16 0 0 0 320 211.2a35.06 35.06 0 0 0-25.22 10.72s-137.2 130.7-150.27 144.06c-13 13.38-13.9 37.44 0 51.72 14 14.24 33.4 15.4 50.48 0L320 297.8l125.02 119.9c17.1 15.4 36.55 14.24 50.44 0 13.95-14.3 13.08-38.37 0-51.72z"/></svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6 -2 44 36"><path d="M12 18H6v4l-6-6 6-6v4h6zm8-4h6v-4l6 6-6 6v-4h-6z"/></svg>

After

Width:  |  Height:  |  Size: 151 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2 -6 16 44"><path d="M8 20v6h4l-6 6-6-6h4v-6zm-4-8V6H0l6-6 6 6H8v6z"/></svg>

After

Width:  |  Height:  |  Size: 149 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-48 0 512 512"><path d="M320 96L128 288l-64-64-64 64 128 128 256-256-64-64z"/></svg>

After

Width:  |  Height:  |  Size: 158 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-24 8 512 512"><path d="M304 96l-48 48 112 112-112 112 48 48 144-160L304 96zm-160 0L0 256l144 160 48-48L80 256l112-112-48-48z"/></svg>

After

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="448" height="512" viewBox="0 0 448 512"><path d="M223.97 175A81 81 0 0 0 143 256c0 44.7 36.27 81.03 80.97 81.03 44.72 0 80.72-36.34 80.72-81.03 0-44.73-36-81-80.8-81zM386.3 302.53l-14.58 35.16 29.47 57.8-36.1 36.1-59.3-28-35.2 14.4-17.87 54.6-2.28 7.24h-51L177.4 418.2l-35.17-14.5-57.9 29.4-36.1-36.1 27.97-59.2-14.47-35.12L0 282.6v-51l61.7-22.1 14.5-35.1-25.96-51.23-3.43-6.72 36.1-36.03 59.3 27.92 35.1-14.5 17.9-54.6 2.3-7.24h51l22.1 61.73 35.07 14.52 58.04-29.4 36.06 36.03-27.96 59.2 14.42 35.17 61.8 20.13v50.97l-61.67 22.18z"/></svg>

After

Width:  |  Height:  |  Size: 587 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2 -2 36 36"><path d="M26 8h-6V6l-6-6H0v24h12v8h20V14l-6-6zm0 2.83L29.17 14H26v-3.17zm-12-8L17.17 6H14V2.83zM2 2h10v6h6v14H2V2zm28 28H14v-6h6V10h4v6h6v14z"/></svg>

After

Width:  |  Height:  |  Size: 235 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zm3 15c0 .2-.2.4-.4.4h-4.4v4.4c0 .2-.2.4-.4.4h-2.4c-.2 0-.4-.2-.4-.4V18H9.9c-.2 0-.4-.2-.4-.4v-2.4c0-.2.2-.4.4-.4h4.4v-4.4c0-.2.2-.4.4-.4H17c.2 0 .4.2.4.4v4.4h4.4c.2 0 .4.2.4.4v2.4z"/></svg>

After

Width:  |  Height:  |  Size: 316 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm22.8 11.2c0 .3-.2.5-.5.5h-5.2v5.2c0 .3-.2.5-.5.5h-2.8c-.3 0-.5-.2-.5-.5v-5.2H8.1c-.3 0-.5-.2-.5-.5v-2.8c0-.3.2-.5.5-.5h5.2v-5.2c0-.3.2-.5.5-.5h2.8c.3 0 .5.2.5.5v5.2h5.2c.3 0 .5.2.5.5v2.8z"/></svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M25.3 8.56L17.88 16l7.44 7.44-1.86 1.87L16 17.9l-7.44 7.4-1.86-1.85L14.12 16 6.68 8.56 8.55 6.7 16 14.12l7.44-7.44z"/></svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M24.27 3.2H6.4a3.2 3.2 0 0 0-3.2 3.2v19.2a3.2 3.2 0 0 0 3.2 3.2h19.2a3.2 3.2 0 0 0 3.2-3.2V8.2l-4.53-5zm-1.87 9.6c0 .88-.72 1.6-1.6 1.6h-9.6a1.6 1.6 0 0 1-1.6-1.6v-8h12.8v8zm-1.6-6.4h-3.2v6.4h3.2V6.4z"/></svg>

After

Width:  |  Height:  |  Size: 301 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-3 0 34 34"><path d="M23 25.9c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm4.6 0c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm2.3-4v5.7c0 .5-.2.9-.5 1.2-.3.3-.7.5-1.2.5H1.9c-.5 0-.9-.2-1.2-.5s-.5-.7-.5-1.2v-5.7c0-.5.2-.9.5-1.2.3-.3.7-.5 1.2-.5h8.3l2.4 2.4c.7.7 1.5 1 2.4 1 .9 0 1.7-.3 2.4-1l2.4-2.4h8.3c.5 0 .9.2 1.2.5.4.3.6.7.6 1.2zm-5.8-10.2c.2.5.1.9-.3 1.3l-8 8c-.2.2-.5.3-.8.3-.3 0-.6-.1-.8-.3l-8-8c-.4-.3-.5-.8-.3-1.3S6.5 11 7 11h4.6V3c0-.3.1-.6.3-.8s.5-.3.8-.3h4.6c.3 0 .6.1.8.3s.3.5.3.8v8H23c.5 0 .8.2 1.1.7z"/></svg>

After

Width:  |  Height:  |  Size: 734 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="448" height="448" viewBox="-136 0 448 448"><path d="M128 312v56q0 6.5-4.75 11.25T112 384H48q-6.5 0-11.25-4.75T32 368v-56q0-6.5 4.75-11.25T48 296h64q6.5 0 11.25 4.75T128 312zm7.5-264l-7 192q-.25 6.5-5.13 11.25T112 256H48q-6.5 0-11.38-4.75T31.5 240l-7-192q-.25-6.5 4.38-11.25T40 32h80q6.5 0 11.13 4.75T135.5 48z"/></svg>

After

Width:  |  Height:  |  Size: 365 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2 -2 36 36"><path d="M29.715 16c-1.696-2.625-4.018-4.875-6.804-6.304 0.714 1.214 1.089 2.607 1.089 4.018 0 4.411-3.589 8-8 8s-8-3.589-8-8c0-1.411 0.375-2.804 1.089-4.018-2.786 1.429-5.107 3.679-6.804 6.304 3.054 4.714 7.982 8 13.714 8s10.661-3.286 13.714-8zM16.858 9.143c0-0.464-0.393-0.857-0.857-0.857-2.982 0-5.429 2.446-5.429 5.429 0 0.464 0.393 0.857 0.857 0.857s0.857-0.393 0.857-0.857c0-2.036 1.679-3.714 3.714-3.714 0.464 0 0.857-0.393 0.857-0.857zM32 16c0 0.446-0.143 0.857-0.357 1.232-3.286 5.411-9.304 9.054-15.643 9.054s-12.357-3.661-15.643-9.054c-0.214-0.375-0.357-0.786-0.357-1.232s0.143-0.857 0.357-1.232c3.286-5.393 9.304-9.054 15.643-9.054s12.357 3.661 15.643 9.054c0.214 0.375 0.357 0.786 0.357 1.232z"></path></svg>

After

Width:  |  Height:  |  Size: 806 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-12 -12 512 512"><path d="M480 416L355.44 291.44C373.22 262.4 384 228.58 384 192 384 85.98 298 0 192 0 85.98 0 0 85.98 0 192c0 106 85.98 192 192 192 36.58 0 70.4-10.78 99.44-28.5L416 480c8.75 8.75 23.25 8.7 32 0l32-32a22.8 22.8 0 0 0 0-32zm-288-96c-70.7 0-128-57.3-128-128S121.3 64 192 64s128 57.3 128 128-57.3 128-128 128z"/></svg>

After

Width:  |  Height:  |  Size: 406 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M18.7 6.7h6.6v6.6h-2.6v-4h-4V6.7zm4 16v-4h2.6v6.6h-6.6v-2.6h4zm-16-9.4V6.7h6.6v2.6h-4v4H6.7zm2.6 5.4v4h4v2.6H6.7v-6.6h2.6z"/></svg>

After

Width:  |  Height:  |  Size: 223 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path d="M256 6.3C114.6 6.3 0 121 0 262.3c0 113 73.4 209 175 243 13 2.3 17.6-5.6 17.6-12.4l-.4-48C121 460.5 106 415 106 415c-11.7-29.5-28.5-37.4-28.5-37.4-23.2-16 1.8-15.6 1.8-15.6 25.7 1.8 39.2 26.4 39.2 26.4 23 39.2 60 27.8 74.5 21.3 2.3-16.5 9-27.8 16.3-34.2C152.3 369 92.6 347 92.6 249c0-28 10-50.8 26.4-68.8-2.6-6.4-11.4-32.5 2.5-67.7 0 0 21.5-7 70.4 26.2 20-5.6 42-8.5 64-8.6 21.3.7 43.2 3 64 9 49-33 70-26 70-26 14 35.3 5 61.4 2.4 67.8 16.3 18 26.2 40.8 26.2 68.7 0 98.4-60 120-117 126.4 9.2 8 17.4 23.4 17.4 47.3l-.2 70.2c0 6.6 4.7 14.6 17.7 12 101.7-34 175-129.7 175-243C512 121 397.5 6 256 6z"/></svg>

After

Width:  |  Height:  |  Size: 698 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M32 18.45L16 6.03 0 18.45V13.4L16 .96 32 13.4zM28 18v12h-8v-8h-8v8H4V18l12-9z"/></svg>

After

Width:  |  Height:  |  Size: 178 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2 -2 34 34"><path d="M16 .6C7.5.6.6 7.6.6 16c0 8.5 7 15.4 15.4 15.4 8.5 0 15.4-7 15.4-15.4C31.4 7.5 24.4.6 16 .6zm1.4 5.6c1.5 0 2 1 2 1.8 0 1.3-1 2.4-2.7 2.4-1.4 0-2-.7-2-2 0-.8.8-2.2 2.7-2.2zm-3.8 19c-1 0-1.8-.6-1-3.4l1-4.8c.3-.8.4-1 0-1-.2 0-1.5.5-2.3 1l-.5-1c2.5-2 5.3-3 6.6-3 1 0 1.2 1 .6 3l-1.3 5c-.2 1 0 1.2 0 1.2.4 0 1.4-.3 2.4-1l1 .7c-2.4 2-5 3-6 3z"/></svg>

After

Width:  |  Height:  |  Size: 439 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path d="M384 128h-69c24 16 46.5 44.5 53.5 64h15c32.5 0 64 32 64 64s-32.5 64-64 64h-96c-31.5 0-64-32-64-64 0-11.5 3.5-22.5 9-32H164c-2.5 10.5-4 21-4 32 0 64 63.5 128 127.5 128H384c64 0 128-64 128-128s-64-128-128-128zM143.5 320h-15c-32.5 0-64-32-64-64s32.5-64 64-64h96c31.5 0 64 32 64 64 0 11.5-3.5 22.5-9 32H348c2.5-10.5 4-21 4-32 0-64-63.5-128-127.5-128H128C64 128 0 192 0 256s64 128 128 128h69c-24-16-46.5-44.5-53.5-64z"/></svg>

After

Width:  |  Height:  |  Size: 517 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><rect width="512" height="512" fill="#26b" rx="64" ry="64"/><path fill="#fff" d="M381 298h-84V167h-66L339 35l108 132h-66zm-168-84h-84v131H63l108 132 108-132h-66z"/></svg>

After

Width:  |  Height:  |  Size: 257 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2 -2 36 36"><path d="M23.53 8.44l3.13-3.13v9.4h-9.38l4.3-4.3C20.18 8.94 18.18 8 16 8c-4.45 0-8 3.56-8 8s3.55 8 8 8c3.5 0 6.5-2.2 7.55-5.3h2.75c-1.2 4.6-5.3 8-10.3 8-5.9 0-10.64-4.83-10.64-10.7S10.1 5.3 15.96 5.3c2.95 0 5.63 1.2 7.57 3.14z"/></svg>

After

Width:  |  Height:  |  Size: 320 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="4 0 24 32"><path d="M16 21.3c1.4 0 2.7 1.3 2.7 2.7s-1.3 2.7-2.7 2.7-2.7-1.3-2.7-2.7 1.3-2.7 2.7-2.7zm0-8c1.4 0 2.7 1.3 2.7 2.7s-1.3 2.7-2.7 2.7-2.7-1.3-2.7-2.7 1.3-2.7 2.7-2.7zm0-2.6c-1.4 0-2.7-1.3-2.7-2.7s1.3-2.7 2.7-2.7 2.7 1.3 2.7 2.7-1.3 2.7-2.7 2.7z"/></svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="2 0 32 32"><path d="M24 4v24h-4V17L10 27V5l10 10V4z"/></svg>

After

Width:  |  Height:  |  Size: 132 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="640" height="640" viewBox="0 0 640 640"><path d="M576 32H64C28.8 32 0 60.8 0 96v384c0 35.2 28.8 63.36 64 63.36h127.36v-62.72h-128V185.6h513.28v295.04h-128v62.75H576c35.23 0 64-28.2 64-63.4V96c0-35.2-28.77-64-64-64zM83.23 138.56c-13.28 0-24-10.46-24-23.36s10.72-23.36 24-23.36c13.25 0 24 10.46 24 23.36s-10.75 23.36-24 23.36zm64 0c-13.28 0-24-10.46-24-23.36s10.72-23.36 24-23.36c13.25 0 24 10.46 24 23.36s-10.75 23.36-24 23.36zm429.44-3.52h-385.3V95.36h385.27v39.68zM318.34 261.57l-155.27 154.3h96V608H377.6V415.87h96l-155.26-154.3z"/></svg>

After

Width:  |  Height:  |  Size: 587 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M26 10V5a1 1 0 0 0-1-1h-7V2a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2H3a1 1 0 0 0-1 1v20a1 1 0 0 0 1 1h9v6h14l6-6V10h-6zM12 2h4v2h-4V2zM6 8V6h16v2H6zm20 21.17V26h3.17L26 29.17zM30 24h-6v6H14V12h16v12z"/></svg>

After

Width:  |  Height:  |  Size: 292 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M4 4h10v24H4zm14 0h10v24H18z"/></svg>

After

Width:  |  Height:  |  Size: 129 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.5 0 32 32"><path d="M6.5 27.4l1.6-1.6-4.2-4.2-1.6 1.6v1.9h2.3v2.3h1.9zm9.3-16.5c0-.3-.1-.4-.4-.4-.1 0-.2 0-.3.1l-9.7 9.7c-.1.1-.1.2-.1.3 0 .3.1.4.4.4.1 0 .2 0 .3-.1l9.7-9.7c.1-.1.1-.2.1-.3zm-.9-3.5l7.4 7.4L7.4 29.7H0v-7.4L14.9 7.4zm12.2 1.7a2 2 0 0 1-.7 1.6l-3 3L16 6.3l3-2.9a2 2 0 0 1 1.6-.7 2 2 0 0 1 1.6.7l4.2 4.2c.4.4.7.9.7 1.5z"/></svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M6 4l20 12L6 28z"/></svg>

After

Width:  |  Height:  |  Size: 117 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M31 12H20V1a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v11H1a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h11v11a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V20h11a1 1 0 0 0 1-1v-6a1 1 0 0 0-1-1z"/></svg>

After

Width:  |  Height:  |  Size: 252 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M8 28V4h4v11L22 5v22L12 17v11z"/></svg>

After

Width:  |  Height:  |  Size: 131 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M24.48 14.8c.37 2.55-.4 5.24-2.4 7.2-2.94 2.9-7.48 3.26-10.82 1.08l2.34-2.28L5 19.6 6.2 28l2.62-2.52c4.72 3.48 11.4 3.15 15.7-1.08 2.48-2.45 3.6-5.7 3.47-8.9l-3.53-.7zM9.92 10c2.94-2.9 7.48-3.26 10.82-1.08L18.4 11.2l8.6 1.2L25.8 4l-2.63 2.52C18.47 3.04 11.77 3.37 7.5 7.6 5 10.05 3.86 13.3 4 16.5l3.52.7c-.37-2.55.4-5.24 2.4-7.2z"/></svg>

After

Width:  |  Height:  |  Size: 430 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M26.67 4V1.33h-8V4h2.66v24h-2.66v2.67h8V28H24V4zm-8 3.12c0-.14-.26-.3-.43-.42a5.8 5.8 0 0 0-2.45-1.07c-.9-.17-2-.25-3.2-.25-.9 0-1.8.14-2.7.42-.9.28-1.7.62-2.4 1.03a5.7 5.7 0 0 0-1.8 1.62c-.5.6-.7 1.24-.7 1.9 0 .64.1 1.2.5 1.72s.8.77 1.6.77 1.4-.2 1.9-.63c.4-.4.7-.8.7-1.3s-.1-1-.2-1.5c-.2-.5-.2-1-.2-1.3.2-.2.6-.5 1.2-.7.5-.2 1.2-.3 1.8-.3.9 0 1.7.2 2.2.6.5.4.9.9 1.2 1.4.2.5.2 1.6.2 1.6v3.2c0 .36-1.8.9-3.8 1.54s-3.2 1-3.8 1.27c-.5.2-1 .48-1.6.8a5.54 5.54 0 0 0-2.4 2.9c-.2.65-.3 1.36-.3 2.2 0 1.58.5 2.87 1.5 3.85S7.82 27.9 9.4 27.9c1.5 0 2.8-.6 3.8-1.13 1.1-.5 2.1-1.3 3-2.7h.1c.2 1.4.6 2.1 1.26 2.7l.87.07V7.1zm-2.32 15.85a7.96 7.96 0 0 1-1.97 1.76 4.9 4.9 0 0 1-2.7.75c-.97 0-1.76-.28-2.4-.85-.62-.56-.93-1.44-.93-2.64 0-1 .2-1.8.63-2.4.4-.7 1-1.3 1.7-1.8.8-.5 1.65-1 2.58-1.3.92-.4 1.86-.7 3.1-1.1v7.4z"/></svg>

After

Width:  |  Height:  |  Size: 910 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M27.84 22.16A7.15 7.15 0 0 0 22.9 20H22l-2-2 7.98-8c2-2 2-6 0-8L16 14 4.02 2c-2 2-2 6 0 8l8 8-2 2H9.1c-1.7 0-3.5.74-4.94 2.16-2.55 2.55-2.9 6.33-.77 8.45.9 1 2.2 1.4 3.5 1.4a7 7 0 0 0 4.9-2.1 6.86 6.86 0 0 0 2.1-5.8L16 22l2.04 2.05a6.87 6.87 0 0 0 2.1 5.8A7.2 7.2 0 0 0 25.07 32c1.34 0 2.6-.46 3.53-1.4 2.13-2.1 1.8-5.9-.77-8.44zm-16.8 4.26A4.95 4.95 0 0 1 8.44 29c-.5.22-1.02.33-1.5.33-.5 0-1.16-.1-1.67-.6a2.3 2.3 0 0 1-.6-1.64A4 4 0 0 1 5 25.5a3.9 3.9 0 0 1 1-1.53c.44-.46 1-.8 1.52-1.05.5-.23 1.03-.34 1.52-.34.46 0 1.13.1 1.64.6.5.5.6 1.2.6 1.65 0 .5-.1 1.02-.3 1.52zm4.96-5.6a2.83 2.83 0 1 1 0-5.67 2.83 2.83 0 0 1 0 5.68zm10.73 7.9c-.5.5-1.18.6-1.66.6-.5 0-1-.1-1.52-.32a4.92 4.92 0 0 1-2.9-4.08c0-.47.1-1.13.6-1.64.5-.5 1.2-.6 1.65-.6.5 0 1.02.1 1.52.32a5.08 5.08 0 0 1 2.6 2.58c.25.5.37 1.02.37 1.5 0 .47-.1 1.13-.6 1.64z"/></svg>

After

Width:  |  Height:  |  Size: 931 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M32 8l-8-8v6c-4.1 0-7.2.97-9.55 2.98l-.48.43A29.5 29.5 0 0 1 16.1 13c1.5-1.8 3.63-3 7.9-3v12c-6.8 0-8.3-3-10.2-6.9-1.1-2.1-2.2-4.3-4.3-6.1C7.2 7 4.1 6 0 6v4c6.76 0 8.28 3.04 10.2 6.9 1.08 2.14 2.2 4.36 4.25 6.12C16.8 25.02 19.9 26 24 26v6l8-8-8-8 8-8zM0 22v4c4.1 0 7.2-.97 9.55-2.98l.48-.43C9.17 21.4 8.5 20.1 7.9 19c-1.5 1.8-3.67 3-7.9 3z"/></svg>

After

Width:  |  Height:  |  Size: 440 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 2 28 28"><path d="M21.1 16c0 .3-.1.6-.3.8l-9.7 9.7c-.2.2-.5.3-.8.3s-.6-.1-.8-.3c-.2-.2-.3-.5-.3-.8v-5.1h-8c-.3 0-.6-.1-.8-.3-.3-.3-.4-.6-.4-.9v-6.9c0-.3.1-.6.3-.8s.5-.3.8-.3h8V6.3c0-.3.1-.6.3-.8s.5-.3.8-.3.6.1.8.3l9.7 9.7c.3.2.4.5.4.8zm6.3-6.3v12.6c0 1.4-.5 2.6-1.5 3.6s-2.2 1.5-3.6 1.5h-5.7c-.2 0-.3-.1-.4-.2s-.2-.2-.2-.3V26l.1-.4.2-.3.4-.1h5.7c.8 0 1.5-.3 2-.8.6-.6.8-1.2.8-2V9.7c0-.8-.3-1.5-.8-2-.6-.6-1.2-.8-2-.8h-5.8l-.2-.1-.1-.1-.3-.2V5l.2-.3.4-.1h5.7c1.4 0 2.6.5 3.6 1.5s1.5 2.2 1.5 3.6z"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="1 1 28 28"><path d="M12.4 25.7V27l-.2.3-.4.1H6.1c-1.4 0-2.6-.5-3.6-1.5S1 23.7 1 22.3V9.7c0-1.4.5-2.6 1.5-3.6s2.2-1.5 3.6-1.5h5.7c.2 0 .3.1.4.2.1.1.2.2.2.4v.9l-.1.4-.2.3-.4.1H6.1c-.8 0-1.5.3-2 .8-.6.6-.8 1.2-.8 2v12.6c0 .8.3 1.5.8 2 .6.6 1.2.8 2 .8h5.8l.2.1.1.1.1.2.1.2zM29 16c0 .3-.1.6-.3.8L19 26.5c-.2.2-.5.3-.8.3-.3 0-.6-.1-.8-.3a.9.9 0 0 1-.4-.8v-5.1H9c-.3 0-.6-.1-.8-.3-.2-.3-.3-.6-.3-.9v-6.9c0-.3.1-.6.3-.8.2-.2.5-.3.8-.3h8V6.3c0-.3.1-.6.3-.8s.5-.3.8-.3c.3 0 .6.1.8.3l9.7 9.7c.3.2.4.5.4.8z"/></svg>

After

Width:  |  Height:  |  Size: 575 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="1 1 31 31"><path d="M21.3 8H24v16h-2.7V8zM8 24V8l11.3 8z"/></svg>

After

Width:  |  Height:  |  Size: 137 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" class="spinner" viewBox="0 0 80 80"><path d="M10 40v-3.2c0-.3.1-.6.1-.9.1-.6.1-1.4.2-2.1.2-.8.3-1.6.5-2.5.2-.9.6-1.8.8-2.8.3-1 .8-1.9 1.2-3 .5-1 1.1-2 1.7-3.1.7-1 1.4-2.1 2.2-3.1 1.6-2.1 3.7-3.9 6-5.6 2.3-1.7 5-3 7.9-4.1.7-.2 1.5-.4 2.2-.7.7-.3 1.5-.3 2.3-.5.8-.2 1.5-.3 2.3-.4l1.2-.1.6-.1h.6c1.5 0 2.9-.1 4.5.2.8.1 1.6.1 2.4.3.8.2 1.5.3 2.3.5 3 .8 5.9 2 8.5 3.6 2.6 1.6 4.9 3.4 6.8 5.4 1 1 1.8 2.1 2.7 3.1.8 1.1 1.5 2.1 2.1 3.2.6 1.1 1.2 2.1 1.6 3.1.4 1 .9 2 1.2 3 .3 1 .6 1.9.8 2.7.2.9.3 1.6.5 2.4.1.4.1.7.2 1 0 .3.1.6.1.9.1.6.1 1 .1 1.4.4 1 .4 1.4.4 1.4a4.02 4.02 0 0 1-8 .6v-3.4c0-.2-.1-.5-.1-.8-.1-.6-.1-1.2-.2-1.9s-.3-1.4-.4-2.2c-.2-.8-.5-1.6-.7-2.4-.3-.8-.7-1.7-1.1-2.6-.5-.9-.9-1.8-1.5-2.7-.6-.9-1.2-1.8-1.9-2.7A27.12 27.12 0 0 0 48 13.4c-.6-.2-1.3-.4-1.9-.6-.7-.2-1.3-.3-1.9-.4-1.2-.3-2.8-.4-4.2-.5h-2c-.7 0-1.4.1-2.1.1-.7.1-1.4.1-2 .3-.7.1-1.3.3-2 .4-2.6.7-5.2 1.7-7.5 3.1-2.2 1.4-4.3 2.9-6 4.7-.9.8-1.6 1.8-2.4 2.7-.7.9-1.3 1.9-1.9 2.8-.5 1-1 1.9-1.4 2.8-.4.9-.8 1.8-1 2.6-.3.9-.5 1.6-.7 2.4-.2.7-.3 1.4-.4 2.1-.1.3-.1.6-.2.9 0 .3-.1.6-.1.8 0 .5-.1.9-.1 1.3-.2.7-.2 1.1-.2 1.1z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M4 4h24v24H4z"/></svg>

After

Width:  |  Height:  |  Size: 114 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448" viewBox="10 10 372 468"><path d="M128 344V168c0-4.5-3.5-8-8-8h-16c-4.5 0-8 3.5-8 8v176c0 4.5 3.5 8 8 8h16c4.5 0 8-3.5 8-8zm64 0V168c0-4.5-3.5-8-8-8h-16c-4.5 0-8 3.5-8 8v176c0 4.5 3.5 8 8 8h16c4.5 0 8-3.5 8-8zm64 0V168c0-4.5-3.5-8-8-8h-16c-4.5 0-8 3.5-8 8v176c0 4.5 3.5 8 8 8h16c4.5 0 8-3.5 8-8zM120 96h112l-12-29.25c-.75-1-3-2.5-4.25-2.75H136.5c-1.5.25-3.5 1.75-4.25 2.75zm232 8v16c0 4.5-3.5 8-8 8h-24v237c0 27.5-18 51-40 51H72c-22 0-40-22.5-40-50V128H8c-4.5 0-8-3.5-8-8v-16c0-4.5 3.5-8 8-8h77.25l17.5-41.75C107.75 42 122.75 32 136 32h80c13.25 0 28.25 10 33.25 22.25L266.75 96H344c4.5 0 8 3.5 8 8z"/></svg>

After

Width:  |  Height:  |  Size: 671 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 100 100"><path d="M40 0v100l60-50"/></svg>

After

Width:  |  Height:  |  Size: 118 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M21.3 10.7h4v2.6h-6.6V6.7h2.6v4zm-2.6 14.6v-6.6h6.6v2.6h-4v4h-2.6zm-8-14.6v-4h2.6v6.6H6.7v-2.6h4zm-4 10.6v-2.6h6.6v6.6h-2.6v-4h-4z"/></svg>

After

Width:  |  Height:  |  Size: 231 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M16 0L0 16h10v16h12V16h10z"/></svg>

After

Width:  |  Height:  |  Size: 127 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="-1 -3 36 36"><path d="M22.86 15.43q0-.25-.16-.4l-6.3-6.3q-.15-.16-.4-.16t-.4.16L9.3 15q-.18.2-.18.43 0 .25.16.4t.4.17h4v6.3q0 .22.18.4t.4.16h3.44q.23 0 .4-.17t.17-.4V16h4q.22 0 .4-.17t.16-.4zm11.43 5.14q0 2.84-2.06 4.85t-4.85 2H8q-3.3 0-5.65-2.34T0 19.43q0-2.32 1.25-4.3T4.6 12.2l-.03-.77q0-3.8 2.68-6.47t6.47-2.68q2.78 0 5.1 1.56t3.36 4.12q1.27-1.1 2.96-1.1 1.9 0 3.24 1.34t1.34 3.23q0 1.35-.74 2.46 2.32.5 3.82 2.4t1.5 4.23z"/></svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><path d="M500 524a192 192 0 1 0-1-383 192 192 0 0 0 1 383z"/><path d="M587 850h1l12-15 2-3-27-4c-16-2-28-17-28-33v-53c0-16 12-31 27-34h1l25-4-12-15c-6-7-9-14-9-22 0-11 6-18 7-21h1l24-27c20-19 31-26 42-26 8 0 15 3 22 8l17 12c1-8 2-17 5-26 4-15 17-26 33-26h8c-21-24-46-44-75-61l-6-3-5 5a209 209 0 0 1-304 0l-5-5-6 3a329 329 0 0 0-158 243l-1 4 3 3a421 421 0 0 0 315 108c31 0 61-1 89-4l2-4z"/><path d="M816 769c0-32-27-58-60-58-32 0-59 26-59 58a59 59 0 0 0 119 0zm119-25v51c0 3-3 8-7 8l-43 7c-2 7-5 14-9 20a486 486 0 0 0 27 38l-2 5c-6 7-37 41-45 41l-6-2-32-25c-6 4-14 7-21 9-1 14-3 29-6 43-1 3-5 6-9 6h-51c-4 0-8-3-8-7l-7-42-21-8-32 24-6 2-6-2c-12-11-29-26-38-39l-2-5 2-5 24-32c-4-7-7-15-9-22l-43-7c-4 0-6-4-6-8v-51c0-3 2-7 6-8l43-6c2-8 5-14 9-21a547 547 0 0 0-27-37l2-6c6-7 37-41 45-41l6 3 32 24 21-9c2-14 3-29 7-42 1-4 4-7 8-7h51c5 0 8 3 9 7l6 42 21 9 33-25 5-2 6 2c13 12 29 26 38 39 2 2 2 4 2 5l-2 6-24 31c4 7 7 15 9 22l43 7c4 1 7 4 7 8z"/></svg>

After

Width:  |  Height:  |  Size: 1009 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><path d="M822 747l-3 3c-116 91-203 108-323 108s-203-15-315-108l-3-3 1-4c16-107 72-193 158-243l6-3 5 5a209 209 0 0 0 304 0l5-5 6 3c85 49 141 136 158 243l1 4zM500 524a192 192 0 1 0-1-383 192 192 0 0 0 1 383z"/></svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="32" viewBox="0 0 34 32"><path d="M27.8 28.8c-.37 0-.75-.13-1.05-.43a1.5 1.5 0 0 1 0-2.12C29.5 23.5 31 19.87 31 16s-1.5-7.5-4.25-10.25a1.5 1.5 0 0 1 0-2.12c.6-.6 1.54-.6 2.12 0C32.17 6.93 34 11.33 34 16s-1.82 9.07-5.13 12.38c-.3.3-.67.44-1.06.44zM22.5 26c-.38 0-.76-.14-1.06-.43a1.5 1.5 0 0 1 0-2.12 10.5 10.5 0 0 0 0-14.85 1.5 1.5 0 0 1 0-2.12c.6-.6 1.54-.6 2.12 0A13.34 13.34 0 0 1 27.5 16c0 3.6-1.4 7-3.96 9.55-.3.3-.67.44-1.06.44zm-5.32-2.82c-.4 0-.77-.15-1.06-.44-.6-.6-.6-1.54 0-2.12a6.52 6.52 0 0 0 0-9.2c-.6-.58-.6-1.53 0-2.1a1.5 1.5 0 0 1 2.12-.02 9.52 9.52 0 0 1 0 13.44c-.3.3-.68.44-1.06.44zm-4.62-20.7c.8-.8 1.46-.53 1.46.6v25.88c0 1.13-.66 1.4-1.46.6L5 22H0V10h5l7.54-7.54z"/></svg>

After

Width:  |  Height:  |  Size: 753 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="32" viewBox="0 0 34 32"><path d="M17.16 23.16c-.4 0-.77-.15-1.06-.44-.6-.6-.6-1.54 0-2.12a6.52 6.52 0 0 0 0-9.2c-.6-.58-.6-1.53 0-2.12a1.5 1.5 0 0 1 2.12 0 9.52 9.52 0 0 1 0 13.44c-.3.3-.68.44-1.06.44zm-4.62-20.7c.8-.8 1.46-.53 1.46.6v25.88c0 1.13-.66 1.4-1.46.6L5 22H0V10h5l7.54-7.54z"/></svg>

After

Width:  |  Height:  |  Size: 353 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="32" viewBox="0 0 34 32"><path d="M22.48 25.98c-.38 0-.76-.14-1.06-.44a1.5 1.5 0 0 1 0-2.12 10.5 10.5 0 0 0 0-14.85 1.5 1.5 0 0 1 0-2.12 1.5 1.5 0 0 1 2.12 0A13.4 13.4 0 0 1 27.5 16c0 3.6-1.4 7-3.96 9.55-.3.3-.67.44-1.06.44zm-5.32-2.82c-.4 0-.77-.15-1.06-.44-.6-.6-.6-1.54 0-2.12a6.52 6.52 0 0 0 0-9.2c-.6-.58-.6-1.53 0-2.12a1.5 1.5 0 0 1 2.12 0 9.52 9.52 0 0 1 0 13.44c-.3.3-.68.44-1.06.44zm-4.62-20.7c.8-.8 1.46-.53 1.46.6v25.88c0 1.13-.66 1.4-1.46.6L5 22H0V10h5l7.54-7.54z"/></svg>

After

Width:  |  Height:  |  Size: 542 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="32" viewBox="0 0 34 32"><path d="M12.54 2.46c.8-.8 1.46-.53 1.46.6v25.88c0 1.13-.66 1.4-1.46.6L5 22H0V10h5l7.54-7.54zM30 19.36V22h-2.65L24 18.65 20.65 22H18v-2.65L21.35 16 18 12.65V10h2.65L24 13.35 27.35 10H30v2.65L26.65 16z"/></svg>

After

Width:  |  Height:  |  Size: 292 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 426 426"><path d="M406.8 54.2H19.2C8.6 54.2 0 62.8 0 73.4v279.2c0 10.6 8.6 19.2 19.2 19.2h387.6c10.6 0 19.2-8.6 19.2-19.2V73.4c0-10.6-8.6-19.2-19.2-19.2zm-38.4 27.6v.2c10 0 18 8 18 17.8s-8 17.8-18 17.8c-9.8 0-17.8-8-17.8-17.8 0-10 8-18 17.8-18zm-47.8 0l-.2.2c10 0 18 8 18 17.8s-8 17.8-18 17.8-17.8-8-17.8-17.8c0-10 8-18 18-18zm-48 0l-.2.2c10 0 18 8 18 17.8s-8 17.8-18 17.8c-9.8 0-17.8-8-17.8-17.8 0-10 8-18 18-18zm115 251.6H38.4V141.6h349.2v191.8z"/><path d="M293 175l-63.8 64 64 64-16 16.2-64.2-63.8-64 63.7-16-15.6 63.8-64.2-64-64 16-16 64.2 64 64-64 16 16z"/></svg>

After

Width:  |  Height:  |  Size: 621 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="426" height="426" viewBox="0 0 426 426"><path d="M406.8 54.2H19.2C8.6 54.2 0 62.8 0 73.4v279.2c0 10.6 8.6 19.2 19.2 19.2h387.6c10.6 0 19.2-8.6 19.2-19.2V73.4c0-10.6-8.6-19.2-19.2-19.2zM368.4 82c10 0 18 8 18 17.8s-8 17.8-18 17.8c-9.8 0-17.8-8-17.8-17.8 0-10 8-18 17.8-18zm-48 0c10 0 18 8 18 17.8s-8 17.8-18 17.8-17.8-8-17.8-17.8c0-10 8-18 18-18zm-48 0c10 0 18 8 18 17.8s-8 17.8-18 17.8c-9.8 0-17.8-8-17.8-17.8 0-10 8-18 18-18zm115.2 251.4H38.4V141.6h349.2v191.8z"/></svg>

After

Width:  |  Height:  |  Size: 517 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="768" height="768" viewBox="0 0 768 768"><path d="M544.5 352.5q52.5 0 90 37.5t37.5 90-37.5 90-90 37.5H480V672l-96-96 96-96v64.5h72q25.5 0 45-19.5t19.5-45-19.5-45-45-19.5H127.5v-63h417zm96-192v63h-513v-63h513zm-513 447v-63h192v63h-192z"/></svg>

After

Width:  |  Height:  |  Size: 289 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M13.8 8.7h-1.6v3.4H8.8v1.7h3.4V17h1.7v-3.2h3.2v-1.7h-3.4"/><path d="M25.7 27.7l2-2L21 19l-1-1c1.1-1.5 1.6-3.1 1.6-5 0-2.4-.8-4.5-2.5-6.2S15.4 4.3 13 4.3s-4.5.8-6.2 2.5C5.2 8.5 4.3 10.6 4.3 13s.8 4.5 2.5 6.1c1.7 1.7 3.7 2.5 6.2 2.5 1.9 0 3.6-.5 5-1.6m-5-1c-1.7 0-3.1-.6-4.2-1.8C7.6 16.1 7 14.7 7 13s.6-3.1 1.8-4.2C10 7.6 11.4 7 13 7c1.7 0 3.1.6 4.2 1.8C18.5 9.9 19 11.4 19 13c0 1.7-.6 3.1-1.8 4.2-1.1 1.2-2.5 1.8-4.2 1.8z"/></svg>

After

Width:  |  Height:  |  Size: 498 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M8.8 12.1v1.7h8.3v-1.7"/><path d="M25.7 27.7l2-2L21 19l-1-1c1.1-1.5 1.6-3.1 1.6-5 0-2.4-.8-4.5-2.5-6.2S15.4 4.3 13 4.3s-4.5.8-6.2 2.5C5.2 8.5 4.3 10.6 4.3 13s.8 4.5 2.5 6.1c1.7 1.7 3.7 2.5 6.2 2.5 1.9 0 3.6-.5 5-1.6m-5-1c-1.7 0-3.1-.6-4.2-1.8C7.6 16.1 7 14.7 7 13s.6-3.1 1.8-4.2C10 7.6 11.4 7 13 7c1.7 0 3.1.6 4.2 1.8C18.5 9.9 19 11.4 19 13c0 1.7-.6 3.1-1.8 4.2-1.1 1.2-2.5 1.8-4.2 1.8z"/></svg>

After

Width:  |  Height:  |  Size: 464 B

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { HomeOutlined } from '@ant-design/icons-vue';
import { RouterLink } from 'vue-router'
import Breadcrumb from '@/components/Breadcrumb.vue'
const props = withDefaults(
defineProps<{
@ -16,19 +16,54 @@ function generateUrl(pathIndex: number) {
<template>
<nav>
<a-breadcrumb>
<a-breadcrumb-item>
<RouterLink to="/">
<home-outlined />
</RouterLink>
</a-breadcrumb-item>
<a-breadcrumb-item v-for="(location, index) in path" :key="index">
<RouterLink :to ="generateUrl(index)">
<span :class="(index === path.length - 1) && 'last' ">{{ decodeURIComponent(location) }}</span>
</RouterLink>
</a-breadcrumb-item>
</a-breadcrumb>
<!--
<div class="view-nav">
<div class="view-nav-left">
<button class="af button tip tip-se" aria-label="Upload files from disk">{{{svg "add-file"}}}</button>
<button class="ad button tip tip-s" aria-label="Upload folder from disk">{{{svg "add-folder"}}}</button>
<button class="cd button tip tip-s" aria-label="Create folder">{{{svg "create-folder"}}}</button>
</div>
<div class="view-nav-right">
<div class="search toggled-off tip tip-s" aria-label="Search">
{{{svg "find"}}}
<input class="search-input" type="search" placeholder="Term" />
</div>
<button class="reload button tip tip-s" aria-label="Reload View">{{{svg "reload"}}}</button>
<button class="newview button tip tip-s" aria-label="Create new View">{{{svg "window"}}}</button>
<button class="prefs button tip tip-s" aria-label="Preferences">{{{svg "cog"}}}</button>
<button class="about button tip tip-s" aria-label="About">{{{svg "info"}}}</button>
<button class="logout button tip tip-sw" aria-label="Sign out">{{{svg "signout"}}}</button>
</div>
</div>
<ul class="path"></ul>
<div class="content-container">
<div class="content"></div>
</div>
<div class="dropzone">
<svg></svg>
</div>
<div class="info-box">
<div class="icon">{{{svg "link"}}}</div>
<span></span>
<div class="link-out mousetrap"></div>
<div class="link-options">
<div class="copy-link tip tip-nw" aria-label="Copy to clipboard">
{{{svg "copy"}}}<div>Copy</div>
</div>
<div class="dl-link checked tip tip-sw" aria-label="Trigger a download when opened">
{{{svg "check"}}}<div>Is DL</div>
</div>
</div>
</div>
<div class="paste-button">
{{{svg "paste"}}}
<span>Paste here</span>
{{{svg "triangle"}}}
</div>
-->
<Breadcrumb :path="props.path"/>
</nav>
</template>
@ -38,6 +73,6 @@ function generateUrl(pathIndex: number) {
}
span:hover, .last{
color: var(--blue-color)
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<div class="breadcrumb">
<a href="#/"><component :is="home"/></a>
<template v-for="(location, index) in props.path">
<a :href="`/#/${props.path.slice(0, index + 1).join('/')}/`">{{ decodeURIComponent(location) }}</a>
</template>
</div>
</template>
<script setup lang="ts">
import home from '@/assets/svg/home.svg'
import { withDefaults, defineProps } from 'vue'
const props = withDefaults(
defineProps<{
path: Array<string>
}>(),
{},
)
</script>
<style>
:root {
--breadcrumb-background-odd: #2d2d2d;
--breadcrumb-background-even: #404040;
--breadcrumb-color: #ddd;
--breadcrumb-hover-color: #fff;
--breadcrumb-hover-background-odd: #25a;
--breadcrumb-hover-background-even: #812;
--breadcrumb-transtime: 0.3s;
}
.breadcrumb {
display: flex;
list-style: none;
margin: 0;
padding: 0 1em 0 0;
}
.breadcrumb > a {
margin: 0 -0.7rem 0 -.7rem;
padding: 0;
max-width: 8em;
font-size: 1.3em;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
height: 1em;
color: var(--breadcrumb-color);
padding: .3em 1.5em;
clip-path: polygon(0 0, 1em 50%, 0 100%, 100% 100%, 100% 0, 0 0);
transition: all var(--breadcrumb-transtime);
}
.breadcrumb a:first-child {
margin-left: 0;
padding-left: 0;
clip-path: none;
}
.breadcrumb a:last-child {
max-width: none;
clip-path: polygon(0 0, calc(100% - 1em) 0, 100% 50%, calc(100% - 1em) 100%, 0 100%, 1em 50%, 0 0);
}
.breadcrumb a:only-child {
clip-path: polygon(0 0, calc(100% - 1em) 0, 100% 50%, calc(100% - 1em) 100%, 0 100%, 0 0);
}
.breadcrumb svg {
/* FIXME: Custom positioning to align it well; needs proper solution */
transform: translate(.3rem, -.3rem) scale(80%);
fill: var(--breadcrumb-color);
transition: fill var(--breadcrumb-transtime);
}
.breadcrumb a:nth-child(odd) { background: var(--breadcrumb-background-odd); }
.breadcrumb a:nth-child(even) { background: var(--breadcrumb-background-even) }
.breadcrumb a:nth-child(odd):hover { background: var(--breadcrumb-hover-background-odd); }
.breadcrumb a:nth-child(even):hover { background: var(--breadcrumb-hover-background-even); }
.breadcrumb a:hover { color: var(--breadcrumb-hover-color); }
.breadcrumb a:hover svg { fill: var(--breadcrumb-hover-color); }
</style>

View File

@ -0,0 +1,69 @@
<template>
<dialog ref="dialog">
<h1 v-if="title">{{ title }}</h1>
<div>
<slot>Dialog with no content</slot>
</div>
<button onclick="dialog.close()">OK</button>
</dialog>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const dialog = ref<HTMLDialogElement | null>(null)
const props = withDefaults(
defineProps<{
title: string
}>(),
{
title: '',
},
)
onMounted(() => {
dialog.value!.showModal()
})
</script>
<style>
/* Style for the background */
body:has(dialog[open])::before {
content: '';
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0008;
backdrop-filter: blur(.2em);
z-index: 1000;
}
/* Hide the dialog by default */
dialog[open] {
display: block;
border: none;
border-radius: .5rem;
box-shadow: .2rem .2rem 1rem #000;
padding: 1rem;
position: fixed;
top: 0;
left: 0;
z-index: 1001;
}
dialog[open] > h1 {
background: #00f;
color: #fff;
font-size: 1rem;
margin: -1rem -1rem 0 -1rem;
padding: .5rem 1rem .5rem 1rem;
}
dialog[open] > div {
padding: 1em 0;
}
</style>

View File

@ -1,137 +0,0 @@
<template>
<div class="carousel" ref="fileCarousel">
<a-page-header :style="{ visibility: idle ? 'hidden' : 'visible' }">
<template #extra>
<a-button type="text" class="action-button" :onclick="toggle" :icon="h(isFullscreen? FullscreenExitOutlined: FullscreenOutlined)" />
<a-button type="text" class="action-button" :onclick="redirectBack" :icon="h(CloseOutlined)" />
</template>
</a-page-header>
<a-row class="slider">
<a-col :span="2" class="centered-vertically">
<div class="custom-slick-arrow slick-arrow slick-prev centered" @click="next(-1)" style="left: 10px; z-index: 1">
<LeftOutlined v-show="!idle" />
</div>
</a-col>
<a-col :span="20" class="centered">
<FileViewer v-if="!documentStore.loading" :visibleImg="visible" @visibleImg="setVisible" :type="fileType"></FileViewer>
</a-col>
<a-col :span="2" class="centered-vertically right">
<div class="custom-slick-arrow slick-arrow slick-prev centered" @click="next(1)" style="right: 10px">
<RightOutlined v-show="!idle" />
</div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { h, ref, watchEffect } from 'vue'
import { useDocumentStore } from '@/stores/documents'
import { useIdle, useFullscreen } from '@vueuse/core'
import { LeftOutlined, RightOutlined, FullscreenOutlined, FullscreenExitOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { getFileType } from '@/utils'
import Router from '@/router/index';
import FileViewer from './FileViewer.vue';
const fileCarousel = ref<HTMLElement | null>(null)
const { isFullscreen, toggle } = useFullscreen(fileCarousel)
const visible = ref<boolean>(false);
const documentStore = useDocumentStore()
const fileType = ref<string| undefined>(undefined);
watchEffect(() => {
if(documentStore.mainDocument[0] && documentStore.mainDocument[0].type === 'file'){
const fileExt = documentStore.mainDocument[0].ext
fileType.value = getFileType(fileExt)
}
})
function setVisible(value: boolean) {
visible.value = value;
}
const { idle } = useIdle(2000)
function redirectBack() {
const currentPath = Router.currentRoute.value.path;
const pathParts = currentPath.split('/').filter(part => part); // Remove empty parts
// Ensure there's always at least one part in the path
if (pathParts.length <= 1) {
// If it's empty, set it to the base URL
pathParts[0] = '/';
} else {
pathParts.pop();
}
const newPath = pathParts.join('/');
Router.push(newPath);
}
function next(direction: number){
const path = decodeURIComponent(new String(Router.currentRoute.value.path) as string)
const name = documentStore.getNextDocumentInRoute(direction, path)
let nextFileLocation : string[] | string = path.split('/')
nextFileLocation.pop()
nextFileLocation.push(name)
nextFileLocation = nextFileLocation.join('/')
Router.push(nextFileLocation)
}
</script>
<style scoped>
:deep(.slick-arrow.custom-slick-arrow) {
width: 60px;
height: 60px;
font-size: 60px;
color: var(--primary-color);
transition: ease-in all 0.3s;
opacity: 0.3;
z-index: 1;
}
:deep(.slick-arrow.custom-slick-arrow:before) {
display: none;
}
:deep(.slick-arrow.custom-slick-arrow:hover) {
color: var(--primary-color);
opacity: 1;
}
.slider {
height: 80vh;
background-color: inherit;
}
.centered {
display: flex;
justify-content: center;
align-content: center;
}
.centered-vertically {
display: flex;
align-items: center;
}
.right {
flex-direction: row-reverse;
}
.action-button {
padding: 0;
font-size: 1.5em;
opacity: 0.5;
color: var(--secondary-color);
&:hover {
color: var(--blue-color);
}
}
.ant-page-header {
padding: 0;
}
.carousel{
margin: 0;
height: inherit;
background-color: var(--table-background);
}
</style>

View File

@ -1,224 +1,220 @@
<template>
<main>
<context-holder />
<!-- <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'">
<FileCarousel></FileCarousel>
</div>
<main>
<table v-if="props.documents.length">
<thead>
<tr>
<th class="selection"><input type="checkbox" v-model="allSelected" :indeterminate="selectionIndeterminate"></th>
<th class="sortcolumn" :class="{sortactive: sort === 'name'}" @click="toggleSort('name')">Name</th>
<th class="sortcolumn modified right" :class="{sortactive: sort === 'modified'}" @click="toggleSort('modified')">Modified</th>
<th class="sortcolumn size right" :class="{sortactive: sort === 'size'}" @click="toggleSort('size')">Size</th>
</tr>
</thead>
<tbody>
<tr v-for="doc of sorted(props.documents as FolderDocument[])" :key="doc.key" :class="doc.type === 'folder' ? 'folder' : 'file'">
<td class="selection">
<input type="checkbox" :checked="doc.key in documentStore.selected" @change="documentStore.selected.add(doc.key)">
</td>
<td class="name">
<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>
</tr>
</tbody>
</table>
<div v-else>
<p>No files</p>
</div>
</main>
</template>
<table v-else-if="!documentStore.loading && documentStore.mainDocument">
<thead>
<tr>
<th class="selection"><input type="checkbox" v-model="allSelected" :indeterminate="selectionIndeterminate"></th>
<th class="sortcolumn" :class="{sortactive: sort === 'name'}" @click="toggleSort('name')">Name</th>
<th class="sortcolumn modified right" :class="{sortactive: sort === 'modified'}" @click="toggleSort('modified')">Modified</th>
<th class="sortcolumn size right" :class="{sortactive: sort === 'size'}" @click="toggleSort('size')">Size</th>
</tr>
</thead>
<tbody>
<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">
<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>
</tr>
</tbody>
</table>
</main>
</template>
<script setup lang="ts">
import { ref, h, computed, reactive, watchEffect } from 'vue'
import type { UnwrapRef } from 'vue'
import { useDocumentStore } from '@/stores/documents'
import Router from '@/router/index';
import { message } from 'ant-design-vue';
import type { Document, FolderDocument } from '@/repositories/Document';
import FileCarousel from './FileCarousel.vue';
import FileRenameInput from './FileRenameInput.vue'
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useDocumentStore } from '@/stores/documents'
import type { Document, FolderDocument } from '@/repositories/Document';
import FileRenameInput from './FileRenameInput.vue'
import createWebSocket from '@/repositories/WS';
const [messageApi, contextHolder] = message.useMessage();
const props = withDefaults(
defineProps<{
path: string,
documents: Document[],
}>(),
{},
)
type Key = string | number;
const documentStore = useDocumentStore()
const editableData: UnwrapRef<Record<string, Document>> = reactive({});
const state = reactive<{
selectedRowKeys: Key[];
}>({
selectedRowKeys: [],
});
const linkBasePath = computed(()=>{
const path = Router.currentRoute.value.path
return path === '/' ? '' : path
const documentStore = useDocumentStore()
const linkBasePath = computed(()=>{
const path = props.path
return path === '/' ? '' : path
})
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
const url_for = (doc: FolderDocument) => (
doc.type === "folder" ?
`#${linkBasePath.value}/${doc.name}` :
`${filesBasePath.value}/${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)
}
})
const filesBasePath = computed(() => `/files${linkBasePath.value}`)
const url_for = (doc: FolderDocument) => doc.type === "folder" ? `#${linkBasePath.value}/${doc.name}` : `${filesBasePath}/${doc.name}`
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
}
// 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
// Column sort
const toggleSort = (name: string) => { sort.value = sort.value === name ? "" : name }
const sort = ref<string>("")
const sortCompare = {
"name": (a: Document, b: Document) => a.name.localeCompare(b.name),
"modified": (a: FolderDocument, b: FolderDocument) => b.mtime - a.mtime,
"size": (a: FolderDocument, b: FolderDocument) => b.size - a.size
}
const sorted = (documents: FolderDocument[]) => {
const cmp = sortCompare[sort.value as keyof typeof sortCompare]
const sorted = [...documents]
if (cmp) sorted.sort(cmp)
return sorted
}
const selectionIndeterminate = computed({
get: () => {
return props.documents.length > 0 && props.documents.some((doc: Document) => doc.key in documentStore.selected) && !allSelected.value
},
set: (value: boolean) => {}
})
const allSelected = computed({
get: () => {
return props.documents.length > 0 && props.documents.every((doc: Document) => doc.key in documentStore.selected)
},
set: (value: boolean) => {
for (const doc of props.documents) {
if (value) {
documentStore.selected.add(doc.key)
} 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 = {
"name": (a: Document, b: Document) => a.name.localeCompare(b.name),
"modified": (a: FolderDocument, b: FolderDocument) => b.mtime - a.mtime,
"size": (a: FolderDocument, b: FolderDocument) => b.size - a.size
}
const sorted = (documents: FolderDocument[]) => {
const cmp = sortCompare[sort.value as keyof typeof sortCompare]
const sorted = [...documents]
if (cmp) sorted.sort(cmp)
return sorted
}
const selectionIndeterminate = computed({
get: () => {
return documentStore.mainDocument && documentStore.mainDocument.length > 0 && documentStore.mainDocument.some((doc: Document) => doc.selected) && !allSelected.value
},
set: (value: boolean) => {}
})
const allSelected = computed({
get: () => {
return documentStore.mainDocument && documentStore.mainDocument.length > 0 && documentStore.mainDocument.every((doc: Document) => doc.selected)
},
set: (value: boolean) => {
if (documentStore.mainDocument) {
documentStore.mainDocument.forEach((doc: Document) => doc.selected = value)
documentStore.selected.delete(doc.key)
}
}
})
</script>
}
})
</script>
<style>
table {
width: 100%;
table-layout: fixed;
}
table input[type=checkbox] {
width: 1em;
height: 1em;
}
table .modified { width: 10em; }
table .size { width: 6em; }
table th, table td {
padding: .5em;
font-weight: normal;
text-align: left;
white-space: nowrap;
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;
}
tbody tr {
background: #444;
color: #ddd;
}
tbody tr:hover {
background: #00f8;
}
.right {
text-align: right;
}
.selection {
width: 2em;
}
.sortcolumn:hover {
cursor: pointer;
}
.sortcolumn:hover::after {
color: #f80;
}
.sortcolumn {
padding-right: 1.7em;
}
.sortcolumn::after {
content: "▸";
color: #888;
margin: 0 1em 0 .5em;
position: absolute;
transition: transform 0.5s ease;
}
.sortactive::after {
transform: rotate(90deg);
color: #000;
}
main {
padding: 5px;
height: 100%;
}
.more-action{
display: flex;
flex-direction: column;
justify-content: start;
}
.action-container{
display: flex;
align-items: center;
}
.edit-action{
min-width: 5%;
}
.carousel-container{
height: inherit;
}
.name a {
text-decoration: none;
}
.file .name::before {
content: '📄 ';
font-size: 1.5em;
}
.folder .name::before {
content: '📁 ';
font-size: 1.5em;
}
</style>
<style>
table {
width: 100%;
table-layout: fixed;
}
table input[type=checkbox] {
width: 1em;
height: 1em;
}
table .modified { width: 10em; }
table .size { width: 6em; }
table th, table td {
padding: .5em;
font-weight: normal;
text-align: left;
white-space: nowrap;
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;
color: #000;
}
tbody tr:hover {
background: #00f8;
}
.right {
text-align: right;
}
.selection {
width: 2em;
}
.sortcolumn:hover {
cursor: pointer;
}
.sortcolumn:hover::after {
color: #f80;
}
.sortcolumn {
padding-right: 1.7em;
}
.sortcolumn::after {
content: "▸";
color: #888;
margin: 0 1em 0 .5em;
position: absolute;
transition: all 0.2s linear;
}
.sortactive::after {
transform: rotate(90deg);
color: #000;
}
main {
padding: 5px;
height: 100%;
}
.more-action{
display: flex;
flex-direction: column;
justify-content: start;
}
.action-container{
display: flex;
align-items: center;
}
.edit-action{
min-width: 5%;
}
.carousel-container{
height: inherit;
}
.name a {
text-decoration: none;
}
.file .name::before {
content: '📄 ';
font-size: 1.5em;
}
.folder .name::before {
content: '📁 ';
font-size: 1.5em;
}
</style>

View File

@ -2,13 +2,11 @@
import { useDocumentStore } from '@/stores/documents'
import LoginModal from '@/components/LoginModal.vue'
import UploadButton from '@/components/UploadButton.vue'
import { InfoCircleOutlined, SettingOutlined, PlusSquareOutlined, SearchOutlined, DeleteOutlined, DownloadOutlined, FileAddFilled, LinkOutlined, FolderAddFilled, FileFilled, FolderFilled } from '@ant-design/icons-vue'
import { h, ref } from 'vue';
import { ref } from 'vue';
const documentStore = useDocumentStore()
const searchQuery = ref<string>('')
const showSearchInput = ref<boolean>(false)
const isLoading = ref<boolean>(false)
const toggleSearchInput = () => {
showSearchInput.value = !showSearchInput.value;
@ -35,9 +33,6 @@ function uploadFolderHandler() {
function createFolderHandler() {
console.log("Uploading Folder")
}
function searchHandler() {
console.log("Searching ...")
}
function newViewHandler() {
console.log("Creating new view ...")
}
@ -48,11 +43,7 @@ function about() {
console.log("About ...")
}
function deleteHandler(){
if(documentStore.selectedDocuments){
documentStore.selectedDocuments.forEach(document => {
documentStore.deleteDocument(document)
})
}
console.log("Delete ...")
}
function share(){
console.log("Share ...")
@ -67,6 +58,7 @@ function download(){
<div class="actions-container">
<div class="actions-list">
<UploadButton />
<!--
<a-tooltip title="Upload folder from disk">
<a-button @click="uploadFolderHandler" type="text" class="action-button" :icon="h(FolderAddFilled)" />
@ -79,8 +71,8 @@ function download(){
<a-tooltip title="Create folder">
<a-button @click="createFolderHandler" type="text" class="action-button" :icon="h(FolderFilled)" />
</a-tooltip>
<!-- TODO ADD CONDITIONAL RENDER -->
<template v-if="documentStore.selectedDocuments && documentStore.selectedDocuments.length > 0">
<template v-if="documentStore.selected.size > 0">
<a-tooltip title="Share">
<a-button type="text" @click="share" class="action-button" :icon="h(LinkOutlined)" />
</a-tooltip>
@ -91,18 +83,15 @@ function download(){
<a-button type="text" @click="deleteHandler" class="action-button" :icon="h(DeleteOutlined)" />
</a-tooltip>
</template>
-->
</div>
<div class="actions-list">
<LoginModal></LoginModal>
<template v-if="showSearchInput">
<a-input-search
v-model="searchQuery"
class="margin-input"
@change="executeSearch"
@search="executeSearch"
:loading="isLoading"
/>
<input type="search" v-model="searchQuery" class="margin-input">
</template>
<!--
<a-tooltip title="Search">
<a-button @click="toggleSearchInput" type="text" class="action-button" :icon="h(SearchOutlined)" />
</a-tooltip>
@ -118,6 +107,8 @@ function download(){
<a-tooltip title="About">
<a-button @click="about" type="text" class="action-button" :icon="h(InfoCircleOutlined)" />
</a-tooltip>
-->
</div>
</div>
</template>
@ -154,4 +145,16 @@ function download(){
.margin-input{
margin-top: 5px;
}
.path {
box-shadow: 0 0 0.5em rgba(0,0,0,.15);
overflow: hidden;
white-space: nowrap;
width: 100%;
z-index: 1;
flex: 0 0 1.5rem;
order: 1;
font-size: .9rem;
position: relative;
}
</style>

View File

@ -1,4 +1,6 @@
<template>
<!--
<a-tooltip title="Login">
<template v-if="DocumentStore.isUserLogged">
<a-button @click="logout" type="text" class="action-button" :icon="h(UserDeleteOutlined)" />
@ -20,11 +22,11 @@
</a-form>
</div>
</a-modal>
-->
</template>
<script lang="ts" setup>
import { ref, h } from 'vue';
import { UserOutlined, UserDeleteOutlined } from '@ant-design/icons-vue';
import { useDocumentStore } from '@/stores/documents';
import { loginUser, logoutUser } from '@/repositories/User';
import type { ISimpleError } from '@/repositories/Client';
@ -60,14 +62,14 @@ const login = async () => {
} catch (error) {
const httpError = error as ISimpleError
if(httpError.name){
loginForm.value.error = httpError.message
loginForm.value.error = httpError.message
}
}finally{
confirmLoading.value = false;
}
};
</script>
<style scoped>
.login-container {
display: flex;
@ -87,4 +89,3 @@ const login = async () => {
color :var(--red-color)
}
</style>

View File

@ -8,15 +8,14 @@
</template>
</template>
<script setup lang="ts">
import { CloseCircleOutlined } from '@ant-design/icons-vue';
import { useDocumentStore } from '@/stores/documents'
const documentStore = useDocumentStore();
function dismissUpload(key: number){
documentStore.deleteUploadingDocument(key)
}
</script>
import { useDocumentStore } from '@/stores/documents'
const documentStore = useDocumentStore()
function dismissUpload(key: number){
documentStore.deleteUploadingDocument(key)
}
</script>
<style scoped>
.progress-container{
display: flex;
@ -25,4 +24,4 @@ import { CloseCircleOutlined } from '@ant-design/icons-vue';
.close-button:hover{
color: #b81414;
}
</style>
</style>

View File

@ -1,27 +1,22 @@
<script setup lang="ts">
import { useDocumentStore } from '@/stores/documents'
import NotificationLoading from '@/components/NotificationLoading.vue'
import { FileAddFilled } from '@ant-design/icons-vue'
import { notification } from 'ant-design-vue';
import type { NotificationPlacement } from 'ant-design-vue';
import { h, ref } from 'vue';
const [api, contextHolder] = notification.useNotification();
const fileUploadButton = ref()
const documentStore = useDocumentStore();
const open = (placement: NotificationPlacement) => openNotification(placement);
const open = (placement: any) => openNotification(placement);
const isNotificationOpen = ref(false);
const openNotification = (placement: NotificationPlacement) => {
const openNotification = (placement: any) => {
if(!isNotificationOpen.value){
/*
api.open({
message: `Uploading documents`,
description: h(NotificationLoading),
placement,
duration: 0,
onClose: () => { isNotificationOpen.value = false }
});
});*/
isNotificationOpen.value = true;
}
};
@ -44,10 +39,10 @@ async function load(file: File, start: number, end: number): Promise<ArrayBuffer
}
async function sendChunk(file :File, start: number, end: number) {
const ws = documentStore.wsUpload;
const ws = documentStore.wsUpload;
if(ws){
const chunk = await load(file, start, end)
ws.send(JSON.stringify({
name: file.name,
size: file.size,
@ -78,15 +73,18 @@ async function uploadFileChangeHandler(event: Event) {
}
</script>
<template>
<!--
<a-tooltip title="Upload files from disk">
<a-button @click="uploadFileHandler" type="text" class="action-button" :icon="h(FileAddFilled)" />
<input ref="fileUploadButton" @change="uploadFileChangeHandler" class="upload-input" type="file" onclick="this.value=null;" />
</a-tooltip>
<contextHolder />
-->
</template>
<style scoped>
/* Extends styles from HeaderMain.vue too */
.upload-input{
display: none;
}
</style>
</style>

View File

@ -1,9 +1,7 @@
import 'ant-design-vue/dist/reset.css';
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue';
import App from './App.vue'
import router from './router'
@ -15,7 +13,6 @@ app.config.errorHandler = (err) => {
}
app.use(createPinia())
app.use(Antd);
app.use(router)
app.mount('#app')
app.mount('#app')

View File

@ -1,32 +1,21 @@
import axios, {AxiosError} from 'axios'
/* Base domain for all request */
export const baseURL = import.meta.env.VITE_URL_DOCUMENT
/* Config Client*/
const Client = axios.create({
baseURL: baseURL,
headers: {
Accept: 'application/json',
},
})
Client.interceptors.response.use(
(response) => {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response
},
(error: AxiosError<any>) => {
const msg = error.response && error.response.data && error.response.data.error ?
error.response.data.error.message : 'Unexpected error'
const code = error.code ? Number(error.response?.status) : 500
const standardizedError = new SimpleError(code, msg)
return Promise.reject(standardizedError)
class ClientClass {
async post(url: string, data?: Record<string, any>): Promise<any> {
const res = await fetch(`${baseURL}/`, {
method: "POST",
headers: {
accept: 'application/json',
"content-type": 'application/json',
},
body: data !== undefined ? JSON.stringify(data) : undefined,
})
return await res.json()
}
)
}
export const Client = new ClientClass()
export interface ISimpleError extends Error {
code : number
}

View File

@ -1,28 +1,22 @@
import type { FileStructure, DocumentStore } from '@/stores/documents'
import type { DocumentStore } from '@/stores/documents'
import { useDocumentStore } from '@/stores/documents'
import { getFileExtension } from '@/utils'
import Client from '@/repositories/Client'
export type FUID = string;
type BaseDocument = {
name: string
key?: number | string
selected?: boolean
key: FUID
};
export type FolderDocument = BaseDocument & {
type: 'folder' | 'folder-file';
size: number;
sizedisp: string;
mtime: number;
modified: string;
type: 'folder' | 'file'
size: number
sizedisp: string
mtime: number
modified: string
};
export type FileDocument = BaseDocument & {
type: 'file';
ext: string;
data: string;
};
export type Document = FolderDocument
export type errorEvent = {
error: {
@ -32,8 +26,31 @@ export type errorEvent = {
}
};
export type Document = FolderDocument | FileDocument;
// Raw types the backend /api/watch sends us
export type FileEntry = {
id: FUID
size: number
mtime: number
}
export type DirEntry = {
id: FUID
size: number
mtime: number
dir: DirList
}
export type DirList = Record<string, FileEntry | DirEntry>
export type UpdateEntry = {
name: string
deleted?: boolean
id?: FUID
size?: number
mtime?: number
dir?: DirList
}
export const url_document_watch_ws = '/api/watch'
export const url_document_upload_ws = '/api/upload'
@ -60,18 +77,27 @@ export class DocumentHandler {
}
}
private handleRootMessage({ root }: { root: FileStructure }) {
private handleRootMessage({ root }: { root: DirEntry }) {
if (this.store && this.store.root) {
this.store.user.isLoggedIn = true;
this.store.root = root;
}
}
private handleUpdateMessage(updateData: { update: FileStructure[] }) {
const root = updateData.update[0]
if(root) {
this.store.user.isLoggedIn = true;
this.store.root = root
private handleUpdateMessage(updateData: { update: UpdateEntry[] }) {
let node: DirEntry = this.store.root;
for (const elem of updateData.update) {
if (elem.deleted) {
delete node.dir[elem.name]
break // Deleted elements can't have further children
}
if (elem.name !== undefined) {
// @ts-ignore
node = node.dir[elem.name] ||= {}
}
if (elem.id !== undefined) node.id = elem.id
if (elem.size !== undefined) node.size = elem.size
if (elem.mtime !== undefined) node.mtime = elem.mtime
if (elem.dir !== undefined) node.dir = elem.dir
}
}
private handleError(msg: errorEvent){
@ -103,13 +129,3 @@ export class DocumentUploadHandler {
console.log('Written message', msg.written)
}
}
export async function fetchFile(path: string): Promise<FileDocument>{
const file = await Client.get(url_document_get + path)
const name = path.substring(1 , path.length)
return {
name,
data: file.data,
type: 'file',
ext: getFileExtension(name)
}
}

View File

@ -1,7 +1,6 @@
import type { Document } from '@/repositories/Document';
import { fetchFile } from '@/repositories/Document'
import { formatSize, formatUnixDate } from '@/utils';
import { defineStore } from 'pinia';
import type { Document, DirEntry, FileEntry, FUID, DirList } from '@/repositories/Document'
import { formatSize, formatUnixDate } from '@/utils'
import { defineStore } from 'pinia'
// @ts-ignore
import { localeIncludes } from 'locale-includes'
@ -9,21 +8,19 @@ type FileData = { id: string, mtime: number, size: number, dir: DirectoryData};
type DirectoryData = {
[filename: string]: FileData;
};
export type FileStructure = {id: string, mtime: number, size: number, dir: DirectoryData};
type User = {
isOpenLoginModal: boolean,
isLoggedIn : boolean,
}
export type DocumentStore = {
root: FileStructure,
root: DirEntry,
document: Document[],
loading: boolean,
selected: Set<FUID>,
uploadingDocuments: Array<{key: number, name: string, progress: number}>,
uploadCount: number,
wsWatch: WebSocket | undefined,
wsUpload: WebSocket | undefined,
selectedDocuments: Document[],
user: User,
error: string,
}
@ -31,24 +28,23 @@ export type DocumentStore = {
export const useDocumentStore = defineStore({
id: 'documents',
state: (): DocumentStore => ({
root: {} as FileStructure,
root: {} as DirEntry,
document: [] as Document[],
loading: true as boolean,
selected: new Set<FUID>(),
uploadingDocuments: [],
uploadCount: 0 as number,
wsWatch: undefined,
wsUpload: undefined,
selectedDocuments: [] as Document[],
error: '' as string,
user: { isLoggedIn: false, isOpenLoginModal: false } as User
}),
actions: {
updateTable(matched: DirectoryData) {
updateTable(matched: DirList) {
// Transform data
const dataMapped = []
for (const [name, attr] of Object.entries(matched)) {
const {id, size, mtime, dir} = attr
const {id, size, mtime} = attr
const element: Document = {
name,
key: id,
@ -56,18 +52,17 @@ export const useDocumentStore = defineStore({
sizedisp: formatSize(size),
mtime,
modified: formatUnixDate(mtime),
type: dir === undefined ? 'folder-file' : 'folder',
type: "dir" in attr ? 'folder' : 'file',
}
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.loading = false;
},
setFilter(filter: string){
function traverseDir(data: FileStructure, path: string){
if (data.dir === undefined) return
function traverseDir(data: DirEntry | FileEntry, path: string){
if (!("dir" in data)) return
for (const [name, attr] of Object.entries(data.dir)) {
const fullname = `${path}/${name}`
if (localeIncludes(name, filter, {usage: "search", sensitivity: "base"})) {
@ -76,47 +71,32 @@ export const useDocumentStore = defineStore({
traverseDir(attr, fullname)
}
}
this.loading = true
const matched: any = {}
traverseDir(this.root, "")
this.updateTable(matched)
},
setActualDocument(location: string){
location = decodeURIComponent(location)
this.loading = true
let data = this.root
let data: FileEntry | DirEntry = this.root
const actualDirArr = []
try {
// Navigate to target folder
for (const dirname of location.split('/').slice(1)) {
if (!dirname) continue
if (!("dir" in data)) throw Error("Target folder not available")
actualDirArr.push(dirname)
data = data.dir[dirname]
}
} catch (error) {
console.error("Cannot show requested folder", location, actualDirArr.join('/'), error)
}
if (data.dir === undefined) {
if (!("dir" in data)) {
// Target folder not available
this.document = []
this.loading = false // ???
return
}
this.updateTable(data.dir)
},
async setActualDocumentFile(path: string){
this.loading = true;
const file = await fetchFile(path)
this.document = [file];
this.loading = false;
},
setSelectedDocuments(document: Document[]){
this.selectedDocuments = document
},
deleteDocument(document: Document){
this.document = this.document.filter(e => document.key !== e.key)
this.selectedDocuments = this.selectedDocuments.filter(e => document.key !== e.key)
},
updateUploadingDocuments(key: number, progress: number){
for (const d of this.uploadingDocuments) {
if(d.key === key) d.progress = progress
@ -135,39 +115,6 @@ export const useDocumentStore = defineStore({
deleteUploadingDocument(key: number){
this.uploadingDocuments = this.uploadingDocuments.filter((e)=> e.key !== key)
},
getNextDocumentInRoute(direction: number, path: string){
const locations = path.split('/').slice(1)
locations.pop()
let data = this.root
const actualDirArr = []
// Get data target location
locations.forEach(location => {
// location = decodeURIComponent(location)
if(data && data.dir){
for (const key in data.dir) {
if(key === location) data = data.dir[key]
}
}
})
//Store in a temporary array
for (const key in data.dir) {
actualDirArr.push({
name: key,
content: data.dir[key]
})
}
const actualFileName = decodeURIComponent(this.mainDocument[0].name).split('/').pop()
let index = actualDirArr.findIndex(e => e.name === actualFileName)
if(index < 1 && direction === -1 ){
index = actualDirArr.length -1
}else if(index >= actualDirArr.length - 1 && direction === 1){
index = 0
}else {
index = index + direction
}
return actualDirArr[index].name
},
updateModified() {
for (const d of this.document) {
if ("mtime" in d) d.modified = formatUnixDate(d.mtime)
@ -178,12 +125,6 @@ export const useDocumentStore = defineStore({
mainDocument(): Document[] {
return this.document;
},
rootSize(): number | undefined {
if(this.root) return this.root.size
},
rootMain(): DirectoryData | undefined {
if(this.root) return this.root.dir
},
isUserLogged(): boolean{
return this.user.isLoggedIn
}

View File

@ -7,8 +7,9 @@ export function determineFileType(inputString: string): "file" | "folder" {
}
export function formatSize(size: number) {
if (size === 0) return 'empty'
for (const unit of [null, 'kB', 'MB', 'GB', 'TB', 'PB', 'EB']) {
if (size < 1e5) return size.toLocaleString().replace(',', '\u202F') + (unit ? `\u202F${unit}` : '')
if (size < 1e4) return size.toLocaleString().replace(',', '\u202F') + (unit ? `\u202F${unit}` : '')
size = Math.round(size / 1000)
}
return "huge"

View File

@ -1,5 +1,16 @@
<template>
<FileExplorer></FileExplorer>
<transition
name="slide-fade"
mode="out-in"
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
>
<FileExplorer
:path="Router.currentRoute.value.path"
:documents="documentStore.mainDocument"
/>
</transition>
</template>
<script setup lang="ts">
@ -10,27 +21,35 @@ import FileExplorer from '@/components/FileExplorer.vue';
const documentStore = useDocumentStore()
function isFile(path: string) {
if (path.includes('.') && !path.endsWith('.')) {
return true;
} else {
return false;
}
}
watchEffect(async () => {
const path = new String(Router.currentRoute.value.path) as string
const file = isFile(path)
if(!file){
documentStore.setActualDocument(path.toString())
}else {
documentStore.setActualDocumentFile(path)
}
setTimeout( () => {
documentStore.loading = false
}, 2000)
documentStore.setActualDocument(path.toString())
})
function beforeEnter(el) {
el.style.transform = 'translateX(100%)'
}
function enter(el, done) {
setTimeout(() => {
el.style.transform = 'translateX(0)'
done()
}, 0)
}
function leave(el, done) {
el.style.transform = 'translateX(-100%)'
setTimeout(done, 300) // Assuming 300ms is your transition duration
}
</script>
<style scoped></style>
<style scoped>
.slide-fade-enter-active,
.slide-fade-leave-active {
transition: transform 300ms ease;
}
.slide-fade-enter,
.slide-fade-leave-to /* .slide-fade-leave-active for <2.1.8 */ {
transform: translateX(100%);
}
</style>

View File

@ -3,11 +3,9 @@ import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from "unplugin-vue-components/vite";
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
// @ts-ignore
import pluginRewriteAll from 'vite-plugin-rewrite-all';
import pluginRewriteAll from 'vite-plugin-rewrite-all'
import svgLoader from 'vite-svg-loader'
// Development mode:
// npm run dev # Run frontend that proxies to dev_backend
@ -23,12 +21,7 @@ export default defineConfig({
plugins: [
vue(),
pluginRewriteAll(),
// Ant Design configuration
Components({
resolvers: [
AntDesignVueResolver({ importStyle:"less" })
],
}),
svgLoader(),
],
css: {
preprocessorOptions: {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
@charset "UTF-8";:root{--primary-background: #181818;--secondary-background: #ffffff;--font-color: #333333;--table-background: #535353;--primary-color: #ffffff;--secondary-color: #ccc;--blue-color: #66ffeb;--red-color: #ff4d4f}@media (prefers-color-scheme: dark){:root{--primary-background: #333;--secondary-background: #666;--font-color: #ffffff;--table-background: #535353;--primary-color: #ffffff;--secondary-color: #ccc;--blue-color: #66ffeb;--red-color: #ff4d4f}}body{background-color:var(--primary-background);font-family:Roboto,sans-serif;margin:0}a:link,a:visited,a:active,a:hover{color:var(--primary-color);text-decoration:none}table{border-collapse:collapse;border:0;gap:0}#app{height:100%;display:flex;flex-direction:column;background-color:var(--secondary-background)}.login-container[data-v-b14929a5]{display:flex;justify-content:center;align-items:center;min-height:30vh}.button-login[data-v-b14929a5]{background-color:var(--secondary-color);color:var(--secondary-background)}.ant-btn-primary[data-v-b14929a5]:not(:disabled):hover{background-color:var(--blue-color)}.error-text[data-v-b14929a5]{color:var(--red-color)}.upload-input[data-v-8cbd2944]{display:none}.actions-container,.actions-list{display:flex;flex-wrap:nowrap;gap:15px}.actions-container{justify-content:space-between}.action-button{padding:0;font-size:1.5em;color:var(--secondary-color)}.action-button:hover{color:var(--blue-color)!important}@media only screen and (max-width: 600px){.actions-container,.actions-list{gap:6px}}.margin-input{margin-top:5px}.path{box-shadow:0 0 .5em #00000026;overflow:hidden;white-space:nowrap;width:100%;z-index:1;flex:0 0 1.5rem;order:1;font-size:.9rem;position:relative}nav[data-v-953811b0],span[data-v-953811b0]{color:var(--primary-color)}span[data-v-953811b0]:hover,.last[data-v-953811b0]{color:var(--blue-color)}input#FileRenameInput{color:#8f8;border:0;padding:0;width:90%;outline:none;background:transparent}table{width:100%;table-layout:fixed}table input[type=checkbox]{width:1em;height:1em}table .modified{width:10em}table .size{width:6em}table th,table td{padding:.5em;font-weight:400;text-align:left;white-space:nowrap;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}tbody tr{background:#444;color:#ddd}tbody tr:hover{background:#00f8}.right{text-align:right}.selection{width:2em}.sortcolumn:hover{cursor:pointer}.sortcolumn:hover:after{color:#f80}.sortcolumn{padding-right:1.7em}.sortcolumn:after{content:"▸";color:#888;margin:0 1em 0 .5em;position:absolute;transition:transform .2s linear}.sortactive:after{transform:rotate(90deg);color:#000}main{padding:5px;height:100%}.more-action{display:flex;flex-direction:column;justify-content:start}.action-container{display:flex;align-items:center}.edit-action{min-width:5%}.carousel-container{height:inherit}.name a{text-decoration:none}.file .name:before{content:"📄 ";font-size:1.5em}.folder .name:before{content:"📁 ";font-size:1.5em}.wrapper[data-v-aa2747c4]{background-color:var(--primary-background);padding:.2em .5em;display:flex;flex-direction:column;gap:10px}.page-container[data-v-aa2747c4]{flex-grow:2;padding:0}

View File

@ -1,15 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Vite Vasanko</title>
<script type="module" crossorigin src="/assets/index-0332a49a.js"></script>
<link rel="stylesheet" href="/assets/index-2503e4fd.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
<html lang=en>
<script type="module" crossorigin src="/assets/index-68773a87.js"></script>
<link rel="stylesheet" href="/assets/index-d4bfeeb6.css">
<meta charset=UTF-8>
<title>Cista</title>
<link rel="icon" href="/favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Emoji&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<div id="app"></div>