dashboard include

This commit is contained in:
carodej
2020-07-05 09:14:17 +02:00
parent e1ebb70035
commit 5a5125967f
61 changed files with 1532 additions and 617 deletions

View File

@@ -1,5 +1,5 @@
<template>
<PageTab class="form-fixed-width">
<PageTab :is-loading="isLoading" class="form-fixed-width">
<!--Personal Information-->
<PageTabGroup>
@@ -9,7 +9,7 @@
<div class="block-wrapper">
<label>App Title:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Title" rules="required" v-slot="{ errors }">
<input v-model="app.title" placeholder="Type your app title" type="text" :class="{'is-error': errors[0]}"/>
<input @input="$updateText('/settings', 'app_title', app.title)" v-model="app.title" placeholder="Type your app title" type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
@@ -17,22 +17,24 @@
<div class="block-wrapper">
<label>App Description:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Description" rules="required" v-slot="{ errors }">
<input v-model="app.description" placeholder="Type your app description" type="text" :class="{'is-error': errors[0]}"/>
<input @input="$updateText('/settings', 'app_description', app.description)" v-model="app.description" placeholder="Type your app description" type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<FormLabel class="mt-70">Appearance</FormLabel>
<div class="block-wrapper">
<label>App Logo (optional):</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Logo" v-slot="{ errors }">
<ImageInput v-model="app.logo" :error="errors[0]"/>
<ImageInput @input="$updateImage('/settings', 'app_logo', app.logo)" :image="'/' + app.logo" v-model="app.logo" :error="errors[0]"/>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>App Favicon (optional):</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }">
<ImageInput v-model="app.favicon" :error="errors[0]"/>
<ImageInput @input="$updateImage('/settings', 'app_favicon', app.favicon)" :image="'/' + app.favicon" v-model="app.favicon" :error="errors[0]"/>
</ValidationProvider>
</div>
</div>
@@ -72,7 +74,7 @@
},
data() {
return {
isLoading: false,
isLoading: true,
app: {
title: '',
description: '',
@@ -80,6 +82,21 @@
favicon: undefined,
},
}
},
mounted() {
axios.get('/api/settings', {
params: {
column: 'app_title|app_description|app_logo|app_favicon'
}
})
.then(response => {
this.isLoading = false
this.app.title = response.data.app_title
this.app.description = response.data.app_description
this.app.logo = response.data.app_logo
this.app.favicon = response.data.app_favicon
})
}
}
</script>

View File

@@ -1,5 +1,5 @@
<template>
<PageTab class="form-fixed-width">
<PageTab :is-loading="isLoading" class="form-fixed-width">
<!--Personal Information-->
<PageTabGroup>
@@ -10,7 +10,7 @@
<label>Company Name:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Name"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_name" placeholder="Type your company name"
<input @input="$updateText('/settings', 'billing_name', billingInformation.billing_name)" v-model="billingInformation.billing_name" placeholder="Type your company name"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -20,7 +20,7 @@
<label>VAT Number:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Vat Number"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_vat_number" placeholder="Type your VAT number"
<input @input="$updateText('/settings', 'billing_vat_number', billingInformation.billing_vat_number)" v-model="billingInformation.billing_vat_number" placeholder="Type your VAT number"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -32,7 +32,7 @@
<label>Billing Country:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Country"
rules="required" v-slot="{ errors }">
<SelectInput v-model="billingInformation.billing_country" :options="countries" placeholder="Select your billing country" :isError="errors[0]"/>
<SelectInput @input="$updateText('/settings', 'billing_country', billingInformation.billing_country)" v-model="billingInformation.billing_country" :default="billingInformation.billing_country" :options="countries" placeholder="Select your billing country" :isError="errors[0]"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
@@ -41,7 +41,7 @@
<label>Billing Address:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Address"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_address" placeholder="Type your billing address"
<input @input="$updateText('/settings', 'billing_address', billingInformation.billing_address)" v-model="billingInformation.billing_address" placeholder="Type your billing address"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -52,7 +52,7 @@
<label>Billing City:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing City"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_city" placeholder="Type your billing city"
<input @input="$updateText('/settings', 'billing_city', billingInformation.billing_city)" v-model="billingInformation.billing_city" placeholder="Type your billing city"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -61,7 +61,7 @@
<label>Billing Postal Code:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Postal Code"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_postal_code"
<input @input="$updateText('/settings', 'billing_postal_code', billingInformation.billing_postal_code)" v-model="billingInformation.billing_postal_code"
placeholder="Type your billing postal code" type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -72,7 +72,7 @@
<label>Billing State:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing State"
rules="required" v-slot="{ errors }">
<input v-model="billingInformation.billing_state" placeholder="Type your billing state"
<input @input="$updateText('/settings', 'billing_state', billingInformation.billing_state)" v-model="billingInformation.billing_state" placeholder="Type your billing state"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -82,7 +82,7 @@
<label>Billing Phone Number (optional):</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Billing Phone Number"
v-slot="{ errors }">
<input v-model="billingInformation.billing_phone_number" placeholder="Type your billing phone number"
<input @input="$updateText('/settings', 'billing_phone_number', billingInformation.billing_phone_number)" v-model="billingInformation.billing_phone_number" placeholder="Type your billing phone number"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
@@ -124,7 +124,7 @@
},
data() {
return {
isLoading: false,
isLoading: true,
countries: [
{label: 'Afghanistan', value: 'AF'},
{label: 'Åland Islands', value: 'AX'},
@@ -381,6 +381,25 @@
billing_name: '',
}
}
},
mounted() {
axios.get('/api/settings', {
params: {
column: 'billing_phone_number|billing_postal_code|billing_vat_number|billing_address|billing_country|billing_state|billing_city|billing_name'
}
})
.then(response => {
this.isLoading = false
this.billingInformation.billing_phone_number = response.data.billing_phone_number
this.billingInformation.billing_postal_code = response.data.billing_postal_code
this.billingInformation.billing_vat_number = response.data.billing_vat_number
this.billingInformation.billing_address = response.data.billing_address
this.billingInformation.billing_country = response.data.billing_country
this.billingInformation.billing_state = response.data.billing_state
this.billingInformation.billing_city = response.data.billing_city
this.billingInformation.billing_name = response.data.billing_name
})
}
}
</script>

