diff --git a/mix-manifest.json b/mix-manifest.json index e68cf9e..027fe9c 100644 --- a/mix-manifest.json +++ b/mix-manifest.json @@ -1,8 +1,8 @@ { "/public/js/spritemap.js": "/public/js/spritemap.js?id=2dda73ecee3bb668b395026efda6524c", - "/public/js/app.js": "/public/js/app.js?id=39ef7cf2ac3e6e0bbe9216057c0c83db", - "/public/js/hub.js": "/public/js/hub.js?id=95df7e59663f51cd22f28582c9816866", - "/public/css/styles.css": "/public/css/styles.css?id=87a9399e6a5ef7045066b025166b8827", + "/public/js/app.js": "/public/js/app.js?id=7dd81b9f69f11ea14b1634ecb4016d68", + "/public/js/hub.js": "/public/js/hub.js?id=f08eb580c27c4f486b8e47cb4dc43a89", + "/public/css/styles.css": "/public/css/styles.css?id=1745381d5fcd3d5c010f916af8e6eec3", "/public/css/demo.html": "/public/css/demo.html?id=a54a5d205e3152fb64b33dda63ffa555", "/public/css/IBMPlexMono-Bold.eot": "/public/css/IBMPlexMono-Bold.eot?id=ef1fadf711db80a00542b202ab14f7ee", "/public/css/IBMPlexMono-Bold.ttf": "/public/css/IBMPlexMono-Bold.ttf?id=e46cace25a93f48a2ec32800717827cb", diff --git a/packages/frontend/icons/back.svg b/packages/frontend/icons/back.svg new file mode 100644 index 0000000..9be967c --- /dev/null +++ b/packages/frontend/icons/back.svg @@ -0,0 +1,5 @@ + + +back + + diff --git a/packages/frontend/icons/checkbox.svg b/packages/frontend/icons/checkbox.svg new file mode 100644 index 0000000..125cbb7 --- /dev/null +++ b/packages/frontend/icons/checkbox.svg @@ -0,0 +1,5 @@ + + +checkbox + + diff --git a/packages/frontend/icons/checkbox_checked.svg b/packages/frontend/icons/checkbox_checked.svg new file mode 100644 index 0000000..30071d2 --- /dev/null +++ b/packages/frontend/icons/checkbox_checked.svg @@ -0,0 +1,5 @@ + + +checkbox_checked + + diff --git a/packages/frontend/js/components/file/files.riot b/packages/frontend/js/components/file/files.riot new file mode 100644 index 0000000..941a947 --- /dev/null +++ b/packages/frontend/js/components/file/files.riot @@ -0,0 +1,90 @@ + + +
+ + + handleParentClick(evnet) } if={ state.path.length > 0 }> + +
+
+ + +
{ handleMarked(event, file) } }> + + +
+ + +
+ { file.name } +
+
{ handleDirectoryClick(event, file) } }> + + { file.name } +
+ + +
+
{ file.size }
+
+ +
+
{ file.updated_at }
+
+ + +
+
+ + +
+
+ +
+
+
+ + + +
\ No newline at end of file diff --git a/packages/frontend/js/components/file/index.riot b/packages/frontend/js/components/file/index.riot index cd8ced3..1f5918a 100644 --- a/packages/frontend/js/components/file/index.riot +++ b/packages/frontend/js/components/file/index.riot @@ -1,18 +1,25 @@ -
+
+ \ No newline at end of file diff --git a/packages/frontend/js/components/file/video.riot b/packages/frontend/js/components/file/video.riot new file mode 100644 index 0000000..d6d7824 --- /dev/null +++ b/packages/frontend/js/components/file/video.riot @@ -0,0 +1,65 @@ + + +
+ + + handleParentClick(evnet) } if={ state.path.length > 0 }> + +
+
+ + +
+ { file.name } +
+
{ handleDirectoryClick(event, file) } }> + + { file.name } +
+ + +
+
{ file.size }
+
+ +
+
{ file.updated_at }
+
+ + +
+
+ + +
+
+ +
+
+
+ + + +
\ No newline at end of file diff --git a/packages/frontend/js/hub.js b/packages/frontend/js/hub.js index 847b647..729d21d 100644 --- a/packages/frontend/js/hub.js +++ b/packages/frontend/js/hub.js @@ -3,10 +3,14 @@ import * as riot from 'riot' import TinyNotification from '@tiny-components/notification/src/notification.riot' riot.register('tiny-notification', TinyNotification) +import AppFileParent from './components/file/parent.riot' import AppFileIndex from './components/file/index.riot' +import AppFileFiles from './components/file/files.riot' // register components riot.register('app-file-index', AppFileIndex) +riot.register('app-file-parent', AppFileParent) +riot.register('app-file-files', AppFileFiles) // mount components riot.mount('app-file-index') \ No newline at end of file diff --git a/packages/frontend/js/mixins/file.js b/packages/frontend/js/mixins/file.js new file mode 100644 index 0000000..5875162 --- /dev/null +++ b/packages/frontend/js/mixins/file.js @@ -0,0 +1,99 @@ +import fileStore from './../stores/file.js' + +/** + * Mixin to Extend a Sidebar + * + * @author Björn Hase + * @license http://opensource.org/licenses/MIT The MIT License + * @link https://gitea.node001.net/tiny-components/sidebar-form + * + */ + +export default { + + state: { + files: [], + path: [], + marked: [] + }, + + onMounted() { + fileStore.on('update', (data) => { + this.state.files = data + this.update() + }) + + fileStore.get(this.props.hubId) + }, + + /** + * + * + * + */ + handleParentClick(event) { + this.state.path.pop() + fileStore.get(this.props.hubId, this.state.path) + }, + + /** + * + * + * + * + */ + handleMarked(event, file) { + + let exists = this.isFileInArray(file) + + if (exists === false) { + this.state.marked.push(file) + } else { + this.state.marked.splice(this.state.marked.indexOf(file), 1) + } + + this.update() + }, + + /** + * + * @return {Boolean} [description] + */ + isFileInArray(file) + { + let exists = false + + this.state.marked.forEach((f, index) => { + if (file.name === f.name) { + exists = true + } + }) + + return exists + }, + + handleDirectoryClick(event, file) { + this.state.path.push(file.name) + fileStore.get(this.props.hubId, this.state.path) + }, + + /** + * + * @param {[type]} event [description] + * @param {[type]} file [description] + * @return {[type]} [description] + */ + handleDownload(event, file) { + + }, + + /** + * + * @param {[type]} event [description] + * @param {[type]} file [description] + * @return {[type]} [description] + */ + handleDelete(event, file) { + + } +} \ No newline at end of file diff --git a/packages/frontend/js/stores/file.js b/packages/frontend/js/stores/file.js index 0de5747..075325b 100644 --- a/packages/frontend/js/stores/file.js +++ b/packages/frontend/js/stores/file.js @@ -20,9 +20,17 @@ * @param {object} data * */ - get(id) + get(id, path) { - fetch('/api/files/v1/' + id) + let url = '/api/files/v1/' + id + + if (path && path.length > 0) { + url += '?' + new URLSearchParams({ + 'path': path.join('/') + }) + } + + fetch(url) .then((response) => response.json()) .then((response) => { this.trigger('update', response.data) diff --git a/packages/frontend/scss/components/_file.scss b/packages/frontend/scss/components/_file.scss new file mode 100644 index 0000000..299d8b7 --- /dev/null +++ b/packages/frontend/scss/components/_file.scss @@ -0,0 +1,98 @@ +/** + * + * + * + */ + +$file__color-hover: #e3e3e3; + +.file { + + // table to show files + &__table { + display: block; + width: 100%; + + &-row { + display: flex; + flex-wrap: wrap; + + padding: 0.25em; + border-bottom: $border; + + &:hover { + background-color: $file__color-hover; + } + + &--selected { + background-color: #02acff; + + &:hover { + background-color: darken(#02acff, 10%); + } + } + } + + &-column { + display: flex; + flex: 2; + align-items: center; + + padding: 5px; + + &--select { + max-width: 30px; + + input[type=checkbox] { + position: relative; + display: none; + + + label { + margin: -4px 0 0 0; + + .checked { + display: none; + } + + &:hover { + cursor: pointer; + } + } + + &:checked + label .checked { + display: inline-block; + } + + &:checked + label .unchecked { + display: none; + } + } + + .checked, .unchecked { + vertical-align: bottom; + } + } + + &--back { + padding: 8px 2px; + } + + &--actions { + line-height: 0; + + button { + &:disabled { + .icon { + opacity: 0.3; + + &:hover { + cursor: not-allowed; + } + } + } + } + } + } + } + +} \ No newline at end of file diff --git a/packages/frontend/scss/styles.scss b/packages/frontend/scss/styles.scss index 05b5d64..7f303df 100644 --- a/packages/frontend/scss/styles.scss +++ b/packages/frontend/scss/styles.scss @@ -1,6 +1,7 @@ @import '@tiny-components/plain-ui/src/scss/plain-ui', - + 'components/field-error', + 'components/file', 'components/breadcrumb'; \ No newline at end of file diff --git a/packages/frontend/webpack.mix.js b/packages/frontend/webpack.mix.js index 3e98265..7b436a2 100644 --- a/packages/frontend/webpack.mix.js +++ b/packages/frontend/webpack.mix.js @@ -31,7 +31,10 @@ mix.webpackConfig({ } ]}, plugins: [ - new SvgSpritemapPlugin('./node_modules/@tiny-components/plain-ui/src/icons/mono-icons/svg/*.svg', { + new SvgSpritemapPlugin([ + './node_modules/@tiny-components/plain-ui/src/icons/mono-icons/svg/*.svg', + './icons/*.svg' + ], { output: { filename: 'public/symbol-defs.svg', chunk: { diff --git a/packages/server/package-lock.json b/packages/server/package-lock.json index 3d10f4a..e1457d1 100644 --- a/packages/server/package-lock.json +++ b/packages/server/package-lock.json @@ -190,6 +190,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "dayjs": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", + "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", diff --git a/packages/server/package.json b/packages/server/package.json index afb8a98..4ad3cab 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -9,6 +9,7 @@ "dependencies": { "@fastify/static": "^6.4.0", "@fastify/view": "^7.0.0", + "dayjs": "^1.11.3", "dotenv": "^16.0.1", "fastify": "^4.0.1", "fastify-formbody": "^5.3.0", diff --git a/packages/server/store/file.js b/packages/server/store/file.js index 7270954..4d0bc6e 100644 --- a/packages/server/store/file.js +++ b/packages/server/store/file.js @@ -1,4 +1,5 @@ -import { readdir } from 'fs/promises' +import { readdir, stat } from 'fs/promises' +import dayjs from 'dayjs' /** * getting files @@ -33,6 +34,8 @@ class File { errors: false } + const files = [] + try { const files = await readdir(this.path, { withFileTypes: true @@ -40,18 +43,53 @@ class File { // run through all files, add options for (const file of files) { + + // getting meta + const meta = await stat(this.path + '/' + file.name) + result['files'].push({ name: file.name, - isDirectory: file.isDirectory() + is_directory: file.isDirectory(), + size: this.formatBytes(meta.size), + created_at: dayjs(meta.ctime).format('DD.MM.YYYY HH:mm'), + updated_at: dayjs(meta.mtime).format('DD.MM.YYYY HH:mm') }) } + + result['files'].sort(function(a, b) { + if (a.is_directory) { + return -1 + } else { + return 0 + } + }) } catch (error) { - result['errors'] = error + result['error'] = error } return result } + /** + * getting size of file + * + * @param float size + * @param integer precision + * @return string + */ + formatBytes(size) { + + if (size === 0) { + return '0 bytes' + } + + // getting base of size + const base = Math.log(size) / Math.log(1024); + const suffixes = ['Bytes', 'KB', 'MB', 'G', 'T'] + + return Math.round(Math.pow(1024, base - Math.floor(base))) + ' ' + suffixes[Math.floor(base)] + } + } export default File \ No newline at end of file diff --git a/public/css/styles.css b/public/css/styles.css index 5a65ac0..56ae0b6 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -14801,6 +14801,74 @@ svg.field-choice__checked { padding: 0 0 0 1em; } +/** + * + * + * + */ +.file__table { + display: block; + width: 100%; +} +.file__table-row { + display: flex; + flex-wrap: wrap; + padding: 0.25em; + border-bottom: 1px solid var(--border); +} +.file__table-row:hover { + background-color: #e3e3e3; +} +.file__table-row--selected { + background-color: #02acff; +} +.file__table-row--selected:hover { + background-color: #008ace; +} +.file__table-column { + display: flex; + flex: 2; + align-items: center; + padding: 5px; +} +.file__table-column--select { + max-width: 30px; +} +.file__table-column--select input[type=checkbox] { + position: relative; + display: none; +} +.file__table-column--select input[type=checkbox] + label { + margin: -4px 0 0 0; +} +.file__table-column--select input[type=checkbox] + label .checked { + display: none; +} +.file__table-column--select input[type=checkbox] + label:hover { + cursor: pointer; +} +.file__table-column--select input[type=checkbox]:checked + label .checked { + display: inline-block; +} +.file__table-column--select input[type=checkbox]:checked + label .unchecked { + display: none; +} +.file__table-column--select .checked, .file__table-column--select .unchecked { + vertical-align: bottom; +} +.file__table-column--back { + padding: 8px 2px; +} +.file__table-column--actions { + line-height: 0; +} +.file__table-column--actions button:disabled .icon { + opacity: 0.3; +} +.file__table-column--actions button:disabled .icon:hover { + cursor: not-allowed; +} + .breadcrumb ul { list-style: none; display: flex; diff --git a/public/js/app.js b/public/js/app.js index 48bbf3a..c7a630a 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -146,11 +146,11 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '', + '', [ { - redundantAttribute: 'expr18', - selector: '[expr18]', + redundantAttribute: 'expr6', + selector: '[expr6]', expressions: [ { @@ -355,7 +355,7 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid bindingTypes, getComponent ) => template( - '', + '', [ { type: bindingTypes.TAG, @@ -365,14 +365,14 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid slots: [ { id: 'title', - html: '', + html: '', bindings: [ { type: bindingTypes.IF, evaluate: _scope => _scope.state.current._id, - redundantAttribute: 'expr7', - selector: '[expr7]', + redundantAttribute: 'expr8', + selector: '[expr8]', template: template( null, @@ -415,8 +415,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid { type: bindingTypes.IF, evaluate: _scope => !_scope.state.current._id, - redundantAttribute: 'expr8', - selector: '[expr8]', + redundantAttribute: 'expr9', + selector: '[expr9]', template: template( null, @@ -443,12 +443,12 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid }, { id: 'form', - html: '
', + html: '
', bindings: [ { - redundantAttribute: 'expr9', - selector: '[expr9]', + redundantAttribute: 'expr10', + selector: '[expr10]', expressions: [ { @@ -461,8 +461,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid { type: bindingTypes.IF, evaluate: _scope => _scope.state.current._id, - redundantAttribute: 'expr10', - selector: '[expr10]', + redundantAttribute: 'expr11', + selector: '[expr11]', template: template( null, @@ -482,8 +482,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid { type: bindingTypes.IF, evaluate: _scope => _scope.state.current._rev, - redundantAttribute: 'expr11', - selector: '[expr11]', + redundantAttribute: 'expr12', + selector: '[expr12]', template: template( null, @@ -501,8 +501,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid ) }, { - redundantAttribute: 'expr12', - selector: '[expr12]', + redundantAttribute: 'expr13', + selector: '[expr13]', expressions: [ { @@ -517,12 +517,12 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid evaluate: _scope => 'field-error', slots: [], attributes: [], - redundantAttribute: 'expr13', - selector: '[expr13]' + redundantAttribute: 'expr14', + selector: '[expr14]' }, { - redundantAttribute: 'expr14', - selector: '[expr14]', + redundantAttribute: 'expr15', + selector: '[expr15]', expressions: [ { @@ -537,12 +537,12 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid evaluate: _scope => 'field-error', slots: [], attributes: [], - redundantAttribute: 'expr15', - selector: '[expr15]' + redundantAttribute: 'expr16', + selector: '[expr16]' }, { - redundantAttribute: 'expr16', - selector: '[expr16]', + redundantAttribute: 'expr17', + selector: '[expr17]', expressions: [ { @@ -558,8 +558,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid evaluate: _scope => 'field-error', slots: [], attributes: [], - redundantAttribute: 'expr17', - selector: '[expr17]' + redundantAttribute: 'expr18', + selector: '[expr18]' } ] } @@ -583,8 +583,8 @@ riot__WEBPACK_IMPORTED_MODULE_5__.register('field-error', _tiny_components_valid } ], - redundantAttribute: 'expr6', - selector: '[expr6]' + redundantAttribute: 'expr7', + selector: '[expr7]' } ] ), @@ -755,13 +755,13 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '
', + '
', [ { type: bindingTypes.IF, evaluate: _scope => _scope.props.active, - redundantAttribute: 'expr33', - selector: '[expr33]', + redundantAttribute: 'expr47', + selector: '[expr47]', template: template( '
', @@ -909,16 +909,16 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '
', + '
', [ { type: bindingTypes.IF, evaluate: _scope => _scope.state.items.length > 0, - redundantAttribute: 'expr28', - selector: '[expr28]', + redundantAttribute: 'expr35', + selector: '[expr35]', template: template( - '
', + '
', [ { expressions: [ @@ -941,7 +941,7 @@ __webpack_require__.r(__webpack_exports__); condition: null, template: template( - '
', + '
', [ { expressions: [ @@ -963,8 +963,8 @@ __webpack_require__.r(__webpack_exports__); ] }, { - redundantAttribute: 'expr30', - selector: '[expr30]', + redundantAttribute: 'expr37', + selector: '[expr37]', expressions: [ { @@ -982,8 +982,8 @@ __webpack_require__.r(__webpack_exports__); ] ), - redundantAttribute: 'expr29', - selector: '[expr29]', + redundantAttribute: 'expr36', + selector: '[expr36]', itemName: 'item', indexName: null, evaluate: _scope => _scope.state.items @@ -1055,11 +1055,11 @@ riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-loading', _tiny_components_load bindingTypes, getComponent ) => template( - '
', + '
', [ { - redundantAttribute: 'expr19', - selector: '[expr19]', + redundantAttribute: 'expr38', + selector: '[expr38]', expressions: [ { @@ -1073,12 +1073,12 @@ riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-loading', _tiny_components_load type: bindingTypes.SLOT, attributes: [], name: 'title', - redundantAttribute: 'expr20', - selector: '[expr20]' + redundantAttribute: 'expr39', + selector: '[expr39]' }, { - redundantAttribute: 'expr21', - selector: '[expr21]', + redundantAttribute: 'expr40', + selector: '[expr40]', expressions: [ { @@ -1092,8 +1092,8 @@ riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-loading', _tiny_components_load type: bindingTypes.SLOT, attributes: [], name: 'form', - redundantAttribute: 'expr22', - selector: '[expr22]' + redundantAttribute: 'expr41', + selector: '[expr41]' }, { type: bindingTypes.TAG, @@ -1109,12 +1109,12 @@ riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-loading', _tiny_components_load } ], - redundantAttribute: 'expr23', - selector: '[expr23]' + redundantAttribute: 'expr42', + selector: '[expr42]' }, { - redundantAttribute: 'expr24', - selector: '[expr24]', + redundantAttribute: 'expr43', + selector: '[expr43]', expressions: [ { @@ -1130,8 +1130,8 @@ riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-loading', _tiny_components_load ] }, { - redundantAttribute: 'expr25', - selector: '[expr25]', + redundantAttribute: 'expr44', + selector: '[expr44]', expressions: [ { @@ -1276,16 +1276,16 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '
', + '
', [ { type: bindingTypes.IF, evaluate: _scope => _scope.state.errors.length > 0, - redundantAttribute: 'expr31', - selector: '[expr31]', + redundantAttribute: 'expr45', + selector: '[expr45]', template: template( - '
', + '
', [ { type: bindingTypes.EACH, @@ -1312,8 +1312,8 @@ __webpack_require__.r(__webpack_exports__); ] ), - redundantAttribute: 'expr32', - selector: '[expr32]', + redundantAttribute: 'expr46', + selector: '[expr46]', itemName: 'error', indexName: null, evaluate: _scope => _scope.state.errors diff --git a/public/js/hub.js b/public/js/hub.js index 62f10b1..143fa77 100644 --- a/public/js/hub.js +++ b/public/js/hub.js @@ -93,9 +93,9 @@ const observable = function(el) { // eslint-disable-line /***/ }), -/***/ "./js/components/file/index.riot": +/***/ "./js/components/file/files.riot": /*!***************************************!*\ - !*** ./js/components/file/index.riot ***! + !*** ./js/components/file/files.riot ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { @@ -104,26 +104,30 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); -/* harmony import */ var _stores_file_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../../stores/file.js */ "./js/stores/file.js"); +/* harmony import */ var _mixins_file_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../../mixins/file.js */ "./js/mixins/file.js"); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ css: null, - exports: { - state: { - files: [] - }, + exports: () => { + return { - onMounted() - { - _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].on('update', (data) => { - this.state.files = data - this.update() - }) + ..._mixins_file_js__WEBPACK_IMPORTED_MODULE_0__["default"], // adding basic funtion for sidebar - _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].get(this.props.hubId) - } + rowClasses(file) { + const classes = [ + 'file__table-row' + ] + + if (this.isFileInArray(file)) { + classes.push('file__table-row--selected') + } + + return classes.join(' ') + } + + } }, template: ( @@ -132,61 +136,467 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '
', + '
', [ + { + type: bindingTypes.IF, + evaluate: _scope => _scope.state.path.length > 0, + redundantAttribute: 'expr24', + selector: '[expr24]', + + template: template( + null, + [ + { + type: bindingTypes.TAG, + getComponent: getComponent, + evaluate: _scope => 'app-file-parent', + slots: [], + + attributes: [ + { + type: expressionTypes.ATTRIBUTE, + name: 'handleClick', + evaluate: _scope => (event) => _scope.handleParentClick(_scope.evnet) + } + ] + } + ] + ) + }, { type: bindingTypes.EACH, getKey: null, condition: null, template: template( - ' ', + '
', [ + { + expressions: [ + { + type: expressionTypes.ATTRIBUTE, + name: 'class', + evaluate: _scope => _scope.rowClasses(_scope.file) + } + ] + }, + { + redundantAttribute: 'expr26', + selector: '[expr26]', + + expressions: [ + { + type: expressionTypes.EVENT, + name: 'onchange', + evaluate: _scope => (event) => { _scope.handleMarked(event, _scope.file) } + } + ] + }, { redundantAttribute: 'expr27', selector: '[expr27]', expressions: [ { - type: expressionTypes.TEXT, - childNodeIndex: 0, + type: expressionTypes.ATTRIBUTE, + name: 'id', evaluate: _scope => [ - _scope.file.name + 'marked_', + _scope.index ].join( '' ) - }, + } + ] + }, + { + redundantAttribute: 'expr28', + selector: '[expr28]', + + expressions: [ { type: expressionTypes.ATTRIBUTE, - name: 'href', + name: 'for', evaluate: _scope => [ - '/file/', - _scope.file.name + 'marked_', + _scope.index ].join( '' ) } ] + }, + { + type: bindingTypes.IF, + evaluate: _scope => !_scope.file.is_directory, + redundantAttribute: 'expr29', + selector: '[expr29]', + + template: template( + ' ', + [ + { + expressions: [ + { + type: expressionTypes.TEXT, + childNodeIndex: 0, + + evaluate: _scope => [ + _scope.file.name + ].join( + '' + ) + } + ] + } + ] + ) + }, + { + type: bindingTypes.IF, + evaluate: _scope => _scope.file.is_directory, + redundantAttribute: 'expr30', + selector: '[expr30]', + + template: template( + ' ', + [ + { + expressions: [ + { + type: expressionTypes.TEXT, + childNodeIndex: 1, + + evaluate: _scope => [ + _scope.file.name + ].join( + '' + ) + }, + { + type: expressionTypes.EVENT, + name: 'onclick', + evaluate: _scope => (event) => { _scope.handleDirectoryClick(event, _scope.file) } + } + ] + } + ] + ) + }, + { + type: bindingTypes.IF, + evaluate: _scope => !_scope.file.is_directory, + redundantAttribute: 'expr31', + selector: '[expr31]', + + template: template( + ' ', + [ + { + expressions: [ + { + type: expressionTypes.TEXT, + childNodeIndex: 0, + evaluate: _scope => _scope.file.size + } + ] + } + ] + ) + }, + { + redundantAttribute: 'expr32', + selector: '[expr32]', + + expressions: [ + { + type: expressionTypes.TEXT, + childNodeIndex: 0, + evaluate: _scope => _scope.file.updated_at + } + ] + }, + { + redundantAttribute: 'expr33', + selector: '[expr33]', + + expressions: [ + { + type: expressionTypes.EVENT, + name: 'onclick', + evaluate: _scope => (event) => { _scope.handleDownload(event, _scope.file) } + } + ] + }, + { + redundantAttribute: 'expr34', + selector: '[expr34]', + + expressions: [ + { + type: expressionTypes.EVENT, + name: 'onclick', + evaluate: _scope => (event) => { _scope.handleDelete(event, _scope.file) } + } + ] } ] ), - redundantAttribute: 'expr26', - selector: '[expr26]', + redundantAttribute: 'expr25', + selector: '[expr25]', itemName: 'file', - indexName: null, + indexName: 'index', evaluate: _scope => _scope.state.files } ] ), + name: 'app-file-files' +}); + +/***/ }), + +/***/ "./js/components/file/index.riot": +/*!***************************************!*\ + !*** ./js/components/file/index.riot ***! + \***************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ + css: null, + + exports: { + state: { + view: 'files', + types: [ + 'files', + 'audio', + 'video', + 'image', + 'document' + ] + }, + + /** + * add selected-class if type match + * + * @param {string} type + * @return {string} + * + */ + tabClasses(type) { + const classes = [ + 'tabs__item' + ] + + if (type === this.state.view) { + classes.push('tabs__item--selected') + } + + return classes.join(' ') + }, + + /** + * change type + * + * @param {object} event + * @param {string} type + * @return {string} + * + */ + handleTabClick(event, type) { + this.state.view = type + this.update() + } + }, + + template: ( + template, + expressionTypes, + bindingTypes, + getComponent + ) => template( + '
', + [ + { + type: bindingTypes.EACH, + getKey: null, + condition: null, + + template: template( + ' ', + [ + { + expressions: [ + { + type: expressionTypes.TEXT, + childNodeIndex: 0, + + evaluate: _scope => [ + _scope.type + ].join( + '' + ) + }, + { + type: expressionTypes.ATTRIBUTE, + name: 'class', + evaluate: _scope => _scope.tabClasses(_scope.type) + }, + { + type: expressionTypes.EVENT, + name: 'onclick', + evaluate: _scope => (event) => { _scope.handleTabClick(event, _scope.type) } + } + ] + } + ] + ), + + redundantAttribute: 'expr20', + selector: '[expr20]', + itemName: 'type', + indexName: null, + evaluate: _scope => _scope.state.types + }, + { + type: bindingTypes.IF, + evaluate: _scope => _scope.state.view === 'files', + redundantAttribute: 'expr21', + selector: '[expr21]', + + template: template( + null, + [ + { + type: bindingTypes.TAG, + getComponent: getComponent, + evaluate: _scope => 'app-file-files', + slots: [], + + attributes: [ + { + type: expressionTypes.ATTRIBUTE, + name: 'hub-id', + evaluate: _scope => _scope.props.hubId + } + ] + } + ] + ) + }, + { + type: bindingTypes.IF, + evaluate: _scope => _scope.state.view === 'video', + redundantAttribute: 'expr22', + selector: '[expr22]', + + template: template( + null, + [ + { + type: bindingTypes.TAG, + getComponent: getComponent, + evaluate: _scope => 'app-file-audio', + slots: [], + + attributes: [ + { + type: expressionTypes.ATTRIBUTE, + name: 'hub-id', + evaluate: _scope => _scope.props.hubId + } + ] + } + ] + ) + }, + { + type: bindingTypes.IF, + evaluate: _scope => _scope.state.view === 'audio', + redundantAttribute: 'expr23', + selector: '[expr23]', + + template: template( + null, + [ + { + type: bindingTypes.TAG, + getComponent: getComponent, + evaluate: _scope => 'app-file-video', + slots: [], + + attributes: [ + { + type: expressionTypes.ATTRIBUTE, + name: 'hub-id', + evaluate: _scope => _scope.props.hubId + } + ] + } + ] + ) + } + ] + ), + name: 'app-file-index' }); /***/ }), +/***/ "./js/components/file/parent.riot": +/*!****************************************!*\ + !*** ./js/components/file/parent.riot ***! + \****************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ + css: null, + exports: {}, + + template: ( + template, + expressionTypes, + bindingTypes, + getComponent + ) => template( + '
', + [ + { + redundantAttribute: 'expr19', + selector: '[expr19]', + + expressions: [ + { + type: expressionTypes.EVENT, + name: 'onclick', + evaluate: _scope => (event) => { _scope.props.handleClick(event, _scope) } + } + ] + } + ] + ), + + name: 'app-file-parent' +}); + +/***/ }), + /***/ "./node_modules/@tiny-components/notification/src/notification.riot": /*!**************************************************************************!*\ !*** ./node_modules/@tiny-components/notification/src/notification.riot ***! @@ -320,16 +730,16 @@ __webpack_require__.r(__webpack_exports__); bindingTypes, getComponent ) => template( - '
', + '
', [ { type: bindingTypes.IF, evaluate: _scope => _scope.state.items.length > 0, - redundantAttribute: 'expr28', - selector: '[expr28]', + redundantAttribute: 'expr35', + selector: '[expr35]', template: template( - '
', + '
', [ { expressions: [ @@ -352,7 +762,7 @@ __webpack_require__.r(__webpack_exports__); condition: null, template: template( - '
', + '
', [ { expressions: [ @@ -374,8 +784,8 @@ __webpack_require__.r(__webpack_exports__); ] }, { - redundantAttribute: 'expr30', - selector: '[expr30]', + redundantAttribute: 'expr37', + selector: '[expr37]', expressions: [ { @@ -393,8 +803,8 @@ __webpack_require__.r(__webpack_exports__); ] ), - redundantAttribute: 'expr29', - selector: '[expr29]', + redundantAttribute: 'expr36', + selector: '[expr36]', itemName: 'item', indexName: null, evaluate: _scope => _scope.state.items @@ -478,6 +888,110 @@ __webpack_require__.r(__webpack_exports__); /***/ }), +/***/ "./js/mixins/file.js": +/*!***************************!*\ + !*** ./js/mixins/file.js ***! + \***************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _stores_file_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./../stores/file.js */ "./js/stores/file.js"); + +/** + * Mixin to Extend a Sidebar + * + * @author Björn Hase + * @license http://opensource.org/licenses/MIT The MIT License + * @link https://gitea.node001.net/tiny-components/sidebar-form + * + */ + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ + state: { + files: [], + path: [], + marked: [] + }, + onMounted: function onMounted() { + var _this = this; + + _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].on('update', function (data) { + _this.state.files = data; + + _this.update(); + }); + _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].get(this.props.hubId); + }, + + /** + * + * + * + */ + handleParentClick: function handleParentClick(event) { + this.state.path.pop(); + _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].get(this.props.hubId, this.state.path); + }, + + /** + * + * + * + * + */ + handleMarked: function handleMarked(event, file) { + var exists = this.isFileInArray(file); + + if (exists === false) { + this.state.marked.push(file); + } else { + this.state.marked.splice(this.state.marked.indexOf(file), 1); + } + + this.update(); + }, + + /** + * + * @return {Boolean} [description] + */ + isFileInArray: function isFileInArray(file) { + var exists = false; + this.state.marked.forEach(function (f, index) { + if (file.name === f.name) { + exists = true; + } + }); + return exists; + }, + handleDirectoryClick: function handleDirectoryClick(event, file) { + this.state.path.push(file.name); + _stores_file_js__WEBPACK_IMPORTED_MODULE_0__["default"].get(this.props.hubId, this.state.path); + }, + + /** + * + * @param {[type]} event [description] + * @param {[type]} file [description] + * @return {[type]} [description] + */ + handleDownload: function handleDownload(event, file) {}, + + /** + * + * @param {[type]} event [description] + * @param {[type]} file [description] + * @return {[type]} [description] + */ + handleDelete: function handleDelete(event, file) {} +}); + +/***/ }), + /***/ "./js/stores/file.js": /*!***************************!*\ !*** ./js/stores/file.js ***! @@ -511,10 +1025,18 @@ __webpack_require__.r(__webpack_exports__); * @param {object} data * */ - get: function get(id) { + get: function get(id, path) { var _this = this; - fetch('/api/files/v1/' + id).then(function (response) { + var url = '/api/files/v1/' + id; + + if (path && path.length > 0) { + url += '?' + new URLSearchParams({ + 'path': path.join('/') + }); + } + + fetch(url).then(function (response) { return response.json(); }).then(function (response) { _this.trigger('update', response.data); @@ -3289,13 +3811,19 @@ var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); /* harmony import */ var riot__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! riot */ "./node_modules/riot/riot.esm.js"); /* harmony import */ var _tiny_components_notification_src_notification_riot__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tiny-components/notification/src/notification.riot */ "./node_modules/@tiny-components/notification/src/notification.riot"); -/* harmony import */ var _components_file_index_riot__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/file/index.riot */ "./js/components/file/index.riot"); +/* harmony import */ var _components_file_parent_riot__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/file/parent.riot */ "./js/components/file/parent.riot"); +/* harmony import */ var _components_file_index_riot__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/file/index.riot */ "./js/components/file/index.riot"); +/* harmony import */ var _components_file_files_riot__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/file/files.riot */ "./js/components/file/files.riot"); riot__WEBPACK_IMPORTED_MODULE_1__.register('tiny-notification', _tiny_components_notification_src_notification_riot__WEBPACK_IMPORTED_MODULE_0__["default"]); + + // register components -riot__WEBPACK_IMPORTED_MODULE_1__.register('app-file-index', _components_file_index_riot__WEBPACK_IMPORTED_MODULE_2__["default"]); // mount components +riot__WEBPACK_IMPORTED_MODULE_1__.register('app-file-index', _components_file_index_riot__WEBPACK_IMPORTED_MODULE_3__["default"]); +riot__WEBPACK_IMPORTED_MODULE_1__.register('app-file-parent', _components_file_parent_riot__WEBPACK_IMPORTED_MODULE_2__["default"]); +riot__WEBPACK_IMPORTED_MODULE_1__.register('app-file-files', _components_file_files_riot__WEBPACK_IMPORTED_MODULE_4__["default"]); // mount components riot__WEBPACK_IMPORTED_MODULE_1__.mount('app-file-index'); })(); diff --git a/public/symbol-defs.svg b/public/symbol-defs.svg index 250cd5e..b05daad 100644 --- a/public/symbol-defs.svg +++ b/public/symbol-defs.svg @@ -1 +1 @@ -addarchivearrow-downarrow-left-downarrow-left-uparrow-leftarrow-right-downarrow-right-uparrow-rightarrow-upattachmentbackspacebanbar-chart-altbar-chartboardboldbookbookmarkcalendarcallcameracaret-downcaret-leftcaret-rightcaret-upcheckcheckbox-checkedcheckboxchevron-double-downchevron-double-leftchevron-double-rightchevron-double-upchevron-downchevron-leftchevron-rightchevron-upcircle-addcircle-arrow-downcircle-arrow-leftcircle-arrow-rightcircle-arrow-upcircle-checkcircle-errorcircle-helpcircle-informationcircle-removecircle-warningcircleclipboard-checkclipboard-listclipboardclockclosecloud-downloadcloud-uploadcloudcloudycommentcompasscomputercopycredit-carddatabasedelete-altdeletedocument-adddocument-checkdocument-downloaddocument-emptydocument-removedocumentdownloaddragdropedit-alteditemailenterexpandexportexternal-linkeye-offeyefavoritefilter-1filter-altfilterflagfogfolder-addfolder-checkfolder-downloadfolder-removefoldergridhearthomeimageinboxitaliclaptoplayerslayoutlink-altlinklistlocationlocklog-inlog-outmapmegaphonemenumessage-altmessageminimizemobilemoonnextnotification-offnotificationoptions-horizontaloptions-verticalpausepenpercentagepinplaypreviousprintrainrefreshremovereorder-altreorderrepeatsavesearchselectsendsettingsshareshopping-cart-addshopping-cartshufflesnowsnowflakesortspeakersstopstormstrikethroughsunsunrise-altsunrisesunsetswitchtabletablettagtemperaturetextthree-rowstwo-columnstwo-rowsunderlineundounlockuser-adduser-checkuser-removeuserusersvolume-offvolume-upwarningwebcamwindwindowzoom-inzoom-out \ No newline at end of file +addarchivearrow-downarrow-left-downarrow-left-uparrow-leftarrow-right-downarrow-right-uparrow-rightarrow-upattachmentbackspacebanbar-chart-altbar-chartboardboldbookbookmarkcalendarcallcameracaret-downcaret-leftcaret-rightcaret-upcheckcheckbox-checkedcheckboxchevron-double-downchevron-double-leftchevron-double-rightchevron-double-upchevron-downchevron-leftchevron-rightchevron-upcircle-addcircle-arrow-downcircle-arrow-leftcircle-arrow-rightcircle-arrow-upcircle-checkcircle-errorcircle-helpcircle-informationcircle-removecircle-warningcircleclipboard-checkclipboard-listclipboardclockclosecloud-downloadcloud-uploadcloudcloudycommentcompasscomputercopycredit-carddatabasedelete-altdeletedocument-adddocument-checkdocument-downloaddocument-emptydocument-removedocumentdownloaddragdropedit-alteditemailenterexpandexportexternal-linkeye-offeyefavoritefilter-1filter-altfilterflagfogfolder-addfolder-checkfolder-downloadfolder-removefoldergridhearthomeimageinboxitaliclaptoplayerslayoutlink-altlinklistlocationlocklog-inlog-outmapmegaphonemenumessage-altmessageminimizemobilemoonnextnotification-offnotificationoptions-horizontaloptions-verticalpausepenpercentagepinplaypreviousprintrainrefreshremovereorder-altreorderrepeatsavesearchselectsendsettingsshareshopping-cart-addshopping-cartshufflesnowsnowflakesortspeakersstopstormstrikethroughsunsunrise-altsunrisesunsetswitchtabletablettagtemperaturetextthree-rowstwo-columnstwo-rowsunderlineundounlockuser-adduser-checkuser-removeuserusersvolume-offvolume-upwarningwebcamwindwindowzoom-inzoom-outbackcheckbox_checkedcheckbox \ No newline at end of file