diff options
| -rw-r--r-- | .quasar/entry.js | 10 | ||||
| -rw-r--r-- | package-lock.json | 8 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | quasar.conf.js | 18 | ||||
| -rw-r--r-- | src/pages/UploadDetail.vue | 16 | ||||
| -rw-r--r-- | src/pages/UploadList.vue | 41 | ||||
| -rw-r--r-- | src/plugins/prettyBytes.js | 25 | ||||
| -rw-r--r-- | src/plugins/vueMoment.js | 5 |
8 files changed, 94 insertions, 30 deletions
diff --git a/.quasar/entry.js b/.quasar/entry.js index 854dcc1..f8e54ce 100644 --- a/.quasar/entry.js +++ b/.quasar/entry.js @@ -40,12 +40,12 @@ import 'src/css/app.styl' import Vue from 'vue' -import Quasar, {QAlert,QLayout,QLayoutHeader,QLayoutDrawer,QPageContainer,QPage,QToolbar,QToolbarTitle,QBtn,QIcon,QList,QListHeader,QInput,QItem,QItemMain,QItemSide,QTable,QTabs,QRouteTab,QInnerLoading,QField,QStep,QStepper,QStepperNavigation,Ripple,LocalStorage,Notify} from 'quasar' +import Quasar, {QAlert,QLayout,QLayoutHeader,QLayoutDrawer,QPageContainer,QPage,QToolbar,QToolbarTitle,QBtn,QIcon,QList,QListHeader,QInput,QItem,QItemMain,QItemSide,QTable,QTabs,QRouteTab,QInnerLoading,QField,QStep,QStepper,QStepperNavigation,QTd,QSpinner,QCard,QCardTitle,QCardMain,QCardMedia,QCardSeparator,QCardActions,QParallax,QCheckbox,Ripple,LocalStorage,Notify} from 'quasar' Vue.config.productionTip = false import App from 'src/App' -Vue.use(Quasar, {components: {QAlert,QLayout,QLayoutHeader,QLayoutDrawer,QPageContainer,QPage,QToolbar,QToolbarTitle,QBtn,QIcon,QList,QListHeader,QInput,QItem,QItemMain,QItemSide,QTable,QTabs,QRouteTab,QInnerLoading,QField,QStep,QStepper,QStepperNavigation},directives: {Ripple},plugins: {LocalStorage,Notify}}) +Vue.use(Quasar, {components: {QAlert,QLayout,QLayoutHeader,QLayoutDrawer,QPageContainer,QPage,QToolbar,QToolbarTitle,QBtn,QIcon,QList,QListHeader,QInput,QItem,QItemMain,QItemSide,QTable,QTabs,QRouteTab,QInnerLoading,QField,QStep,QStepper,QStepperNavigation,QTd,QSpinner,QCard,QCardTitle,QCardMain,QCardMedia,QCardSeparator,QCardActions,QParallax,QCheckbox},directives: {Ripple},plugins: {LocalStorage,Notify}}) @@ -74,6 +74,12 @@ plugins.push(pluginI18n) import pluginAxios from 'src/plugins/axios' plugins.push(pluginAxios) +import pluginPrettyBytes from 'src/plugins/prettyBytes' +plugins.push(pluginPrettyBytes) + +import pluginVueMoment from 'src/plugins/vueMoment' +plugins.push(pluginVueMoment) + plugins.forEach(plugin => plugin({ app, router, store, Vue })) diff --git a/package-lock.json b/package-lock.json index 4eb05b4..39a9ce4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11099,6 +11099,14 @@ } } }, + "vue-moment": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vue-moment/-/vue-moment-3.2.0.tgz", + "integrity": "sha1-KM0rMTgxroOVP2RqxHhaLMck5BI=", + "requires": { + "moment": "2.21.0" + } + }, "vue-router": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.1.tgz", diff --git a/package.json b/package.json index 0602d81..665a9d8 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "moment": "^2.21.0", "quasar-extras": "^1.0.2", "vue-i18n": "^7.3.3", + "vue-moment": "^3.2.0", "vue-truncate-collapsed": "^1.3.0", "vue2-dropzone": "^3.0.5" }, diff --git a/quasar.conf.js b/quasar.conf.js index 863b4c4..2d0a893 100644 --- a/quasar.conf.js +++ b/quasar.conf.js @@ -4,7 +4,9 @@ module.exports = function (ctx) { return { plugins: [ 'i18n', - 'axios' + 'axios', + 'prettyBytes', + 'vueMoment', ], css: [ 'app.styl' @@ -38,8 +40,8 @@ module.exports = function (ctx) { }, env: ctx.dev ? { // so on dev we'll have - API: JSON.stringify('http://localhost:8080') - //API: JSON.stringify('https://frustrum.pictor.uberspace.de/larry') + //API: JSON.stringify('http://localhost:8080') + API: JSON.stringify('https://frustrum.pictor.uberspace.de/larry') } : { // and on build (production): API: JSON.stringify('https://frustrum.pictor.uberspace.de/larry') @@ -78,6 +80,16 @@ module.exports = function (ctx) { 'QStep', 'QStepper', 'QStepperNavigation', + 'QTd', + 'QSpinner', + 'QCard', + 'QCardTitle', + 'QCardMain', + 'QCardMedia', + 'QCardSeparator', + 'QCardActions', + 'QParallax', + 'QCheckbox', ], directives: [ 'Ripple' diff --git a/src/pages/UploadDetail.vue b/src/pages/UploadDetail.vue index d742a4a..956e324 100644 --- a/src/pages/UploadDetail.vue +++ b/src/pages/UploadDetail.vue @@ -9,7 +9,7 @@ <span slot="subtitle">by {{ upload.author.username }}</span> <span slot="right" class="text-white" style="margin-left: 3rem">updated {{ upload.updatedAt | moment("from") }}</span> </q-card-title> - <img :src="`${$http.defaults.baseURL}/media/${upload.pic}`"> + <img :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`"> </q-card-media> <q-card-title class="bg-positive text-white" v-else> {{ upload.title }} @@ -38,7 +38,7 @@ <q-card-title slot="overlay"> Voting </q-card-title> - <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic}`" :height="150"> + <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`" :height="150"> </q-parallax> </q-card-media> <q-card-title v-else> @@ -53,18 +53,18 @@ <q-card-title slot="overlay"> Dependencies </q-card-title> - <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic}`" :height="150"> + <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`" :height="150"> </q-parallax> </q-card-media> <q-card-title v-else> Dependencies </q-card-title> <q-card-main> - <q-btn disabled flat v-if="upload.dependency.length === 0"> + <q-btn disabled flat v-if="!Array.isArray(upload.dependencies) || upload.dependencies.length === 0"> No dependencies </q-btn> <div class="group" v-else> - <div v-for="d of upload.dependency" + <div v-for="d of upload.dependencies" :key="d._id"> <q-btn @click="$router.push({name: 'upload-detail', params: {uploadId: d._id}})" no-caps outline> {{ d.title }} @@ -76,14 +76,14 @@ <q-card-title slot="overlay"> File downloads </q-card-title> - <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic}`" :height="150"> + <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`" :height="150"> </q-parallax> </q-card-media> <q-card-title v-else> File downloads </q-card-title> <q-card-main> - <q-btn disabled flat v-if="upload.file.length === 0"> + <q-btn disabled flat v-if="!Array.isArray(upload.files) || upload.files.length === 0"> No files </q-btn> <div class="group" @@ -112,7 +112,7 @@ <q-card-title slot="overlay"> Other data </q-card-title> - <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic}`" :height="150"> + <q-parallax :src="`${$http.defaults.baseURL}/media/${upload.pic._id}`" :height="150"> </q-parallax> </q-card-media> <q-card-title v-else> diff --git a/src/pages/UploadList.vue b/src/pages/UploadList.vue index a8a731c..da297ba 100644 --- a/src/pages/UploadList.vue +++ b/src/pages/UploadList.vue @@ -5,28 +5,29 @@ <h4>Available Mods</h4> <q-table no-data-label="No mods available" + row-key="name" :data="uploads" :config="tableConfig" :columns="tableColumns" @refresh="refresh"> - <template slot='col-action' slot-scope='cell'> + <q-td slot='body-cell-action' slot-scope="props" :props='props'> <q-btn color="primary" small outline icon="fa-info-circle" - @click="$router.push({name: 'upload-detail', params: {uploadId: cell.row._id}})"> + @click="$router.push({name: 'upload-detail', params: {uploadId: props.row._id}})"> Details</q-btn> <q-btn color="negative" outline small icon="fa-trash-o" - v-if="cell.row.author.username === $store.state.user.decodedToken.username" + v-if="props.row.author.username === $store.state.user.decodedToken.username" @click="deleteUpload(cell.row)"> Delete</q-btn> - </template> - <template slot='col-voting' slot-scope='cell'> - {{ cell.data.sum }} <i class="fa" :class="{'fa-caret-up text-positive': cell.data.sum > 0, 'fa-caret-down text-negative': cell.data.sum < 0, 'fa-sort text-dark': cell.data.sum === 0}"></i> - </template> + </q-td> + <q-td slot='body-cell-voting' slot-scope="props" :props='props'> + {{ props.value.sum }} <i class="fa" :class="{'fa-caret-up text-positive': props.value.sum > 0, 'fa-caret-down text-negative': props.value.sum < 0, 'fa-sort text-dark': props.value.sum === 0}"></i> + </q-td> </q-table> </div> <router-view></router-view> @@ -38,13 +39,9 @@ import { Dialog, } from 'quasar' - import Truncate from 'vue-truncate-collapsed' import moment from 'moment' export default { - components: { - Truncate, - }, computed: { showList () { return this.$route.name === 'upload-list' @@ -71,12 +68,22 @@ rowHeight: '60px', }, tableColumns: [ - {label: 'Title', field: 'title', width: '100px'}, - {label: 'Description', field: 'description', width: '500px'}, - {label: 'Author', field: 'author', width: '100px', format: el => el.username}, - {label: 'Voting', field: 'voting', width: '100px'}, - {label: 'Last update', field: 'updatedAt', width: '100px', format: el => moment(el).from()}, - {label: 'Actions', field: 'action', width: '200px'}, + {name: 'title', label: 'Title', field: 'title'}, + { + name: 'description', + label: 'Description', + field: 'description', + format: el => typeof el === 'string' && el.length > 150 ? el.slice(0, 150) + '...' : el, + }, + {name: 'author', label: 'Author', field: row => row.author.username}, + {name: 'voting', label: 'Voting', field: 'voting'}, + { + name: 'updatedAt', + label: 'Last update', + field: 'updatedAt', + format: el => moment(el).from(), + }, + {name: 'action', label: 'Actions', field: 'action'}, ], } }, diff --git a/src/plugins/prettyBytes.js b/src/plugins/prettyBytes.js new file mode 100644 index 0000000..ebfb72d --- /dev/null +++ b/src/plugins/prettyBytes.js @@ -0,0 +1,25 @@ +export default ({ Vue }) => { + Vue.filter('prettyBytes', function (value) { + const UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + + if (!Number.isFinite(value)) { + throw new TypeError(`Expected a finite number, got ${typeof value}: ${value}`) + } + + const neg = value < 0 + + if (neg) { + value = -value + } + + if (value < 1) { + return (neg ? '-' : '') + value + ' B' + } + + const exponent = Math.min(Math.floor(Math.log10(value) / 3), UNITS.length - 1) + const numStr = Number((value / Math.pow(1000, exponent)).toPrecision(3)) + const unit = UNITS[exponent] + + return (neg ? '-' : '') + numStr + ' ' + unit + }) +} diff --git a/src/plugins/vueMoment.js b/src/plugins/vueMoment.js new file mode 100644 index 0000000..dd8ebfb --- /dev/null +++ b/src/plugins/vueMoment.js @@ -0,0 +1,5 @@ +import VueMoment from 'vue-moment' + +export default ({ Vue }) => { + Vue.use(VueMoment) +} |