View File

@@ -1,11 +1,15 @@
<template>
<PageTab class="form-fixed-width">
<PageTab :is-loading="isLoading" class="form-fixed-width">
<!--Personal Information-->
<PageTabGroup>
<div class="form block-form">
<ValidationObserver @submit.prevent="EmailSetupSubmit" ref="EmailSetup" v-slot="{ invalid }" tag="form" class="form block-form">
<FormLabel>Email Setup</FormLabel>
<InfoBox>
<p>This form is not fully pre-filled for security reasons. Your email settings is available in your <b>.env</b> file. For apply new Email settings, please confirm your options by button at the end of formular.</p>
</InfoBox>
<div class="block-wrapper">
<label>Mail Driver:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Mail Driver" rules="required" v-slot="{ errors }">
@@ -53,7 +57,12 @@
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
</div>
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit"
button-style="theme" class="submit-button">
Save Email Settings
</ButtonBase>
</ValidationObserver>
</PageTabGroup>
</PageTab>
</template>
@@ -70,6 +79,7 @@
import PageTab from '@/components/Others/Layout/PageTab'
import InfoBox from '@/components/Others/Forms/InfoBox'
import {required} from 'vee-validate/dist/rules'
import {events} from "@/bus"
import axios from 'axios'
export default {
@@ -90,7 +100,8 @@
},
data() {
return {
isLoading: false,
isLoading: true,
isSendingRequest: false,
encryptionList: [
{
label: 'TLS',
@@ -110,6 +121,49 @@
encryption: '',
}
}
},
methods: {
async EmailSetupSubmit() {
// Validate fields
const isValid = await this.$refs.EmailSetup.validate();
if (!isValid) return;
// Start loading
this.isSendingRequest = true
// Send request to get verify account
axios
.put('/api/settings/email', this.mail)
.then(response => {
// End loading
this.isSendingRequest = false
events.$emit('toaster', {
type: 'success',
message: 'Your email settings was updated successfully',
})
})
.catch(error => {
// End loading
this.isSendingRequest = false
})
},
},
mounted() {
axios.get('/api/settings', {
params: {
column: 'app_title|app_description|app_logo|app_favicon'
}
})
.then(response => {
this.isLoading = false
this.app.title = response.data.app_title
})
}
}
</script>

View File

