mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-05-29 07:34:43 +00:00
backend update
This commit is contained in:
@@ -61,6 +61,14 @@
|
||||
if (args.emoji) {
|
||||
this.emoji = args.emoji
|
||||
}
|
||||
|
||||
if (args.buttonStyle) {
|
||||
this.buttonStyle = args.buttonStyle
|
||||
}
|
||||
|
||||
if (args.button) {
|
||||
this.button = args.button
|
||||
}
|
||||
})
|
||||
|
||||
// Show alert
|
||||
|
||||
@@ -274,7 +274,10 @@
|
||||
EyeIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
...mapGetters(['user']),
|
||||
favourites() {
|
||||
return this.user.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
isFolder() {
|
||||
return this.item && this.item.type === 'folder'
|
||||
},
|
||||
@@ -285,7 +288,7 @@
|
||||
return this.item && this.item.type === 'image'
|
||||
},
|
||||
isInFavourites() {
|
||||
return this.app.favourites.find(el => el.unique_id == this.item.unique_id)
|
||||
return this.favourites.find(el => el.unique_id == this.item.unique_id)
|
||||
},
|
||||
},
|
||||
data() {
|
||||
@@ -312,7 +315,7 @@
|
||||
},
|
||||
addToFavourites() {
|
||||
// Check if folder is in favourites and then add/remove from favourites
|
||||
if (this.app.favourites && !this.app.favourites.find(el => el.unique_id == this.item.unique_id)) {
|
||||
if (this.favourites && !this.favourites.find(el => el.unique_id == this.item.unique_id)) {
|
||||
this.$store.dispatch('addToFavourites', this.item)
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.item)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<!--Files controlls-->
|
||||
<div class="toolbar-button-wrapper" v-if="$checkPermission(['master', 'editor'])">
|
||||
<ToolbarButtonUpload
|
||||
:class="{'is-inactive': canUploadInView}"
|
||||
:class="{'is-inactive': canUploadInView || ! hasCapacity}"
|
||||
:action="$t('actions.upload')"
|
||||
/>
|
||||
<ToolbarButton
|
||||
@@ -109,6 +109,9 @@
|
||||
'browseHistory',
|
||||
'homeDirectory',
|
||||
]),
|
||||
hasCapacity() {
|
||||
return this.$store.getters.user.relationships.storage.data.attributes.used <= 100
|
||||
},
|
||||
directoryName() {
|
||||
return this.currentFolder ? this.currentFolder.name : this.homeDirectory.name
|
||||
},
|
||||
|
||||
@@ -288,6 +288,7 @@
|
||||
bottom: 0;
|
||||
@include transition;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.is-offset {
|
||||
margin-top: 50px;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="file-info-content" v-if="fileInfoDetail">
|
||||
<div class="file-headline" spellcheck="false">
|
||||
<FilePreview />
|
||||
<FilePreview/>
|
||||
|
||||
<!--File info-->
|
||||
<div class="flex">
|
||||
@@ -14,45 +14,38 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<span ref="name" class="name">{{ fileInfoDetail.name }}</span>
|
||||
<span ref="name" class="name">{{ fileInfoDetail.name }}</span>
|
||||
<span class="mimetype" v-if="fileInfoDetail.mimetype">.{{ fileInfoDetail.mimetype }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Info list-->
|
||||
<ul class="list-info">
|
||||
<ListInfo>
|
||||
<ListInfoItem v-if="fileInfoDetail.filesize"
|
||||
:title="$t('file_detail.size')"
|
||||
:content="fileInfoDetail.filesize">
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Filesize-->
|
||||
<li v-if="fileInfoDetail.filesize" class="list-info-item">
|
||||
<b>{{ $t('file_detail.size') }}</b>
|
||||
<span>{{ fileInfoDetail.filesize }}</span>
|
||||
</li>
|
||||
<ListInfoItem v-if="$checkPermission(['master']) && fileInfoDetail.user_scope !== 'master'"
|
||||
:title="$t('file_detail.author')"
|
||||
:content="$t('file_detail.author_participant')">
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Latest change-->
|
||||
<li v-if="$checkPermission(['master']) && fileInfoDetail.user_scope !== 'master'" class="list-info-item">
|
||||
<b>{{ $t('file_detail.author') }}</b>
|
||||
<span>{{ $t('file_detail.author_participant') }}</span>
|
||||
</li>
|
||||
<ListInfoItem
|
||||
:title="$t('file_detail.created_at')"
|
||||
:content="fileInfoDetail.created_at">
|
||||
</ListInfoItem>
|
||||
|
||||
<!--Latest change-->
|
||||
<li class="list-info-item">
|
||||
<b>{{ $t('file_detail.created_at') }}</b>
|
||||
<span>{{ fileInfoDetail.created_at }}</span>
|
||||
</li>
|
||||
|
||||
<!--Parent-->
|
||||
<li v-if="$checkPermission(['master'])" class="list-info-item">
|
||||
<b>{{ $t('file_detail.where') }}</b>
|
||||
<ListInfoItem v-if="$checkPermission(['master'])"
|
||||
:title="$t('file_detail.where')">
|
||||
<div class="action-button" @click="moveItem">
|
||||
<span>{{ fileInfoDetail.parent ? fileInfoDetail.parent.name : $t('locations.home') }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!--Parent-->
|
||||
<li v-if="$checkPermission('master') && fileInfoDetail.shared" class="list-info-item">
|
||||
<b>{{ $t('file_detail.shared') }}</b>
|
||||
</ListInfoItem>
|
||||
<ListInfoItem v-if="$checkPermission('master') && fileInfoDetail.shared"
|
||||
:title="$t('file_detail.shared')">
|
||||
<div class="action-button" @click="shareItemOptions">
|
||||
<span>{{ sharedInfo }}</span>
|
||||
<edit-2-icon size="10" class="edit-icon"></edit-2-icon>
|
||||
@@ -60,24 +53,27 @@
|
||||
<div class="sharelink">
|
||||
<lock-icon v-if="isLocked" @click="shareItemOptions" class="lock-icon" size="17"></lock-icon>
|
||||
<unlock-icon v-if="! isLocked" @click="shareItemOptions" class="lock-icon" size="17"></unlock-icon>
|
||||
|
||||
<CopyInput class="copy-sharelink" size="small" :value="fileInfoDetail.shared.link" />
|
||||
<CopyInput class="copy-sharelink" size="small" :value="fileInfoDetail.shared.link"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ListInfoItem>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon } from 'vue-feather-icons'
|
||||
import {Edit2Icon, LockIcon, UnlockIcon, ImageIcon, VideoIcon, FolderIcon, FileIcon} from 'vue-feather-icons'
|
||||
import FilePreview from '@/components/FilesView/FilePreview'
|
||||
import CopyInput from '@/components/Others/Forms/CopyInput'
|
||||
import ListInfoItem from '@/components/Others/ListInfoItem'
|
||||
import ListInfo from '@/components/Others/ListInfo'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
|
||||
export default {
|
||||
name: 'FileInfoPanel',
|
||||
components: {
|
||||
ListInfoItem,
|
||||
ListInfo,
|
||||
FilePreview,
|
||||
FolderIcon,
|
||||
UnlockIcon,
|
||||
@@ -92,23 +88,23 @@
|
||||
...mapGetters(['fileInfoDetail', 'permissionOptions']),
|
||||
fileType() {
|
||||
return this.fileInfoDetail.type
|
||||
/* switch () {
|
||||
case 'folder':
|
||||
return 'folder'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file'
|
||||
break;
|
||||
case 'image':
|
||||
return 'file-image'
|
||||
break;
|
||||
case 'video':
|
||||
return 'file-video'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file-audio'
|
||||
break;
|
||||
}*/
|
||||
/* switch () {
|
||||
case 'folder':
|
||||
return 'folder'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file'
|
||||
break;
|
||||
case 'image':
|
||||
return 'file-image'
|
||||
break;
|
||||
case 'video':
|
||||
return 'file-video'
|
||||
break;
|
||||
case 'file':
|
||||
return 'file-audio'
|
||||
break;
|
||||
}*/
|
||||
},
|
||||
sharedInfo() {
|
||||
|
||||
@@ -123,10 +119,10 @@
|
||||
switch (this.fileInfoDetail.shared.permission) {
|
||||
case 'editor':
|
||||
return 'user-edit'
|
||||
break
|
||||
break
|
||||
case 'visitor':
|
||||
return 'user'
|
||||
break
|
||||
break
|
||||
default:
|
||||
return 'download'
|
||||
}
|
||||
@@ -199,41 +195,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.list-info {
|
||||
|
||||
.list-info-item {
|
||||
display: block;
|
||||
padding-top: 20px;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
cursor: pointer;
|
||||
|
||||
.edit-icon {
|
||||
display: inline-block;
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
b {
|
||||
display: block;
|
||||
@include font-size(13);
|
||||
color: $theme;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
@include font-size(14);
|
||||
font-weight: bold;
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sharelink {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -264,23 +225,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.list-info {
|
||||
|
||||
.list-info-item {
|
||||
|
||||
span {
|
||||
color: $dark_mode_text_primary
|
||||
}
|
||||
|
||||
.action-button {
|
||||
|
||||
.icon {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sharelink {
|
||||
|
||||
.lock-icon {
|
||||
|
||||
@@ -258,9 +258,12 @@
|
||||
EyeIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['fileInfoDetail', 'app']),
|
||||
...mapGetters(['fileInfoDetail', 'user']),
|
||||
favourites() {
|
||||
return this.user.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
isInFavourites() {
|
||||
return this.app.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)
|
||||
return this.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)
|
||||
},
|
||||
isFile() {
|
||||
return (this.fileInfoDetail && this.fileInfoDetail.type !== 'folder') && (this.fileInfoDetail && this.fileInfoDetail.type !== 'image')
|
||||
@@ -292,7 +295,7 @@
|
||||
}
|
||||
},
|
||||
addToFavourites() {
|
||||
if (this.app.favourites && !this.app.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)) {
|
||||
if (this.favourites && !this.favourites.find(el => el.unique_id == this.fileInfoDetail.unique_id)) {
|
||||
this.$store.dispatch('addToFavourites', this.fileInfoDetail)
|
||||
} else {
|
||||
this.$store.dispatch('removeFromFavourites', this.fileInfoDetail)
|
||||
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
background: $dark_background;
|
||||
background: $light_background;
|
||||
margin-top: 5px;
|
||||
border-radius: 10px;
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
}
|
||||
|
||||
.input-area {
|
||||
border: 1px solid #ebebeb;
|
||||
border: 1px solid transparent;
|
||||
justify-content: space-between;
|
||||
background: $light_mode_input_background;
|
||||
@include transition(150ms);
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
.setup-box {
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.title {
|
||||
@include font-size(19);
|
||||
margin-bottom: 15px;
|
||||
@include font-size(21);
|
||||
margin-bottom: 5px;
|
||||
display: block;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.description {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<ul class="list-info">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ListInfo',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<li class="list-info-item">
|
||||
<b>{{ title }}</b>
|
||||
<span v-if="content">{{ content }}</span>
|
||||
<slot></slot>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ListInfoItem',
|
||||
props: ['title', 'content']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.list-info-item {
|
||||
display: block;
|
||||
padding-bottom: 20px;
|
||||
|
||||
&:first-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
cursor: pointer;
|
||||
|
||||
.edit-icon {
|
||||
display: inline-block;
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
b {
|
||||
display: block;
|
||||
@include font-size(13);
|
||||
color: $theme;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
@include font-size(14);
|
||||
font-weight: bold;
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.list-info-item {
|
||||
|
||||
span {
|
||||
color: $dark_mode_text_primary
|
||||
}
|
||||
|
||||
.action-button {
|
||||
|
||||
.icon {
|
||||
color: $dark_mode_text_primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mobile-main-navigation" v-if="app">
|
||||
<div class="mobile-main-navigation" v-if="user">
|
||||
<transition name="context-menu">
|
||||
<nav v-if="isVisible" class="mobile-navigation">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
UserAvatar,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app', 'homeDirectory']),
|
||||
...mapGetters(['user', 'homeDirectory']),
|
||||
navigation() {
|
||||
return [
|
||||
{
|
||||
@@ -71,7 +71,7 @@
|
||||
icon: 'settings',
|
||||
title: this.$t('menu.admin'),
|
||||
routeName: 'AdminMobileMenu',
|
||||
isVisible: this.app.user.role === 'admin',
|
||||
isVisible: this.user.data.attributes.role === 'admin',
|
||||
},
|
||||
{
|
||||
icon: 'power',
|
||||
|
||||
@@ -49,9 +49,15 @@
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
axios.get('/api/public/pricing')
|
||||
.then(response => {
|
||||
this.plans = response.data.data
|
||||
this.plans = response.data.data.filter(plan => {
|
||||
if (this.$store.getters.user.relationships.subscription)
|
||||
return plan.data.attributes.capacity > this.$store.getters.user.relationships.subscription.data.attributes.capacity
|
||||
|
||||
return true
|
||||
})
|
||||
this.$emit('load', false)
|
||||
})
|
||||
}
|
||||
@@ -133,6 +139,7 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -25px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app', 'permissionOptions']),
|
||||
...mapGetters(['permissionOptions']),
|
||||
itemTypeTitle() {
|
||||
return this.pickedItem && this.pickedItem.type === 'folder' ? this.$t('types.folder') : this.$t('types.file')
|
||||
},
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app', 'permissionOptions', 'currentFolder']),
|
||||
...mapGetters(['user', 'permissionOptions', 'currentFolder']),
|
||||
isFolder() {
|
||||
return this.pickedItem && this.pickedItem.type === 'folder'
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
@click="sort(column.field, column.sortable, index)"
|
||||
:key="index"
|
||||
:class="{ sortable: column.sortable }"
|
||||
v-if="! column.hidden"
|
||||
>
|
||||
<span>{{ column.label }}</span>
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div class="upgrade-banner">
|
||||
<div class="header-title">
|
||||
<hard-drive-icon size="19" class="icon"></hard-drive-icon>
|
||||
<span class="title">{{ storage.used }}% From {{ storage.capacity_formatted }}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p v-if="storage.used > 95" class="reach-capacity">You reach your storage capacity. Please upgrade.</p>
|
||||
<p v-else class="reach-capacity">You nearly reach your storage capacity.</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<router-link :to="{name: 'UpgradePlan'}" class="button">
|
||||
Upgrade
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import { HardDriveIcon } from 'vue-feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'UpgradeSidebarBanner',
|
||||
components: {
|
||||
HardDriveIcon,
|
||||
ButtonBase,
|
||||
},
|
||||
computed: {
|
||||
storage() {
|
||||
return this.$store.getters.user.relationships.storage.data.attributes
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.upgrade-banner {
|
||||
background: rgba($danger, 0.1);
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
|
||||
line, path {
|
||||
stroke: $danger;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
@include font-size(13);
|
||||
font-weight: 800;
|
||||
color: $danger;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 12px;
|
||||
|
||||
p {
|
||||
@include font-size(12);
|
||||
color: $danger;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
background: $danger;
|
||||
border-radius: 50px;
|
||||
padding: 6px 0;
|
||||
width: 100%;
|
||||
color: white;
|
||||
text-align: center;
|
||||
@include font-size(12);
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
box-shadow: 0 4px 10px rgba($danger, 0.35);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="user-avatar" :class="size">
|
||||
<img :src="app.user.avatar" :alt="app.user.name">
|
||||
<img :src="user.data.attributes.avatar" :alt="user.data.attributes.name">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
'size'
|
||||
],
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
...mapGetters(['user']),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<nav class="menu-bar" v-if="app">
|
||||
<nav class="menu-bar" v-if="user">
|
||||
|
||||
<!--Navigation Icons-->
|
||||
<div class="icon-navigation menu">
|
||||
@@ -26,13 +26,13 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link :to="{name: 'Profile'}" :class="{'is-active': $isThisRoute($route, ['Password', 'Profile', 'Storage'])}" class="icon-navigation-item settings">
|
||||
<router-link :to="{name: 'Profile'}" :class="{'is-active': isUserProfileRoute}" class="icon-navigation-item settings">
|
||||
<div class="button-icon">
|
||||
<user-icon size="19"></user-icon>
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link v-if="app.user.role === 'admin'" :to="{name: 'Users'}" :class="{'is-active': $isThisRoute($route, adminRoutes)}" class="icon-navigation-item users">
|
||||
<router-link v-if="user.data.attributes.role === 'admin'" :to="{name: 'Users'}" :class="{'is-active': $isThisRoute($route, adminRoutes)}" class="icon-navigation-item users">
|
||||
<div class="button-icon">
|
||||
<settings-icon size="19"></settings-icon>
|
||||
</div>
|
||||
@@ -74,24 +74,34 @@
|
||||
UserIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
...mapGetters(['user']),
|
||||
isUserProfileRoute() {
|
||||
return this.$isThisRoute(this.$route, ['Profile', 'Password', 'Storage', 'Invoice', 'Subscription'])
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
adminRoutes: [
|
||||
'PlanSubscribers',
|
||||
'PlanSettings',
|
||||
'PlanDelete',
|
||||
|
||||
'GatewayTransactions',
|
||||
'GatewaySettings',
|
||||
'UserInvoices',
|
||||
'UserInvoices',
|
||||
'UserPassword',
|
||||
'UserStorage',
|
||||
'PlanCreate',
|
||||
'UserCreate',
|
||||
'UserDelete',
|
||||
'UserDetail',
|
||||
'Invoices',
|
||||
'Gateways',
|
||||
'Gateway',
|
||||
'Plans',
|
||||
'Users',
|
||||
'User',
|
||||
'UserDetail',
|
||||
'UserStorage',
|
||||
'UserPassword',
|
||||
'UserDelete',
|
||||
'Plans',
|
||||
'Invoices',
|
||||
'UserInvoices',
|
||||
'Gateway',
|
||||
'Gateways',
|
||||
'GatewaySettings',
|
||||
'GatewayTransactions',
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="user-meta" v-if="app">
|
||||
<b class="name">{{ app.user.name }}</b>
|
||||
<span class="email">{{ app.user.email }}</span>
|
||||
<b class="name">{{ user.data.attributes.name }}</b>
|
||||
<span class="email">{{ user.data.attributes.email }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
export default {
|
||||
name: 'UserHeadline',
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
...mapGetters(['user']),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
Vendored
+10
@@ -51,6 +51,7 @@ import UserDelete from './views/Admin/Users/UserTabs/UserDelete'
|
||||
import UserStorage from './views/Admin/Users/UserTabs/UserStorage'
|
||||
import UserPassword from './views/Admin/Users/UserTabs/UserPassword'
|
||||
import UserInvoices from './views/Admin/Users/UserTabs/UserInvoices'
|
||||
import UserSubscription from './views/Admin/Users/UserTabs/UserSubscription'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
@@ -151,6 +152,15 @@ const routesAdmin = [
|
||||
title: i18n.t('routes_title.users_storage_usage')
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'UserSubscription',
|
||||
path: '/admin/user/:id/subscription',
|
||||
component: UserSubscription,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
title: 'Subscription'
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'UserInvoices',
|
||||
path: '/admin/user/:id/invoices',
|
||||
|
||||
+10
-17
@@ -6,7 +6,7 @@ import router from '@/router'
|
||||
const defaultState = {
|
||||
authorized: undefined,
|
||||
permission: 'master', // master | editor | visitor
|
||||
app: undefined,
|
||||
user: undefined,
|
||||
}
|
||||
|
||||
const actions = {
|
||||
@@ -15,7 +15,7 @@ const actions = {
|
||||
axios
|
||||
.get(getters.api + '/user')
|
||||
.then((response) => {
|
||||
commit('RETRIEVE_APP_DATA', response.data)
|
||||
commit('RETRIEVE_USER', response.data)
|
||||
|
||||
}).catch((error) => {
|
||||
|
||||
@@ -74,8 +74,8 @@ const actions = {
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
RETRIEVE_APP_DATA(state, app) {
|
||||
state.app = app
|
||||
RETRIEVE_USER(state, user) {
|
||||
state.user = user
|
||||
},
|
||||
SET_PERMISSION(state, role) {
|
||||
state.permission = role
|
||||
@@ -85,30 +85,23 @@ const mutations = {
|
||||
state.app = undefined
|
||||
},
|
||||
ADD_TO_FAVOURITES(state, folder) {
|
||||
state.app.favourites.push({
|
||||
state.user.relationships.favourites.data.attributes.folders.push({
|
||||
unique_id: folder.unique_id,
|
||||
name: folder.name,
|
||||
type: folder.type,
|
||||
})
|
||||
},
|
||||
UPDATE_NAME(state, name) {
|
||||
state.app.user.name = name
|
||||
state.user.data.attributes.name = name
|
||||
},
|
||||
UPDATE_AVATAR(state, avatar) {
|
||||
state.app.user.avatar = avatar
|
||||
},
|
||||
UPDATE_RECENT_UPLOAD(state, file) {
|
||||
// Remove last file from altest uploads
|
||||
if (state.app.latest_uploads.length === 7) state.app.latest_uploads.pop()
|
||||
|
||||
// Add new file to latest uploads
|
||||
state.app.latest_uploads.unshift(file)
|
||||
state.user.data.attributes.avatar = avatar
|
||||
},
|
||||
REMOVE_ITEM_FROM_FAVOURITES(state, item) {
|
||||
state.app.favourites = state.app.favourites.filter(folder => folder.unique_id !== item.unique_id)
|
||||
state.user.relationships.favourites.data.attributes.folders = state.user.relationships.favourites.data.attributes.folders.filter(folder => folder.unique_id !== item.unique_id)
|
||||
},
|
||||
UPDATE_NAME_IN_FAVOURITES(state, data) {
|
||||
state.app.favourites.find(folder => {
|
||||
state.user.relationships.favourites.data.attributes.folders.find(folder => {
|
||||
if (folder.unique_id == data.unique_id) folder.name = data.name
|
||||
})
|
||||
}
|
||||
@@ -118,7 +111,7 @@ const getters = {
|
||||
permission: state => state.permission,
|
||||
isGuest: state => ! state.authorized,
|
||||
isLogged: state => state.authorized,
|
||||
app: state => state.app,
|
||||
user: state => state.user,
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<section id="viewport">
|
||||
|
||||
<ContentSidebar>
|
||||
|
||||
<!--SaaS-->
|
||||
<ContentGroup title="SaaS" class="navigator">
|
||||
<ContentGroup v-if="config.isSaaS" title="SaaS" class="navigator">
|
||||
<div class="menu-list-wrapper vertical">
|
||||
<router-link :to="{name: 'Plans'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
<SwitchInput @input="changeStatus($event, row.data.id)" class="switch" :state="row.data.attributes.status"/>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.subscribers }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
${{ row.data.attributes.price }}
|
||||
@@ -40,11 +45,6 @@
|
||||
{{ row.data.attributes.capacity_formatted }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cell-item">
|
||||
{{ row.data.attributes.subscribers }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-icons">
|
||||
<router-link :to="{name: 'PlanSettings', params: {id: row.data.id}}">
|
||||
@@ -109,6 +109,11 @@
|
||||
field: 'attributes.status',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Subscribers',
|
||||
field: 'attributes.subscribers',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Price',
|
||||
field: 'attributes.price',
|
||||
@@ -119,11 +124,6 @@
|
||||
field: 'attributes.capacity',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: 'Subscribers',
|
||||
field: 'attributes.subscribers',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.action'),
|
||||
field: 'data.action',
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
{{ row.data.attributes.role }}
|
||||
</ColorLabel>
|
||||
</td>
|
||||
<td>
|
||||
<td v-if="config.isSaaS">
|
||||
<span class="cell-item" v-if="row.relationships.subscription">
|
||||
{{ row.relationships.subscription.data.attributes.name }}
|
||||
</span>
|
||||
@@ -89,6 +89,7 @@
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import ColorLabel from '@/components/Others/ColorLabel'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import {mapGetters} from "vuex"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
@@ -106,6 +107,9 @@
|
||||
Edit2Icon,
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
@@ -124,7 +128,8 @@
|
||||
{
|
||||
label: 'Subscription Plan',
|
||||
field: 'data.attributes.role',
|
||||
sortable: true
|
||||
sortable: true,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: this.$t('admin_page_user.table.storage_used'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="single-page" v-if="app">
|
||||
<div id="single-page">
|
||||
<div id="page-content" v-if="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
|
||||
@@ -42,7 +42,16 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'UserInvoices'}" class="menu-list-item link">
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'UserSubscription'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
Subscription
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'UserInvoices'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<file-text-icon size="17"></file-text-icon>
|
||||
</div>
|
||||
@@ -60,7 +69,7 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'UserDelete'}" v-if="user.data.attributes.name !== app.user.name"
|
||||
<router-link replace :to="{name: 'UserDelete'}" v-if="user.data.attributes.name !== admin.name"
|
||||
class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<trash2-icon size="17"></trash2-icon>
|
||||
@@ -82,7 +91,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {UserIcon, HardDriveIcon, LockIcon, Trash2Icon, FileTextIcon} from 'vue-feather-icons'
|
||||
import {UserIcon, HardDriveIcon, LockIcon, Trash2Icon, FileTextIcon, CreditCardIcon} from 'vue-feather-icons'
|
||||
import StorageItemDetail from '@/components/Others/StorageItemDetail'
|
||||
import MobileHeader from '@/components/Mobile/MobileHeader'
|
||||
import SectionTitle from '@/components/Others/SectionTitle'
|
||||
@@ -95,6 +104,7 @@
|
||||
export default {
|
||||
name: 'Profile',
|
||||
components: {
|
||||
CreditCardIcon,
|
||||
HardDriveIcon,
|
||||
StorageItemDetail,
|
||||
SectionTitle,
|
||||
@@ -108,7 +118,10 @@
|
||||
Spinner,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
admin() {
|
||||
return this.$store.getters.user ? this.$store.getters.user.data.attributes : undefined
|
||||
},
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<PageTab v-if="invoices">
|
||||
<PageTabGroup>
|
||||
<PageTabGroup v-if="invoices.length > 0">
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="invoices" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr>
|
||||
@@ -35,6 +35,9 @@
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
User don't have any invoices yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<template>
|
||||
<PageTab v-if="storage">
|
||||
<PageTabGroup>
|
||||
<StorageItemDetail
|
||||
type="disk"
|
||||
:title="$t('storage.total_used', {used: storage.attributes.used})"
|
||||
:percentage="storage.attributes.percentage"
|
||||
:used="$t('storage.total_capacity', {capacity: storage.attributes.capacity})"
|
||||
/>
|
||||
<SetupBox
|
||||
v-if="! config.isSaaS || ! user.relationships.subscription"
|
||||
theme="base"
|
||||
:title="$t('user_box_storage.title')"
|
||||
:description="$t('user_box_storage.description')"
|
||||
@@ -32,6 +27,12 @@
|
||||
</ValidationProvider>
|
||||
</ValidationObserver>
|
||||
</SetupBox>
|
||||
<StorageItemDetail
|
||||
type="disk"
|
||||
:title="$t('storage.total_used', {used: storage.attributes.used})"
|
||||
:percentage="storage.attributes.percentage"
|
||||
:used="$t('storage.total_capacity', {capacity: storage.attributes.capacity})"
|
||||
/>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup>
|
||||
<b class="form-group-label">{{ $t('storage.sec_details') }}</b>
|
||||
@@ -54,9 +55,11 @@
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'UserStorage',
|
||||
props: ['user'],
|
||||
components: {
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
@@ -67,6 +70,9 @@
|
||||
SetupBox,
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTabGroup v-if="subscription">
|
||||
|
||||
<!--Info about active subscription-->
|
||||
<div v-if="! subscription.canceled" class="state active">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.attributes.name + ' - ' + subscription.attributes.capacity_formatted"/>
|
||||
<ListInfoItem class="list-item" title="Billed" content="Monthly"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Created At" :content="subscription.attributes.created_at"/>
|
||||
<ListInfoItem class="list-item" title="Renews At" :content="subscription.attributes.ends_at"/>
|
||||
</ListInfo>
|
||||
</div>
|
||||
|
||||
<!--Info about canceled subscription-->
|
||||
<div v-if="subscription.attributes.canceled" class="state canceled">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.attributes.name"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Canceled At" :content="subscription.attributes.canceled_at"/>
|
||||
<ListInfoItem class="list-item" title="Ends At" :content="subscription.attributes.ends_at"/>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
User don't have any subscription yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import ListInfoItem from '@/components/Others/ListInfoItem'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import ListInfo from '@/components/Others/ListInfo'
|
||||
import {ExternalLinkIcon} from "vue-feather-icons"
|
||||
import { mapGetters } from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UserSubscription',
|
||||
components: {
|
||||
ExternalLinkIcon,
|
||||
DatatableWrapper,
|
||||
ListInfoItem,
|
||||
PageTabGroup,
|
||||
ButtonBase,
|
||||
ListInfo,
|
||||
PageTab,
|
||||
},
|
||||
computed: {
|
||||
status() {
|
||||
if (this.subscription.attributes.canceled) {
|
||||
return 'Canceled'
|
||||
}
|
||||
if (this.subscription.attributes.active) {
|
||||
return 'Active'
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
subscription: undefined,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/users/' + this.$route.params.id + '/subscription')
|
||||
.then(response => {
|
||||
this.subscription = response.data.data
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
|
||||
.cancel-plan {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.list-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.list-item {
|
||||
flex: 0 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -88,6 +88,8 @@
|
||||
checkedAccount: undefined,
|
||||
loginPassword: 'vuefilemanager',
|
||||
loginEmail: 'howdy@hi5ve.digital',
|
||||
//loginPassword: '',
|
||||
//loginEmail: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<template>
|
||||
<section id="viewport" v-if="app">
|
||||
<section id="viewport" v-if="user">
|
||||
|
||||
<ContentSidebar>
|
||||
|
||||
<ContentGroup v-if="config.isSaaS && storage.used > 95">
|
||||
<UpgradeSidebarBanner />
|
||||
</ContentGroup>
|
||||
|
||||
<!--Locations-->
|
||||
<ContentGroup :title="$t('sidebar.locations_title')">
|
||||
<div class="menu-list-wrapper vertical">
|
||||
@@ -28,10 +32,10 @@
|
||||
|
||||
<!--Navigator-->
|
||||
<ContentGroup :title="$t('sidebar.navigator_title')" class="navigator">
|
||||
<span class="empty-note navigator" v-if="app.tree.length == 0">
|
||||
<span class="empty-note navigator" v-if="tree.length == 0">
|
||||
{{ $t('sidebar.folders_empty') }}
|
||||
</span>
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="items" v-for="items in app.tree"
|
||||
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="items" v-for="items in tree"
|
||||
:key="items.unique_id"/>
|
||||
</ContentGroup>
|
||||
|
||||
@@ -45,14 +49,14 @@
|
||||
@drop="dragFinish($event)"
|
||||
>
|
||||
<transition-group tag="div" class="menu-list" name="folder-item">
|
||||
<span class="empty-note favourites" v-if="app.favourites.length == 0" :key="0">
|
||||
<span class="empty-note favourites" v-if="favourites.length == 0" :key="0">
|
||||
{{ $t('sidebar.favourites_empty') }}
|
||||
</span>
|
||||
|
||||
<a @click.stop="openFolder(folder)"
|
||||
class="menu-list-item"
|
||||
:class="{'is-current': (folder && currentFolder) && (currentFolder.unique_id === folder.unique_id)}"
|
||||
v-for="folder in app.favourites"
|
||||
v-for="folder in favourites"
|
||||
:key="folder.unique_id">
|
||||
<div>
|
||||
<folder-icon size="17" class="folder-icon"></folder-icon>
|
||||
@@ -70,6 +74,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UpgradeSidebarBanner from '@/components/Others/UpgradeSidebarBanner'
|
||||
import TreeMenuNavigator from '@/components/Others/TreeMenuNavigator'
|
||||
import ContentFileView from '@/components/Others/ContentFileView'
|
||||
import ContentSidebar from '@/components/Sidebar/ContentSidebar'
|
||||
@@ -86,6 +91,7 @@
|
||||
export default {
|
||||
name: 'FilesView',
|
||||
components: {
|
||||
UpgradeSidebarBanner,
|
||||
TreeMenuNavigator,
|
||||
ContentFileView,
|
||||
ContentSidebar,
|
||||
@@ -96,7 +102,16 @@
|
||||
XIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app', 'homeDirectory', 'currentFolder']),
|
||||
...mapGetters(['user', 'homeDirectory', 'currentFolder', 'config']),
|
||||
favourites() {
|
||||
return this.user.relationships.favourites.data.attributes.folders
|
||||
},
|
||||
tree() {
|
||||
return this.user.relationships.tree.data.attributes.folders
|
||||
},
|
||||
storage() {
|
||||
return this.$store.getters.user.relationships.storage.data.attributes
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -129,7 +144,7 @@
|
||||
if (this.draggedItem && this.draggedItem.type !== 'folder') return
|
||||
|
||||
// Check if folder exist in favourites
|
||||
if (this.app.favourites.find(folder => folder.unique_id == this.draggedItem.unique_id)) return
|
||||
if (this.favourites.find(folder => folder.unique_id == this.draggedItem.unique_id)) return
|
||||
|
||||
// Store favourites folder
|
||||
this.$store.dispatch('addToFavourites', this.draggedItem)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="single-page">
|
||||
<div id="single-page" v-if="user">
|
||||
<div id="page-content" class="medium-width" v-if="! isLoading">
|
||||
<MobileHeader :title="$router.currentRoute.meta.title"/>
|
||||
<PageHeader :title="$router.currentRoute.meta.title"/>
|
||||
@@ -12,20 +12,20 @@
|
||||
<div class="avatar">
|
||||
<UserImageInput
|
||||
v-model="avatar"
|
||||
:avatar="profile.data.attributes.avatar"
|
||||
:avatar="user.data.attributes.avatar"
|
||||
/>
|
||||
</div>
|
||||
<div class="info">
|
||||
<b class="name">
|
||||
{{ profile.data.attributes.name }}
|
||||
<ColorLabel :color="subscriptionColor">
|
||||
{{ user.data.attributes.name }}
|
||||
<ColorLabel v-if="config.isSaaS" :color="subscriptionColor">
|
||||
{{ subscriptionStatus }}
|
||||
</ColorLabel>
|
||||
</b>
|
||||
<span class="email">{{ profile.data.attributes.email }}</span>
|
||||
<span class="email">{{ user.data.attributes.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="headline-actions">
|
||||
<div v-if="config.isSaaS" class="headline-actions">
|
||||
<router-link :to="{name: 'UpgradePlan'}">
|
||||
<ButtonBase button-style="secondary" type="button">
|
||||
Upgrade Plan
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'Subscription'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<credit-card-icon size="17"></credit-card-icon>
|
||||
</div>
|
||||
@@ -63,7 +63,7 @@
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<router-link replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<router-link v-if="config.isSaaS" replace :to="{name: 'Invoice'}" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<file-text-icon size="17"></file-text-icon>
|
||||
</div>
|
||||
@@ -80,19 +80,10 @@
|
||||
{{ $t('menu.password') }}
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<!--<router-link replace :to="{name: 'UserDelete'}" v-if="user.attributes.name !== app.user.name" class="menu-list-item link">
|
||||
<div class="icon">
|
||||
<trash2-icon size="17"></trash2-icon>
|
||||
</div>
|
||||
<div class="label">
|
||||
{{ $t('admin_page_user.tabs.delete') }}
|
||||
</div>
|
||||
</router-link>-->
|
||||
</div>
|
||||
|
||||
<!--Router Content-->
|
||||
<router-view :user="profile" />
|
||||
<router-view :user="user" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="loader" v-if="isLoading">
|
||||
@@ -108,6 +99,7 @@
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import ColorLabel from '@/components/Others/ColorLabel'
|
||||
import Spinner from '@/components/FilesView/Spinner'
|
||||
import { mapGetters } from 'vuex'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
CreditCardIcon,
|
||||
@@ -133,26 +125,19 @@
|
||||
LockIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user', 'config']),
|
||||
subscriptionStatus() {
|
||||
return this.profile.relationships.subscription ? 'Subscription' : 'Free'
|
||||
return this.user.relationships.subscription ? 'Premium' : 'Free'
|
||||
},
|
||||
subscriptionColor() {
|
||||
return this.profile.relationships.subscription ? 'green' : 'purple'
|
||||
return this.user.relationships.subscription ? 'green' : 'purple'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatar: undefined,
|
||||
profile: undefined,
|
||||
isLoading: true,
|
||||
isLoading: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/profile')
|
||||
.then(response => {
|
||||
this.profile = response.data
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -206,11 +206,14 @@
|
||||
|
||||
// Send order request
|
||||
axios
|
||||
.post('/api/upgrade', {
|
||||
.post('/api/subscription/upgrade', {
|
||||
billing: this.billing,
|
||||
plan: this.requestedPlan,
|
||||
})
|
||||
.then(response => {
|
||||
.then(() => {
|
||||
|
||||
// Update user data
|
||||
this.$store.dispatch('getAppData')
|
||||
|
||||
// End loading
|
||||
this.isSubmitted = false
|
||||
@@ -232,7 +235,7 @@
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get('/api/profile')
|
||||
axios.get('/api/user')
|
||||
.then(response => {
|
||||
|
||||
if (! this.requestedPlan) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<PageTab v-if="invoices">
|
||||
<PageTabGroup>
|
||||
<PageTabGroup v-if="invoices.length > 0">
|
||||
<DatatableWrapper :paginator="true" :columns="columns" :data="invoices" class="table">
|
||||
<template scope="{ row }">
|
||||
<tr>
|
||||
@@ -35,6 +35,9 @@
|
||||
</template>
|
||||
</DatatableWrapper>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
You don't have any invoices yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,27 +3,27 @@
|
||||
<PageTabGroup>
|
||||
<ValidationObserver ref="password" @submit.prevent="resetPassword" v-slot="{ invalid }" tag="form"
|
||||
class="form block-form">
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>{{ $t('page_create_password.label_new_pass') }}:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
|
||||
rules="required" v-slot="{ errors }">
|
||||
<input v-model="newPassword" :placeholder="$t('page_create_password.label_new_pass')"
|
||||
type="password"
|
||||
:class="{'is-error': errors[0]}"/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
|
||||
rules="required" v-slot="{ errors }">
|
||||
<input v-model="newPasswordConfirmation"
|
||||
:placeholder="$t('page_create_password.label_confirm_pass')" type="password"
|
||||
:class="{'is-error': errors[0]}"/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
<div class="wrapper-inline">
|
||||
<div class="block-wrapper">
|
||||
<label>{{ $t('page_create_password.label_new_pass') }}:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
|
||||
rules="required" v-slot="{ errors }">
|
||||
<input v-model="newPassword" :placeholder="$t('page_create_password.label_new_pass')"
|
||||
type="password"
|
||||
:class="{'is-error': errors[0]}"/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
|
||||
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
|
||||
rules="required" v-slot="{ errors }">
|
||||
<input v-model="newPasswordConfirmation"
|
||||
:placeholder="$t('page_create_password.label_confirm_pass')" type="password"
|
||||
:class="{'is-error': errors[0]}"/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
@@ -46,7 +46,6 @@
|
||||
import PageHeader from '@/components/Others/PageHeader'
|
||||
import ThemeLabel from '@/components/Others/ThemeLabel'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {mapGetters} from 'vuex'
|
||||
import {events} from '@/bus'
|
||||
import axios from 'axios'
|
||||
|
||||
@@ -64,9 +63,6 @@
|
||||
ThemeLabel,
|
||||
required,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['app']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
newPasswordConfirmation: '',
|
||||
@@ -125,6 +121,10 @@
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
.form {
|
||||
|
||||
@@ -1,38 +1,130 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<PageTabGroup>
|
||||
<PageTabGroup v-if="subscription">
|
||||
|
||||
<!--Info about active subscription-->
|
||||
<div v-if="! subscription.canceled" class="state active">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.name + ' - ' + subscription.capacity_formatted"/>
|
||||
<ListInfoItem class="list-item" title="Billed" content="Monthly"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Created At" :content="subscription.created_at"/>
|
||||
<ListInfoItem class="list-item" title="Renews At" :content="subscription.ends_at"/>
|
||||
</ListInfo>
|
||||
<div class="cancel-plan">
|
||||
<ButtonBase
|
||||
@click.native="cancelSubscription"
|
||||
:button-style="cancelButtonStyle"
|
||||
class="cancel-button">
|
||||
{{ cancelButtonText }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Info about canceled subscription-->
|
||||
<div v-if="subscription.canceled" class="state canceled">
|
||||
<ListInfo class="list-info">
|
||||
<ListInfoItem class="list-item" title="Plan" :content="subscription.name"/>
|
||||
<ListInfoItem class="list-item" title="Status" :content="status"/>
|
||||
<ListInfoItem class="list-item" title="Canceled At" :content="subscription.canceled_at"/>
|
||||
<ListInfoItem class="list-item" title="Ends At" :content="subscription.ends_at"/>
|
||||
</ListInfo>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
<PageTabGroup v-else>
|
||||
You don't have any subscription yet.
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
|
||||
import {ExternalLinkIcon} from "vue-feather-icons";
|
||||
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
|
||||
import ListInfoItem from '@/components/Others/ListInfoItem'
|
||||
import ButtonBase from '@/components/FilesView/ButtonBase'
|
||||
import PageTab from '@/components/Others/Layout/PageTab'
|
||||
import ListInfo from '@/components/Others/ListInfo'
|
||||
import {ExternalLinkIcon} from "vue-feather-icons"
|
||||
import { mapGetters } from 'vuex'
|
||||
import {events} from "@/bus"
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'UserSubscription',
|
||||
components: {
|
||||
PageTabGroup,
|
||||
PageTab,
|
||||
DatatableWrapper,
|
||||
ExternalLinkIcon,
|
||||
DatatableWrapper,
|
||||
ListInfoItem,
|
||||
PageTabGroup,
|
||||
ButtonBase,
|
||||
ListInfo,
|
||||
PageTab,
|
||||
},
|
||||
computed: {
|
||||
cancelButtonText() {
|
||||
return this.isConfirmedCancel ? this.$t('popup_share_edit.confirm') : 'Cancel Plan'
|
||||
},
|
||||
cancelButtonStyle() {
|
||||
return this.isConfirmedCancel ? 'danger-solid' : 'danger'
|
||||
},
|
||||
subscription() {
|
||||
return this.$store.getters.user.relationships.subscription
|
||||
? this.$store.getters.user.relationships.subscription.data.attributes
|
||||
: undefined
|
||||
},
|
||||
status() {
|
||||
if (this.subscription.canceled) {
|
||||
return 'Canceled'
|
||||
}
|
||||
if (this.subscription.active) {
|
||||
return 'Active'
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
invoices: undefined,
|
||||
isConfirmedCancel: false,
|
||||
isDeleting: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
/* axios.get('/api/user/subscription')
|
||||
.then(response => {
|
||||
this.invoices = response.data.data
|
||||
this.isLoading = false
|
||||
})*/
|
||||
methods: {
|
||||
cancelSubscription() {
|
||||
|
||||
// Set confirm button
|
||||
if (! this.isConfirmedCancel) {
|
||||
|
||||
this.isConfirmedCancel = true
|
||||
} else {
|
||||
|
||||
// Start deleting spinner button
|
||||
this.isDeleting = true
|
||||
|
||||
// Send delete request
|
||||
axios
|
||||
.post('/api/subscription/cancel')
|
||||
.then(() => {
|
||||
|
||||
// Update user data
|
||||
this.$store.dispatch('getAppData')
|
||||
|
||||
// End deleting spinner button
|
||||
this.isDeleting = false
|
||||
|
||||
events.$emit('alert:open', {
|
||||
emoji: '👍',
|
||||
title: 'Subscription Was Canceled',
|
||||
message: 'You\'ll continue to have access to the features you\'ve paid for until the end of your billing cycle.',
|
||||
buttonStyle: 'theme',
|
||||
button: 'I\'m done'
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
// End deleting spinner button
|
||||
this.isDeleting = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -40,12 +132,19 @@
|
||||
<style lang="scss" scoped>
|
||||
@import '@assets/vue-file-manager/_variables';
|
||||
@import '@assets/vue-file-manager/_mixins';
|
||||
@import '@assets/vue-file-manager/_forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
.cancel-plan {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.list-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.list-item {
|
||||
flex: 0 0 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ $light_background: #f4f5f6;
|
||||
$dark_background: #EBEBEB;
|
||||
$shadow: 0 7px 25px 1px rgba(0, 0, 0, 0.12);
|
||||
|
||||
$light_mode_input_background: #f4f5f6;
|
||||
$light_mode_input_background: hsla(210, 10%, 98%, 1);
|
||||
$light_mode_popup_shadow: 0 15px 50px 10px rgba(26,38,74,0.12);
|
||||
$light_mode_vignette: rgba(9, 8, 12, 0.35);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
hasAuthCookie: {{ Cookie::has('token') ? 1 : 0 }},
|
||||
userRegistration: {{ config('vuefilemanager.registration') ? 1 : 0 }},
|
||||
storageLimit: {{ config('vuefilemanager.limit_storage_by_capacity') ? 1 : 0 }},
|
||||
isSaaS: 1,
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user