diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js new file mode 100644 index 00000000..c9775054 --- /dev/null +++ b/frontend/.eslintrc.js @@ -0,0 +1,198 @@ +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint', + sourceType: 'module' + }, + env: { + browser: true, + node: true, + es6: true, + }, + extends: ['plugin:vue/recommended', 'eslint:recommended'], + + // add your custom rules here + //it is base on https://github.com/vuejs/eslint-config-vue + rules: { + "vue/max-attributes-per-line": [2, { + "singleline": 10, + "multiline": { + "max": 1, + "allowFirstLine": false + } + }], + "vue/singleline-html-element-content-newline": "off", + "vue/multiline-html-element-content-newline":"off", + "vue/name-property-casing": ["error", "PascalCase"], + "vue/no-v-html": "off", + 'accessor-pairs': 2, + 'arrow-spacing': [2, { + 'before': true, + 'after': true + }], + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true + }], + 'camelcase': [0, { + 'properties': 'always' + }], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { + 'before': false, + 'after': true + }], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + 'curly': [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + 'eqeqeq': ["error", "always", {"null": "ignore"}], + 'generator-star-spacing': [2, { + 'before': true, + 'after': true + }], + 'handle-callback-err': [2, '^(err|error)$'], + 'indent': [2, 2, { + 'SwitchCase': 1 + }], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true + }], + 'keyword-spacing': [2, { + 'before': true, + 'after': true + }], + 'new-cap': [2, { + 'newIsCap': true, + 'capIsNew': false + }], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [2, { + 'allowLoop': false, + 'allowSwitch': false + }], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [2, { + 'max': 1 + }], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [2, { + 'defaultAssignment': false + }], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [2, { + 'vars': 'all', + 'args': 'none' + }], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [2, { + 'initialized': 'never' + }], + 'operator-linebreak': [2, 'after', { + 'overrides': { + '?': 'before', + ':': 'before' + } + }], + 'padded-blocks': [2, 'never'], + 'quotes': [2, 'single', { + 'avoidEscape': true, + 'allowTemplateLiterals': true + }], + 'semi': [2, 'never'], + 'semi-spacing': [2, { + 'before': false, + 'after': true + }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { + 'words': true, + 'nonwords': false + }], + 'spaced-comment': [2, 'always', { + 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] + }], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + 'yoda': [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': [2, 'always', { + objectsInObjects: false + }], + 'array-bracket-spacing': [2, 'never'] + } +} diff --git a/frontend/src/components/files/Listing.vue b/frontend/src/components/files/Listing.vue index a227cced..44cfd31e 100644 --- a/frontend/src/components/files/Listing.vue +++ b/frontend/src/components/files/Listing.vue @@ -4,41 +4,53 @@ sentiment_dissatisfied {{ $t('files.lonely') }} - + -
+ @dragend="dragEnd" + >
-
+
-

+ :aria-label="$t('files.sortByName')" + @click="sort('name')" + > {{ $t('files.name') }} {{ nameIcon }}

-

+ :aria-label="$t('files.sortBySize')" + @click="sort('size')" + > {{ $t('files.size') }} {{ sizeIcon }}

-

+ :aria-label="$t('files.sortByLastModified')" + @click="sort('modified')" + > {{ $t('files.lastModified') }} {{ modifiedIcon }}

@@ -48,37 +60,39 @@

{{ $t('files.folders') }}

- - + :index="item.index" + :name="item.name" + :is-dir="item.isDir" + :url="item.url" + :modified="item.modified" + :type="item.type" + :size="item.size" + />

{{ $t('files.files') }}

- - + :index="item.index" + :name="item.name" + :is-dir="item.isDir" + :url="item.url" + :modified="item.modified" + :type="item.type" + :size="item.size" + />
- + -
-

{{ $t('files.multipleSelectionEnabled') }}

-
+
+

{{ $t('files.multipleSelectionEnabled') }}