@@ -1,56 +1,25 @@
<template>
<PageTab class="form-fixed-width">
<PageTab :is-loading="isLoading" class="form-fixed-width">
<!--Personal Information-->
<PageTabGroup>
<div class="form block-form">
<FormLabel>Others Settings</FormLabel>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Allow User Registration:</label>
</div>
<SwitchInput v-model="app.userRegistration" class="switch" :state="app.userRegistration"/>
</div>
</div>
</div>
<div class="block-wrapper">
<label>Contact Email:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Contact Email"
rules="required" v-slot="{ errors }">
<input v-model="app.contactMail" placeholder="Type your contact email" type="email" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Google Analytics Code (optional):</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Google Analytics Code"
v-slot="{ errors }">
<input v-model="app.googleAnalytics" placeholder="Paste your Google Analytics Code"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<FormLabel>Users and Storage</FormLabel>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Storage Limitation:</label>
</div>
<SwitchInput v-model="app.storageLimitation" class="switch" :state="app.storageLimitation"/>
<SwitchInput @input="$updateText('/settings', 'storage_limitation', app.storageLimitation)" v-model="app.storageLimitation" class="switch" :state="app.storageLimitation"/>
</div>
</div>
</div>
<div class="block-wrapper" v-if="app.storageLimitation">
<label>Default Storage Space for Accounts:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Default Storage Space" rules="required" v-slot="{ errors }">
<input v-model="app.defaultStorage"
<input @input="$updateText('/settings', 'storage_default', app.defaultStorage)"
v-model="app.defaultStorage"
min="1"
max="999999999"
placeholder="Set default storage space in GB"
@@ -60,6 +29,37 @@
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Allow User Registration:</label>
</div>
<SwitchInput @input="$updateText('/settings', 'registration', app.userRegistration)" v-model="app.userRegistration" class="switch" :state="app.userRegistration"/>
</div>
</div>
</div>
<FormLabel class="mt-70">Others Settings</FormLabel>
<div class="block-wrapper">
<label>Contact Email:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Contact Email"
rules="required" v-slot="{ errors }">
<input @input="$updateText('/settings', 'contact_email', app.contactMail)" v-model="app.contactMail"
placeholder="Type your contact email" type="email" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Google Analytics Code (optional):</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Google Analytics Code"
v-slot="{ errors }">
<input @input="$updateText('/settings', 'google_analytics', app.googleAnalytics)" v-model="app.googleAnalytics"
placeholder="Paste your Google Analytics Code"
type="text" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
</div>
</PageTabGroup>
</PageTab>
@@ -99,7 +99,7 @@
},
data() {
return {
isLoading: false,
isLoading: true,
app: {
contactMail: '',
googleAnalytics: '',
@@ -108,6 +108,22 @@
storageLimitation: 1,
},
}
},
mounted() {
axios.get('/api/settings', {
params: {
column: 'contact_email|google_analytics|storage_default|registration|storage_limitation'
}
})
.then(response => {
this.isLoading = false
this.app.contactMail = response.data.contact_email
this.app.googleAnalytics = response.data.google_analytics
this.app.defaultStorage = response.data.storage_default
this.app.userRegistration = parseInt(response.data.registration)
this.app.storageLimitation = parseInt(response.data.storage_limitation)
})
}
}
</script>

View File

