diff options
| author | Zephyrrus <[email protected]> | 2020-07-10 01:17:00 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-07-10 01:17:00 +0300 |
| commit | a721681944e9eb06742e5b3f71c71aed9c1c117d (patch) | |
| tree | 93ff9fd13a0434d91fb1ae7ca0da48d6929c4d00 /src/site/pages/dashboard/admin | |
| parent | feat: backend pagination for albums (diff) | |
| parent | refactor: finish refactoring all the components to use vuex (diff) | |
| download | host.fuwn.me-a721681944e9eb06742e5b3f71c71aed9c1c117d.tar.xz host.fuwn.me-a721681944e9eb06742e5b3f71c71aed9c1c117d.zip | |
Merge pull request #1 from Zephyrrus/feature/store_refactor
Feature/store refactor
Diffstat (limited to 'src/site/pages/dashboard/admin')
| -rw-r--r-- | src/site/pages/dashboard/admin/file/_id.vue | 145 | ||||
| -rw-r--r-- | src/site/pages/dashboard/admin/settings.vue | 109 | ||||
| -rw-r--r-- | src/site/pages/dashboard/admin/user/_id.vue | 96 | ||||
| -rw-r--r-- | src/site/pages/dashboard/admin/users.vue | 264 |
4 files changed, 334 insertions, 280 deletions
diff --git a/src/site/pages/dashboard/admin/file/_id.vue b/src/site/pages/dashboard/admin/file/_id.vue index 5821292..89afa47 100644 --- a/src/site/pages/dashboard/admin/file/_id.vue +++ b/src/site/pages/dashboard/admin/file/_id.vue @@ -9,87 +9,111 @@ <Sidebar /> </div> <div class="column"> - <h2 class="subtitle">File details</h2> + <h2 class="subtitle"> + File details + </h2> <hr> <div class="columns"> <div class="column is-6"> - <b-field label="ID" + <b-field + label="ID" horizontal> - <span>{{ file.id }}</span> + <span>{{ admin.file.id }}</span> </b-field> - <b-field label="Name" + <b-field + label="Name" horizontal> - <span>{{ file.name }}</span> + <span>{{ admin.file.name }}</span> </b-field> - <b-field label="Original Name" + <b-field + label="Original Name" horizontal> - <span>{{ file.original }}</span> + <span>{{ admin.file.original }}</span> </b-field> - <b-field label="IP" + <b-field + label="IP" horizontal> - <span class="underline">{{ file.ip }}</span> + <span class="underline">{{ admin.file.ip }}</span> </b-field> - <b-field label="Link" + <b-field + label="Link" horizontal> - <a :href="file.url" - target="_blank">{{ file.url }}</a> + <a + :href="admin.file.url" + target="_blank">{{ admin.file.url }}</a> </b-field> - <b-field label="Size" + <b-field + label="Size" horizontal> - <span>{{ formatBytes(file.size) }}</span> + <span>{{ formatBytes(admin.file.size) }}</span> </b-field> - <b-field label="Hash" + <b-field + label="Hash" horizontal> - <span>{{ file.hash }}</span> + <span>{{ admin.file.hash }}</span> </b-field> - <b-field label="Uploaded" + <b-field + label="Uploaded" horizontal> - <span><timeago :since="file.createdAt" /></span> + <span><timeago :since="admin.file.createdAt" /></span> </b-field> </div> <div class="column is-6"> - <b-field label="User Id" + <b-field + label="User Id" horizontal> - <span>{{ user.id }}</span> + <span>{{ admin.user.id }}</span> </b-field> - <b-field label="Username" + <b-field + label="Username" horizontal> - <span>{{ user.username }}</span> + <span>{{ admin.user.username }}</span> </b-field> - <b-field label="Enabled" + <b-field + label="Enabled" horizontal> - <span>{{ user.enabled }}</span> + <span>{{ admin.user.enabled }}</span> </b-field> - <b-field label="Registered" + <b-field + label="Registered" horizontal> - <span><timeago :since="user.createdAt" /></span> + <span><timeago :since="admin.user.createdAt" /></span> </b-field> - <b-field label="Files" + <b-field + label="Files" horizontal> <span> - <nuxt-link :to="`/dashboard/admin/user/${user.id}`">{{ user.fileCount }}</nuxt-link> + <nuxt-link :to="`/dashboard/admin/user/${admin.user.id}`">{{ admin.user.fileCount }}</nuxt-link> </span> </b-field> </div> </div> <div class="mb2 mt2 text-center"> - <button class="button is-danger" - @click="promptBanIP">Ban IP</button> - <button class="button is-danger" - @click="promptDisableUser">Disable user</button> + <b-button + v-if="admin.user.id !== auth.user.id" + type="is-danger" + @click="promptBanIP"> + Ban IP + </b-button> + <b-button + v-if="admin.user.id !== auth.user.id" + type="is-danger" + @click="promptDisableUser"> + Disable user + </b-button> </div> </div> </div> @@ -98,59 +122,42 @@ </template> <script> +import { mapState } from 'vuex'; import Sidebar from '~/components/sidebar/Sidebar.vue'; export default { components: { - Sidebar + Sidebar, }, - middleware: ['auth', 'admin'], - data() { - return { - options: {}, - file: null, - user: null - }; - }, - async asyncData({ $axios, route }) { + middleware: ['auth', 'admin', ({ route, store }) => { try { - const response = await $axios.$get(`file/${route.params.id}`); - return { - file: response.file ? response.file : null, - user: response.user ? response.user : null - }; - } catch (error) { - console.error(error); - return { - file: null, - user: null - }; + store.dispatch('admin/fetchFile', route.params.id); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); } - }, + }], + computed: mapState(['admin', 'auth']), methods: { promptDisableUser() { this.$buefy.dialog.confirm({ + type: 'is-danger', message: 'Are you sure you want to disable the account of the user that uploaded this file?', - onConfirm: () => this.disableUser() + onConfirm: () => this.disableUser(), }); }, - async disableUser() { - const response = await this.$axios.$post('admin/users/disable', { - id: this.user.id - }); - this.$buefy.toast.open(response.message); + disableUser() { + this.$handler.executeAction('admin/disableUser', this.user.id); }, promptBanIP() { this.$buefy.dialog.confirm({ + type: 'is-danger', message: 'Are you sure you want to ban the IP this file was uploaded from?', - onConfirm: () => this.banIP() + onConfirm: () => this.banIP(), }); }, - async banIP() { - const response = await this.$axios.$post('admin/ban/ip', { - ip: this.file.ip - }); - this.$buefy.toast.open(response.message); + banIP() { + this.$handler.executeAction('admin/banIP', this.file.ip); }, formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; @@ -161,8 +168,8 @@ export default { const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; - } - } + return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`; + }, + }, }; </script> diff --git a/src/site/pages/dashboard/admin/settings.vue b/src/site/pages/dashboard/admin/settings.vue index 2d59fff..7f6a0fe 100644 --- a/src/site/pages/dashboard/admin/settings.vue +++ b/src/site/pages/dashboard/admin/settings.vue @@ -6,87 +6,112 @@ <Sidebar /> </div> <div class="column"> - <h2 class="subtitle">Service settings</h2> + <h2 class="subtitle"> + Service settings + </h2> <hr> - <b-field label="Service name" + <b-field + label="Service name" message="Please enter the name which this service is gonna be identified as" horizontal> - <b-input v-model="options.serviceName" + <b-input + v-model="settings.serviceName" expanded /> </b-field> - <b-field label="Upload folder" + <b-field + label="Upload folder" message="Where to store the files relative to the working directory" horizontal> - <b-input v-model="options.uploadFolder" + <b-input + v-model="settings.uploadFolder" expanded /> </b-field> - <b-field label="Links per album" + <b-field + label="Links per album" message="Maximum links allowed per album" horizontal> - <b-input v-model="options.linksPerAlbum" + <b-input + v-model="settings.linksPerAlbum" type="number" expanded /> </b-field> - <b-field label="Max upload size" + <b-field + label="Max upload size" message="Maximum allowed file size in MB" horizontal> - <b-input v-model="options.maxUploadSize" + <b-input + v-model="settings.maxUploadSize" expanded /> </b-field> - <b-field label="Filename length" + <b-field + label="Filename length" message="How many characters long should the generated filenames be" horizontal> - <b-input v-model="options.filenameLength" + <b-input + v-model="settings.filenameLength" expanded /> </b-field> - <b-field label="Album link length" + <b-field + label="Album link length" message="How many characters a link for an album should have" horizontal> - <b-input v-model="options.albumLinkLength" + <b-input + v-model="settings.albumLinkLength" expanded /> </b-field> - <b-field label="Generate thumbnails" + <b-field + label="Generate thumbnails" message="Generate thumbnails when uploading a file if possible" horizontal> - <b-switch v-model="options.generateThumbnails" + <b-switch + v-model="settings.generateThumbnails" :true-value="true" :false-value="false" /> </b-field> - <b-field label="Generate zips" + <b-field + label="Generate zips" message="Allow generating zips to download entire albums" horizontal> - <b-switch v-model="options.generateZips" + <b-switch + v-model="settings.generateZips" :true-value="true" :false-value="false" /> </b-field> - <b-field label="Public mode" + <b-field + label="Public mode" message="Enable anonymous uploades" horizontal> - <b-switch v-model="options.publicMode" + <b-switch + v-model="settings.publicMode" :true-value="true" :false-value="false" /> </b-field> - <b-field label="Enable creating account" + <b-field + label="Enable creating account" message="Enable creating new accounts in the platform" horizontal> - <b-switch v-model="options.enableAccounts" + <b-switch + v-model="settings.enableAccounts" :true-value="true" :false-value="false" /> </b-field> <div class="mb2 mt2 text-center"> - <button class="button is-primary" - @click="promptRestartService">Save and restart service</button> + <button + class="button is-primary" + @click="promptRestartService"> + Save and restart service + </button> </div> </div> </div> @@ -95,39 +120,37 @@ </template> <script> +import { mapState } from 'vuex'; import Sidebar from '~/components/sidebar/Sidebar.vue'; export default { components: { - Sidebar - }, - middleware: ['auth', 'admin'], - data() { - return { - options: {} - }; + Sidebar, }, + middleware: ['auth', 'admin', ({ store }) => { + try { + store.dispatch('admin/fetchSettings'); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + }], metaInfo() { return { title: 'Settings' }; }, - mounted() { - this.getSettings(); - }, + computed: mapState({ + settings: (state) => state.admin.settings, + }), methods: { - async getSettings() { - const response = await this.$axios.$get(`service/config`); - this.options = response.config; - }, promptRestartService() { this.$buefy.dialog.confirm({ message: 'Keep in mind that restarting only works if you have PM2 or something similar set up. Continue?', - onConfirm: () => this.restartService() + onConfirm: () => this.restartService(), }); }, - async restartService() { - const response = await this.$axios.$post(`service/restart`); - this.$buefy.toast.open(response.message); - } - } + restartService() { + this.$handler.executeAction('admin/restartService'); + }, + }, }; </script> diff --git a/src/site/pages/dashboard/admin/user/_id.vue b/src/site/pages/dashboard/admin/user/_id.vue index 2a56c34..7814468 100644 --- a/src/site/pages/dashboard/admin/user/_id.vue +++ b/src/site/pages/dashboard/admin/user/_id.vue @@ -9,41 +9,59 @@ <Sidebar /> </div> <div class="column"> - <h2 class="subtitle">User details</h2> + <h2 class="subtitle"> + User details + </h2> <hr> - <b-field label="User Id" + <b-field + label="User Id" horizontal> <span>{{ user.id }}</span> </b-field> - <b-field label="Username" + <b-field + label="Username" horizontal> <span>{{ user.username }}</span> </b-field> - <b-field label="Enabled" + <b-field + label="Enabled" horizontal> <span>{{ user.enabled }}</span> </b-field> - <b-field label="Registered" + <b-field + label="Registered" horizontal> <span><timeago :since="user.createdAt" /></span> </b-field> - <b-field label="Files" + <b-field + label="Files" horizontal> - <span>{{ files.length }}</span> + <span>{{ user.files.length }}</span> </b-field> <div class="mb2 mt2 text-center"> - <button class="button is-danger" - @click="promptDisableUser">Disable user</button> + <b-button + v-if="user.enabled" + type="is-danger" + @click="promptDisableUser"> + Disable user + </b-button> + <b-button + v-if="!user.enabled" + type="is-success" + @click="promptEnableUser"> + Enable user + </b-button> </div> - <Grid v-if="files.length" - :files="files" /> + <Grid + v-if="user.files.length" + :files="user.files" /> </div> </div> </div> @@ -51,50 +69,52 @@ </template> <script> +import { mapState } from 'vuex'; import Sidebar from '~/components/sidebar/Sidebar.vue'; import Grid from '~/components/grid/Grid.vue'; export default { components: { Sidebar, - Grid + Grid, }, - middleware: ['auth', 'admin'], + middleware: ['auth', 'admin', ({ route, store }) => { + try { + store.dispatch('admin/fetchUser', route.params.id); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + }], data() { return { options: {}, - files: null, - user: null }; }, - async asyncData({ $axios, route }) { - try { - const response = await $axios.$get(`/admin/users/${route.params.id}`); - return { - files: response.files ? response.files : null, - user: response.user ? response.user : null - }; - } catch (error) { - console.error(error); - return { - files: null, - user: null - }; - } - }, + computed: mapState({ + user: (state) => state.admin.user, + }), methods: { promptDisableUser() { this.$buefy.dialog.confirm({ - message: 'Are you sure you want to disable the account of the user that uploaded this file?', - onConfirm: () => this.disableUser() + type: 'is-danger', + message: 'Are you sure you want to disable the account of this user?', + onConfirm: () => this.disableUser(), }); }, - async disableUser() { - const response = await this.$axios.$post('admin/users/disable', { - id: this.user.id + promptEnableUser() { + this.$buefy.dialog.confirm({ + type: 'is-danger', + message: 'Are you sure you want to enable the account of this user?', + onConfirm: () => this.enableUser(), }); - this.$buefy.toast.open(response.message); - } - } + }, + disableUser() { + this.$handler.executeAction('admin/disableUser', this.user.id); + }, + enableUser() { + this.$handler.executeAction('admin/enableUser', this.user.id); + }, + }, }; </script> diff --git a/src/site/pages/dashboard/admin/users.vue b/src/site/pages/dashboard/admin/users.vue index 695cf0b..bed4c2b 100644 --- a/src/site/pages/dashboard/admin/users.vue +++ b/src/site/pages/dashboard/admin/users.vue @@ -1,3 +1,137 @@ +<template> + <section class="section is-fullheight dashboard"> + <div class="container"> + <div class="columns"> + <div class="column is-narrow"> + <Sidebar /> + </div> + <div class="column"> + <h2 class="subtitle"> + Manage your users + </h2> + <hr> + + <div class="view-container"> + <b-table + :data="users" + :mobile-cards="true"> + <template slot-scope="props"> + <b-table-column + field="id" + label="Id" + centered> + {{ props.row.id }} + </b-table-column> + + <b-table-column + field="username" + label="Username" + centered> + <nuxt-link :to="`/dashboard/admin/user/${props.row.id}`"> + {{ props.row.username }} + </nuxt-link> + </b-table-column> + + <b-table-column + field="enabled" + label="Enabled" + centered> + <b-switch + :value="props.row.enabled" + @input="changeEnabledStatus(props.row)" /> + </b-table-column> + + <b-table-column + field="isAdmin" + label="Admin" + centered> + <b-switch + :value="props.row.isAdmin" + @input="changeIsAdmin(props.row)" /> + </b-table-column> + + <b-table-column + field="purge" + centered> + <b-button + type="is-danger" + @click="promptPurgeFiles(props.row)"> + Purge files + </b-button> + </b-table-column> + </template> + <template slot="empty"> + <div class="has-text-centered"> + <i class="icon-misc-mood-sad" /> + </div> + <div class="has-text-centered"> + Nothing here + </div> + </template> + <template slot="footer"> + <div class="has-text-right"> + {{ users.length }} users + </div> + </template> + </b-table> + </div> + </div> + </div> + </div> + </section> +</template> + +<script> +import { mapState } from 'vuex'; +import Sidebar from '~/components/sidebar/Sidebar.vue'; + +export default { + components: { + Sidebar, + }, + middleware: ['auth', 'admin', ({ route, store }) => { + try { + store.dispatch('admin/fetchUsers', route.params.id); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + }], + computed: mapState({ + users: (state) => state.admin.users, + config: (state) => state.config, + }), + metaInfo() { + return { title: 'Uploads' }; + }, + methods: { + async changeEnabledStatus(row) { + if (row.enabled) { + this.$handler.executeAction('admin/disableUser', row.id); + } else { + this.$handler.executeAction('admin/enableUser', row.id); + } + }, + async changeIsAdmin(row) { + if (row.isAdmin) { + this.$handler.executeAction('admin/demoteUser', row.id); + } else { + this.$handler.executeAction('admin/promoteUser', row.id); + } + }, + promptPurgeFiles(row) { + this.$buefy.dialog.confirm({ + message: 'Are you sure you want to delete this user\'s files?', + onConfirm: () => this.purgeFiles(row), + }); + }, + async purgeFiles(row) { + this.$handler.executeAction('admin/purgeUserFiles', row.id); + }, + }, +}; +</script> + <style lang="scss" scoped> @import '~/assets/styles/_colors.scss'; div.view-container { @@ -107,9 +241,6 @@ } div.column > h2.subtitle { padding-top: 1px; } -</style> -<style lang="scss"> - @import '~/assets/styles/_colors.scss'; .b-table { .table-wrapper { @@ -118,130 +249,3 @@ } } </style> - - -<template> - <section class="section is-fullheight dashboard"> - <div class="container"> - <div class="columns"> - <div class="column is-narrow"> - <Sidebar /> - </div> - <div class="column"> - <h2 class="subtitle">Manage your users</h2> - <hr> - - <div class="view-container"> - <b-table - :data="users || []" - :mobile-cards="true"> - <template slot-scope="props"> - <b-table-column field="id" - label="Id" - centered> - {{ props.row.id }} - </b-table-column> - - <b-table-column field="username" - label="Username" - centered> - <nuxt-link :to="`/dashboard/admin/user/${props.row.id}`">{{ props.row.username }}</nuxt-link> - </b-table-column> - - <b-table-column field="enabled" - label="Enabled" - centered> - <b-switch v-model="props.row.enabled" - @input="changeEnabledStatus(props.row)" /> - </b-table-column> - - <b-table-column field="isAdmin" - label="Admin" - centered> - <b-switch v-model="props.row.isAdmin" - @input="changeIsAdmin(props.row)" /> - </b-table-column> - - <b-table-column field="purge" - centered> - <button class="button is-primary" - @click="promptPurgeFiles(props.row)">Purge files</button> - </b-table-column> - </template> - <template slot="empty"> - <div class="has-text-centered"> - <i class="icon-misc-mood-sad" /> - </div> - <div class="has-text-centered"> - Nothing here - </div> - </template> - <template slot="footer"> - <div class="has-text-right"> - {{ users.length }} users - </div> - </template> - </b-table> - </div> - </div> - </div> - </div> - </section> -</template> - -<script> -import Sidebar from '~/components/sidebar/Sidebar.vue'; - -export default { - components: { - Sidebar - }, - middleware: ['auth', 'admin'], - data() { - return { - users: [] - }; - }, - computed: { - config() { - return this.$store.state.config; - } - }, - metaInfo() { - return { title: 'Uploads' }; - }, - mounted() { - this.getUsers(); - }, - methods: { - async getUsers() { - const response = await this.$axios.$get(`admin/users`); - this.users = response.users; - }, - async changeEnabledStatus(row) { - const response = await this.$axios.$post(`admin/users/${row.enabled ? 'enable' : 'disable'}`, { - id: row.id - }); - this.$buefy.toast.open(response.message); - }, - async changeIsAdmin(row) { - const response = await this.$axios.$post(`admin/users/${row.isAdmin ? 'promote' : 'demote'}`, { - id: row.id - }); - this.$buefy.toast.open(response.message); - }, - promptPurgeFiles(row) { - this.$buefy.dialog.confirm({ - message: 'Are you sure you want to delete this user\'s files?', - onConfirm: () => this.purgeFiles(row) - }); - }, - async purgeFiles(row) { - const response = await this.$axios.$post(`admin/users/purge`, { - id: row.id - }); - this.$buefy.toast.open(response.message); - } - } -}; -</script> |