+
clear
@@ -94,28 +108,28 @@ import buttons from '@/utils/buttons' import url from '@/utils/url' export default { - name: 'listing', + name: 'Listing', components: { Item }, - data: function () { + data: function() { return { show: 50 } }, computed: { ...mapState(['req', 'selected', 'user']), - nameSorted () { + nameSorted() { return (this.req.sorting.by === 'name') }, - sizeSorted () { + sizeSorted() { return (this.req.sorting.by === 'size') }, - modifiedSorted () { + modifiedSorted() { return (this.req.sorting.by === 'modified') }, - ascOrdered () { + ascOrdered() { return this.req.sorting.asc }, - items () { + items() { const dirs = [] const files = [] @@ -129,31 +143,31 @@ export default { return { dirs, files } }, - dirs () { + dirs() { return this.items.dirs.slice(0, this.show) }, - files () { + files() { let show = this.show - this.items.dirs.length if (show < 0) show = 0 return this.items.files.slice(0, show) }, - nameIcon () { + nameIcon() { if (this.nameSorted && !this.ascOrdered) { return 'arrow_upward' } return 'arrow_downward' }, - sizeIcon () { + sizeIcon() { if (this.sizeSorted && this.ascOrdered) { return 'arrow_downward' } return 'arrow_upward' }, - modifiedIcon () { + modifiedIcon() { if (this.modifiedSorted && this.ascOrdered) { return 'arrow_downward' } @@ -161,7 +175,7 @@ export default { return 'arrow_upward' } }, - mounted: function () { + mounted: function() { // Check the columns size for the first time. this.resizeEvent() @@ -172,7 +186,7 @@ export default { document.addEventListener('dragover', this.preventDefault) document.addEventListener('drop', this.drop) }, - beforeDestroy () { + beforeDestroy() { // Remove event listeners before destroying this page. window.removeEventListener('keydown', this.keyEvent) window.removeEventListener('resize', this.resizeEvent) @@ -181,16 +195,16 @@ export default { document.removeEventListener('drop', this.drop) }, methods: { - ...mapMutations([ 'updateUser' ]), - base64: function (name) { + ...mapMutations(['updateUser']), + base64: function(name) { return window.btoa(unescape(encodeURIComponent(name))) }, - keyEvent (event) { + keyEvent(event) { if (!event.ctrlKey && !event.metaKey) { return } - let key = String.fromCharCode(event.which).toLowerCase() + const key = String.fromCharCode(event.which).toLowerCase() switch (key) { case 'f': @@ -206,25 +220,25 @@ export default { break } }, - preventDefault (event) { + preventDefault(event) { // Wrapper around prevent default. event.preventDefault() }, - copyCut (event, key) { + copyCut(event, key) { if (event.target.tagName.toLowerCase() === 'input') { return } - let items = [] + const items = [] - for (let i of this.selected) { + for (const i of this.selected) { items.push({ from: this.req.items[i].url, name: encodeURIComponent(this.req.items[i].name) }) } - if (items.length == 0) { + if (items.length === 0) { return } @@ -233,14 +247,14 @@ export default { items: items }) }, - paste (event) { + paste(event) { if (event.target.tagName.toLowerCase() === 'input') { return } - let items = [] + const items = [] - for (let item of this.$store.state.clipboard.items) { + for (const item of this.$store.state.clipboard.items) { const from = item.from.endsWith('/') ? item.from.slice(0, -1) : item.from const to = this.$route.path + item.name items.push({ from, to }) @@ -261,36 +275,36 @@ export default { this.$store.commit('setReload', true) }).catch(this.$showError) }, - resizeEvent () { + resizeEvent() { // Update the columns size based on the window width. let columns = Math.floor(document.querySelector('main').offsetWidth / 300) - let items = css(['#listing.mosaic .item', '.mosaic#listing .item']) + const items = css(['#listing.mosaic .item', '.mosaic#listing .item']) if (columns === 0) columns = 1 items.style.width = `calc(${100 / columns}% - 1em)` }, - scrollEvent () { + scrollEvent() { if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { this.show += 50 } }, - dragEnter () { + dragEnter() { // When the user starts dragging an item, put every // file on the listing with 50% opacity. - let items = document.getElementsByClassName('item') + const items = document.getElementsByClassName('item') Array.from(items).forEach(file => { file.style.opacity = 0.5 }) }, - dragEnd () { + dragEnd() { this.resetOpacity() }, - drop: function (event) { + drop: function(event) { event.preventDefault() this.resetOpacity() - let dt = event.dataTransfer - let files = dt.files + const dt = event.dataTransfer + const files = dt.files let el = event.target if (files.length <= 0) return @@ -318,14 +332,14 @@ export default { this.checkConflict(files, this.req.items, base) }, - checkConflict (files, items, base) { + checkConflict(files, items, base) { if (typeof items === 'undefined' || items === null) { items = [] } let conflict = false for (let i = 0; i < files.length; i++) { - let res = items.findIndex(function hasConflict (element) { + const res = items.findIndex(function hasConflict(element) { return (element.name === this) }, files[i].name) @@ -349,22 +363,22 @@ export default { } }) }, - uploadInput (event) { + uploadInput(event) { this.checkConflict(event.currentTarget.files, this.req.items, '') }, - resetOpacity () { - let items = document.getElementsByClassName('item') + resetOpacity() { + const items = document.getElementsByClassName('item') Array.from(items).forEach(file => { file.style.opacity = 1 }) }, - handleFiles (files, base, overwrite = false) { + handleFiles(files, base, overwrite = false) { buttons.loading('upload') - let promises = [] - let progress = new Array(files.length).fill(0) + const promises = [] + const progress = new Array(files.length).fill(0) - let onupload = (id) => (event) => { + const onupload = (id) => (event) => { progress[id] = (event.loaded / event.total) * 100 let sum = 0 @@ -376,12 +390,12 @@ export default { } for (let i = 0; i < files.length; i++) { - let file = files[i] - let filenameEncoded = url.encodeRFC5987ValueChars(file.name) + const file = files[i] + const filenameEncoded = url.encodeRFC5987ValueChars(file.name) promises.push(api.post(this.$route.path + base + filenameEncoded, file, overwrite, onupload(i))) } - let finish = () => { + const finish = () => { buttons.success('upload') this.$store.commit('setProgress', 0) } @@ -398,7 +412,7 @@ export default { return false }, - async sort (by) { + async sort(by) { let asc = false if (by === 'name') { @@ -416,7 +430,7 @@ export default { } try { - await users.update({ id: this.user.id, sorting: { by, asc } }, ['sorting']) + await users.update({ id: this.user.id, sorting: { by, asc }}, ['sorting']) } catch (e) { this.$showError(e) } diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue index 96aa9dad..b47bef8d 100644 --- a/frontend/src/components/files/ListingItem.vue +++ b/frontend/src/components/files/ListingItem.vue @@ -4,18 +4,18 @@ role="button" tabindex="0" draggable="true" + :data-dir="isDir" + :aria-label="name" + :aria-selected="isSelected" @dragstart="dragStart" @dragover="dragOver" @drop="drop" @click="click" @dblclick="open" @touchstart="touchstart" - :data-dir="isDir" - :aria-label="name" - :aria-selected="isSelected" >
- + {{ icon }}
@@ -34,146 +34,146 @@ diff --git a/frontend/src/components/files/Preview.vue b/frontend/src/components/files/Preview.vue index 714c34fe..aed90522 100644 --- a/frontend/src/components/files/Preview.vue +++ b/frontend/src/components/files/Preview.vue @@ -2,57 +2,57 @@
- - - - + + + +
- - + +