@@ -0,0 +1,198 @@
<template>
<div id="single-page">
<div id="page-content" v-if="! isLoading">
<div class="dashboard-headline">
<div class="logo">
<a href="https://vuefilemanager.com" target="_blank">
<img src="/assets/images/vuefilemanager-horizontal-logo.svg" alt="VueFileManager">
</a>
</div>
<div class="metadata">
<a href="https://vuefilemanager.com/changelog" target="_blank" class="meta">
<span class="meta-title">Version:</span>
<ColorLabel color="purple">
{{ data.app_version }}
</ColorLabel>
</a>
<a href="https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986" target="_blank" class="meta">
<span class="meta-title">License:</span>
<ColorLabel color="purple">
Extended
</ColorLabel>
</a>
<a href="https://vuefilemanager.com" target="_blank" class="became-backer">
<div class="icon">
<credit-card-icon size="15"></credit-card-icon>
</div>
<span class="content">
Become a Backer
</span>
</a>
</div>
</div>
<div class="widgets-total">
<WidgetTotals
class="widget"
icon="users"
title="Total Users"
:value="data.total_users"
link-route="Users"
link-name="Show All Users"
></WidgetTotals>
<WidgetTotals
class="widget"
icon="hard-drive"
title="Total Space Used"
:value="data.total_used_space"
link-route="Users"
link-name="Show All Users"
></WidgetTotals>
<WidgetTotals
class="widget"
icon="star"
title="Total Premium Users"
:value="data.total_premium_users"
link-route="Plans"
link-name="Show All Plans"
></WidgetTotals>
</div>
<div class="widget-users">
<WidgetLatestRegistrations
class="widget"
icon="users"
title="Latest Registrations"
/>
</div>
</div>
<div id="loader" v-if="isLoading">
<Spinner></Spinner>
</div>
</div>
</template>
<script>
import WidgetLatestRegistrations from '@/components/Admin/WidgetLatestRegistrations'
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import EmptyPageContent from '@/components/Others/EmptyPageContent'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import MobileHeader from '@/components/Mobile/MobileHeader'
import SectionTitle from '@/components/Others/SectionTitle'
import WidgetTotals from '@/components/Admin/WidgetTotals'
import ButtonBase from '@/components/FilesView/ButtonBase'
import PageHeader from '@/components/Others/PageHeader'
import ColorLabel from '@/components/Others/ColorLabel'
import Spinner from '@/components/FilesView/Spinner'
import {CreditCardIcon} from "vue-feather-icons"
import axios from 'axios'
export default {
name: 'Dashboard',
components: {
WidgetLatestRegistrations,
MobileActionButton,
EmptyPageContent,
DatatableWrapper,
WidgetTotals,
CreditCardIcon,
SectionTitle,
MobileHeader,
SwitchInput,
PageHeader,
ButtonBase,
ColorLabel,
Spinner,
},
data() {
return {
isLoading: false,
data: undefined,
}
},
methods: {
changeStatus(val, id) {
this.$updateText('/plans/' + id + '/update', 'is_active', val)
}
},
created() {
axios.get('/api/dashboard')
.then(response => {
this.data = response.data
this.isLoading = false
})
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.widgets-total {
display: flex;
flex: 0 0 33%;
margin: 0 -20px 20px;
.widget {
width: 100%;
padding: 20px;
}
}
.dashboard-headline {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.became-backer {
background: rgba($yellow, 0.1);
display: inline-block;
padding: 5px 10px;
border-radius: 6px;
margin-left: 40px;
cursor: pointer;
.icon, .content {
display: inline-block;
vertical-align: middle;
}
.icon {
margin-right: 10px;
line-height: 0;
rect, line {
stroke: $yellow;
}
}
.content {
color: $yellow;
font-weight: 700;
@include font-size(14);
}
}
.metadata {
.meta {
display: inline-block;
margin-left: 20px;
}
.meta-title {
@include font-size(14);
font-weight: 700;
}
}
@media only screen and (max-width: 690px) {
}
@media (prefers-color-scheme: dark) {
}
</style>

View File

@@ -1,219 +0,0 @@
<template>
<div id="single-page">
<div id="page-content" v-if="! isLoading">
<MobileHeader :title="$router.currentRoute.meta.title"/>
<PageHeader :title="$router.currentRoute.meta.title"/>
<div class="content-page">
<DatatableWrapper :paginator="false" :columns="columns" :data="gateways" class="table table-users">
<template scope="{ row }">
<tr>
<td style="min-width: 200px;">
<router-link :to="{name: 'GatewaySettings', params: {slug: row.data.attributes.slug}}">
<DatatableCellImage
:image="row.data.attributes.logo"
:title="row.data.attributes.name"
/>
</router-link>
</td>
<td>
<span class="cell-item">
<SwitchInput
@input="changeStatus($event, row.data.attributes.slug)"
:state="row.data.attributes.status"
class="switch"
/>
</span>
</td>
<td>
<span class="cell-item">
{{ row.data.attributes.payment_processed }}
</span>
</td>
<td>
<div class="action-icons">
<router-link :to="{name: 'GatewaySettings', params: {slug: row.data.attributes.slug}}">
<edit-2-icon size="15" class="icon icon-edit"></edit-2-icon>
</router-link>
</div>
</td>
</tr>
</template>
</DatatableWrapper>
</div>
</div>
<div id="loader" v-if="isLoading">
<Spinner></Spinner>
</div>
</div>
</template>
<script>
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import MobileHeader from '@/components/Mobile/MobileHeader'
import SectionTitle from '@/components/Others/SectionTitle'
import ButtonBase from '@/components/FilesView/ButtonBase'
import {Trash2Icon, Edit2Icon} from "vue-feather-icons";
import PageHeader from '@/components/Others/PageHeader'
import ColorLabel from '@/components/Others/ColorLabel'
import Spinner from '@/components/FilesView/Spinner'
import axios from 'axios'
export default {
name: 'Plans',
components: {
DatatableCellImage,
MobileActionButton,
DatatableWrapper,
SectionTitle,
MobileHeader,
SwitchInput,
Trash2Icon,
PageHeader,
ButtonBase,
ColorLabel,
Edit2Icon,
Spinner,
},
data() {
return {
isLoading: true,
gateways: undefined,
columns: [
{
label: 'Payment Gateway',
field: 'data.attributes.gateway',
sortable: true
},
{
label: 'Status',
field: 'data.attributes.status',
sortable: true
},
{
label: 'Payments Processed',
field: 'data.attributes.payment_processed',
sortable: true
},
{
label: this.$t('admin_page_user.table.action'),
field: 'data.action',
sortable: false
},
],
}
},
methods: {
changeStatus(val, type) {
this.$updateText('/gateways/' + type, 'status', val)
}
},
created() {
axios.get('/api/gateways')
.then(response => {
this.gateways = response.data.data
this.isLoading = false
})
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.user-thumbnail {
display: flex;
align-items: center;
cursor: pointer;
.avatar {
margin-right: 20px;
line-height: 0;
img {
line-height: 0;
width: 48px;
height: 48px;
border-radius: 8px;
}
}
.info {
.name {
max-width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.name {
@include font-size(15);
line-height: 1;
}
}
}
.table-tools {
background: white;
display: flex;
justify-content: space-between;
padding: 15px 0 10px;
position: sticky;
top: 40px;
z-index: 9;
}
.table {
.cell-item {
@include font-size(15);
white-space: nowrap;
}
.name {
font-weight: 700;
cursor: pointer;
}
}
@media only screen and (max-width: 690px) {
.table-tools {
padding: 0 0 5px;
}
}
@media (prefers-color-scheme: dark) {
.table-tools {
background: $dark_mode_background;
}
.action-icons {
.icon {
cursor: pointer;
circle, path, line, polyline {
stroke: $dark_mode_text_primary;
}
}
}
.user-thumbnail {
.info {
.email {
color: $dark_mode_text_secondary;
}
}
}
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<div id="single-page">
<div id="page-content" v-if="! isLoading">
<div id="page-content" v-if="! isLoading && invoices.length > 0">
<MobileHeader :title="$router.currentRoute.meta.title"/>
<PageHeader :title="$router.currentRoute.meta.title"/>
@@ -9,7 +9,7 @@
<template scope="{ row }">
<tr>
<td>
<a :href="'/invoice/' + row.data.id" target="_blank" class="cell-item">
<a :href="$getInvoiceLink(row.data.attributes.customer, row.data.id)" target="_blank" class="cell-item">
{{ row.data.attributes.order }}
</a>
</td>
@@ -42,7 +42,7 @@
</td>
<td>
<div class="action-icons">
<a :href="'/invoice/' + row.data.id" target="_blank">
<a :href="$getInvoiceLink(row.data.attributes.customer, row.data.id)" target="_blank">
<external-link-icon size="15" class="icon"></external-link-icon>
</a>
</div>
@@ -52,6 +52,13 @@
</DatatableWrapper>
</div>
</div>
<EmptyPageContent
v-if="! isLoading && invoices.length === 0"
icon="file-text"
title="You dont have any invoices yet"
description="All customers invoices will be showed here."
>
</EmptyPageContent>
<div id="loader" v-if="isLoading">
<Spinner></Spinner>
</div>
@@ -62,22 +69,24 @@
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import EmptyPageContent from '@/components/Others/EmptyPageContent'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import MobileHeader from '@/components/Mobile/MobileHeader'
import SectionTitle from '@/components/Others/SectionTitle'
import ButtonBase from '@/components/FilesView/ButtonBase'
import {ExternalLinkIcon} from "vue-feather-icons";
import PageHeader from '@/components/Others/PageHeader'
import ColorLabel from '@/components/Others/ColorLabel'
import Spinner from '@/components/FilesView/Spinner'
import {ExternalLinkIcon} from "vue-feather-icons";
import axios from 'axios'
export default {
name: 'Invoices',
components: {
ExternalLinkIcon,
DatatableCellImage,
MobileActionButton,
ExternalLinkIcon,
EmptyPageContent,
DatatableWrapper,
SectionTitle,
MobileHeader,
@@ -94,32 +103,31 @@
columns: [
{
label: 'Invoice Number',
field: 'attributes.total',
field: 'data.attributes.order',
sortable: true
},
{
label: 'Total',
field: 'attributes.total',
field: 'data.attributes.bag.amount',
sortable: true
},
{
label: 'Plan',
field: 'attributes.plan',
field: 'data.attributes.bag.amount',
sortable: true
},
{
label: 'Payed',
field: 'attributes.created_at',
field: 'data.attributes.created_at',
sortable: true
},
{
label: 'User',
field: 'relationships.user.data.id',
field: 'relationships.user.data.attributes.name',
sortable: true
},
{
label: this.$t('admin_page_user.table.action'),
field: 'data.action',
sortable: false
},
],

View File

@@ -1,6 +1,6 @@
<template>
<div id="single-page">
<div id="page-content" v-if="! isLoading">
<div id="page-content" v-if="! isLoading && plans.length > 0">
<MobileHeader :title="$router.currentRoute.meta.title"/>
<PageHeader :title="$router.currentRoute.meta.title"/>
@@ -37,7 +37,7 @@
</td>
<td>
<span class="cell-item">
${{ row.data.attributes.price }}
{{ row.data.attributes.price_formatted }}
</span>
</td>
<td>
@@ -60,6 +60,18 @@
</DatatableWrapper>
</div>
</div>
<EmptyPageContent
v-if="! isLoading && plans.length === 0"
icon="file"
title="You dont have any plan yet"
description="For create new plan, click on button below."
>
<router-link :to="{name: 'PlanCreate'}">
<ButtonBase button-style="theme">Create New Plan</ButtonBase>
</router-link>
</EmptyPageContent>
<div id="loader" v-if="isLoading">
<Spinner></Spinner>
</div>
@@ -69,6 +81,7 @@
<script>
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import MobileActionButton from '@/components/FilesView/MobileActionButton'
import EmptyPageContent from '@/components/Others/EmptyPageContent'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import MobileHeader from '@/components/Mobile/MobileHeader'
import SectionTitle from '@/components/Others/SectionTitle'
@@ -83,6 +96,7 @@
name: 'Plans',
components: {
MobileActionButton,
EmptyPageContent,
DatatableWrapper,
SectionTitle,
MobileHeader,
@@ -101,32 +115,31 @@
columns: [
{
label: 'Plan',
field: 'attributes.name',
field: 'data.attributes.name',
sortable: true
},
{
label: 'Status',
field: 'attributes.status',
field: 'data.attributes.status',
sortable: true
},
{
label: 'Subscribers',
field: 'attributes.subscribers',
field: 'data.attributes.subscribers',
sortable: true
},
{
label: 'Price',
field: 'attributes.price',
field: 'data.attributes.price',
sortable: true
},
{
label: 'Storage Capacity',
field: 'attributes.capacity',
field: 'data.attributes.capacity',
sortable: true
},
{
label: this.$t('admin_page_user.table.action'),
field: 'data.action',
sortable: false
},
],

View File

@@ -10,7 +10,7 @@
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Status:</label>
<small class="input-help">Status of your payment gateway on website.</small>
<small class="input-help">Status of your plan availability on website.</small>
</div>
<SwitchInput @input="changeStatus" class="switch" :state="plan.attributes.status"/>
</div>
@@ -37,28 +37,33 @@
<!--Storage Capacity-->
<div class="block-wrapper">
<label>Storage Capacity:</label>
<label>Storage Capacity in GB:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Storage capacity" rules="required" v-slot="{ errors }">
<input @input="$updateText('/plans/' + $route.params.id + '/update', 'capacity', plan.attributes.capacity)" v-model="plan.attributes.capacity" placeholder="Storage capacity" type="number" min="1" max="999999999" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<small class="input-help">You have to type only number e.g. value '5' means, user will have 5GB of storage capacity.</small>
</div>
<InfoBox>
<p>Price change for your plan is not available due to Stripe service design. If you wish change your price plan, please, create new plan.</p>
</InfoBox>
</PageTabGroup>
</ValidationObserver>
</PageTab>
</template>
<script>
import FormLabel from '@/components/Others/Forms/FormLabel'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import PageTab from '@/components/Others/Layout/PageTab'
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import StorageItemDetail from '@/components/Others/StorageItemDetail'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import SelectInput from '@/components/Others/Forms/SelectInput'
import FormLabel from '@/components/Others/Forms/FormLabel'
import ButtonBase from '@/components/FilesView/ButtonBase'
import SetupBox from '@/components/Others/Forms/SetupBox'
import PageTab from '@/components/Others/Layout/PageTab'
import InfoBox from '@/components/Others/Forms/InfoBox'
import {required} from 'vee-validate/dist/rules'
export default {
@@ -67,17 +72,18 @@
'plan'
],
components: {
FormLabel,
SwitchInput,
PageTabGroup,
PageTab,
ValidationProvider,
ValidationObserver,
StorageItemDetail,
PageTabGroup,
SwitchInput,
SelectInput,
ButtonBase,
FormLabel,
SetupBox,
required,
InfoBox,
PageTab,
},
data() {
return {

View File

@@ -1,6 +1,6 @@
<template>
<PageTab v-if="subscribers">
<PageTabGroup>
<PageTab :is-loading="isLoading">
<PageTabGroup v-if="subscribers && subscribers.length > 0">
<DatatableWrapper :paginator="true" :columns="columns" :data="subscribers" class="table">
<template scope="{ row }">
<tr>
@@ -18,11 +18,6 @@
{{ row.relationships.storage.data.attributes.used }}%
</span>
</td>
<td>
<span class="cell-item">
{{ row.relationships.subscription.data.attributes.ends_at }}
</span>
</td>
<td>
<div class="action-icons">
<router-link :to="{name: 'UserDetail', params: {id: row.data.id}}">
@@ -37,15 +32,19 @@
</template>
</DatatableWrapper>
</PageTabGroup>
<InfoBox v-else>
<p>There is no any subscriber yet.</p>
</InfoBox>
</PageTab>
</template>
<script>
import DatatableCellImage from '@/components/Others/Tables/DatatableCellImage'
import {DownloadCloudIcon, Edit2Icon, Trash2Icon} from "vue-feather-icons"
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import PageTab from '@/components/Others/Layout/PageTab'
import {DownloadCloudIcon, Edit2Icon, Trash2Icon} from "vue-feather-icons";
import InfoBox from '@/components/Others/Forms/InfoBox'
import axios from 'axios'
export default {
@@ -55,33 +54,28 @@
DownloadCloudIcon,
DatatableWrapper,
PageTabGroup,
PageTab,
Edit2Icon,
Trash2Icon,
Edit2Icon,
PageTab,
InfoBox,
},
data() {
return {
isLoading: false,
subscribers: undefined,
isLoading: false,
columns: [
{
label: 'User',
field: 'data.attributes.plan',
field: 'data.attributes.name',
sortable: true
},
{
label: this.$t('admin_page_user.table.storage_used'),
field: 'data.storage.attributes.storage.used',
sortable: true
},
{
label: 'Expire At',
field: 'data.subscription.data.attributes.ends_at',
field: 'data.relationships.storage.data.attributes.used',
sortable: true
},
{
label: this.$t('admin_page_user.table.action'),
field: 'data.action',
sortable: false
},
],

View File

@@ -3,7 +3,6 @@
<div id="page-content" v-if="! isLoading">
<MobileHeader :title="$router.currentRoute.meta.title"/>
<PageHeader :can-back="true" :title="$router.currentRoute.meta.title"/>
<div class="content-page">
<!--User thumbnail-->

View File

@@ -32,30 +32,27 @@
<div class="form block-form">
<FormLabel>{{ $t('admin_page_user.label_person_info') }}</FormLabel>
<div class="wrapper-inline">
<!--Email-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<div class="input-wrapper">
<input :value="user.data.attributes.email"
:placeholder="$t('page_registration.placeholder_email')"
type="email"
disabled
/>
</div>
<!--Email-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<div class="input-wrapper">
<input :value="user.data.attributes.email"
:placeholder="$t('page_registration.placeholder_email')"
type="email"
disabled
/>
</div>
</div>
<!--Name-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<div class="input-wrapper">
<input :value="user.data.attributes.name"
:placeholder="$t('page_registration.placeholder_name')"
type="text"
disabled
/>
</div>
<!--Name-->
<div class="block-wrapper">
<label>{{ $t('page_registration.label_name') }}</label>
<div class="input-wrapper">
<input :value="user.data.attributes.name"
:placeholder="$t('page_registration.placeholder_name')"
type="text"
disabled
/>
</div>
</div>
</div>

View File

@@ -1,11 +1,11 @@
<template>
<PageTab :is-loading="isLoading">
<PageTab :is-loading="isLoading" :class="{'form-fixed-width': ! isLoading && invoices.length === 0}">
<PageTabGroup v-if="invoices && invoices.length > 0">
<DatatableWrapper :paginator="true" :columns="columns" :data="invoices" class="table">
<template scope="{ row }">
<tr>
<td>
<a :href="'/invoice/' + row.data.id" target="_blank" class="cell-item">
<a :href="$getInvoiceLink(row.data.attributes.customer, row.data.id)" target="_blank" class="cell-item">
{{ row.data.attributes.order }}
</a>
</td>
@@ -26,7 +26,7 @@
</td>
<td>
<div class="action-icons">
<a :href="'/invoice/' + row.data.id" target="_blank">
<a :href="$getInvoiceLink(row.data.attributes.customer, row.data.id)" target="_blank">
<external-link-icon size="15" class="icon"></external-link-icon>
</a>
</div>
@@ -35,26 +35,30 @@
</template>
</DatatableWrapper>
</PageTabGroup>
<PageTabGroup v-else>
User don't have any invoices yet.
</PageTabGroup>
<InfoBox v-else>
<p>User don't have any invoices yet.</p>
</InfoBox>
</PageTab>
</template>
<script>
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import EmptyPageContent from '@/components/Others/EmptyPageContent'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import PageTab from '@/components/Others/Layout/PageTab'
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import InfoBox from '@/components/Others/Forms/InfoBox'
import {ExternalLinkIcon} from "vue-feather-icons";
import axios from 'axios'
export default {
name: 'UserInvoices',
components: {
PageTabGroup,
PageTab,
EmptyPageContent,
DatatableWrapper,
ExternalLinkIcon,
PageTabGroup,
InfoBox,
PageTab,
},
data() {
return {
@@ -63,17 +67,17 @@
columns: [
{
label: 'Invoice Number',
field: 'data.attributes.total',
field: 'data.attributes.order',
sortable: true
},
{
label: 'Total',
field: 'data.attributes.total',
field: 'data.attributes.bag.amount',
sortable: true
},
{
label: 'Plan',
field: 'data.attributes.plan',
field: 'data.attributes.bag.amount',
sortable: true
},
{
@@ -83,7 +87,6 @@
},
{
label: this.$t('admin_page_user.table.action'),
field: 'data.action',
sortable: false
},
],

View File

@@ -1,5 +1,5 @@
<template>
<PageTab class="form-fixed-width" v-if="storage">
<PageTab :is-loading="isLoading" class="form-fixed-width" v-if="storage">
<PageTabGroup v-if="! config.isSaaS || ! user.data.attributes.subscription">
<FormLabel>{{ $t('user_box_storage.title') }}</FormLabel>
<InfoBox>

View File

@@ -1,6 +1,7 @@
<template>
<PageTab class="form-fixed-width" :is-loading="isLoading">
<PageTab :is-loading="isLoading" class="form-fixed-width">
<PageTabGroup v-if="subscription">
<FormLabel>Subscription Plan</FormLabel>
<!--Info about active subscription-->
<div v-if="! subscription.canceled" class="state active">
@@ -24,7 +25,9 @@
</div>
</PageTabGroup>
<PageTabGroup v-if="! subscription">
User don't have any subscription yet.
<InfoBox>
<p>User don't have any subscription yet.</p>
</InfoBox>
</PageTabGroup>
</PageTab>
</template>
@@ -33,8 +36,10 @@
import DatatableWrapper from '@/components/Others/Tables/DatatableWrapper'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import ListInfoItem from '@/components/Others/ListInfoItem'
import FormLabel from '@/components/Others/Forms/FormLabel'
import ButtonBase from '@/components/FilesView/ButtonBase'
import PageTab from '@/components/Others/Layout/PageTab'
import InfoBox from '@/components/Others/Forms/InfoBox'
import ListInfo from '@/components/Others/ListInfo'
import {ExternalLinkIcon} from "vue-feather-icons"
import {mapGetters} from 'vuex'
@@ -49,7 +54,9 @@
ListInfoItem,
PageTabGroup,
ButtonBase,
FormLabel,
ListInfo,
InfoBox,
PageTab,
},
computed: {