upload request prototype UI

This commit is contained in:
Čarodej
2022-02-16 16:57:57 +01:00
parent 3fafc811fe
commit 394a7b6baf
197 changed files with 6927 additions and 2738 deletions
+59 -51
View File
@@ -19,14 +19,22 @@
<MobileNavigationToolbar />
<ContentSidebar>
<ContentGroup v-for="(menu, i) in nav" :key="i" :title="menu.groupTitle" :slug="menu.groupTitle" :can-collapse="false">
<ContentGroup
v-for="(menu, i) in nav"
:key="i"
:title="menu.groupTitle"
:slug="menu.groupTitle"
:can-collapse="false"
>
<router-link
v-for="(item, i) in menu.groupLinks"
:key="i"
:to="{ name: item.route }"
class="flex items-center py-2.5"
:class="{
'router-link-active': item.linkActivation && item.linkActivation.includes($router.currentRoute.fullPath.split('/')[2]),
'router-link-active':
item.linkActivation &&
item.linkActivation.includes($router.currentRoute.fullPath.split('/')[2]),
}"
>
<box-icon v-if="item.icon === 'box'" size="17" class="vue-feather icon-active mr-2.5" />
@@ -124,57 +132,57 @@ export default {
],
}[this.config.subscriptionType]
let sections = [
{
groupCollapsable: false,
groupTitle: this.$t('global.admin'),
groupLinks: [
{
title: this.$t('admin_menu.dashboard'),
route: 'Dashboard',
icon: 'box',
},
{
title: this.$t('admin_menu.users'),
route: 'Users',
icon: 'users',
linkActivation: ['users', 'user'],
},
{
title: this.$t('admin_menu.settings'),
route: 'AppSettings',
icon: 'settings',
},
],
},
{
groupCollapsable: false,
groupTitle: this.$t('Content'),
groupLinks: [
{
title: this.$t('admin_menu.pages'),
route: 'Pages',
icon: 'monitor',
},
{
title: this.$t('admin_menu.languages'),
route: 'Language',
icon: 'globe',
},
],
},
]
let sections = [
{
groupCollapsable: false,
groupTitle: this.$t('global.admin'),
groupLinks: [
{
title: this.$t('admin_menu.dashboard'),
route: 'Dashboard',
icon: 'box',
},
{
title: this.$t('admin_menu.users'),
route: 'Users',
icon: 'users',
linkActivation: ['users', 'user'],
},
{
title: this.$t('admin_menu.settings'),
route: 'AppSettings',
icon: 'settings',
},
],
},
{
groupCollapsable: false,
groupTitle: this.$t('Content'),
groupLinks: [
{
title: this.$t('admin_menu.pages'),
route: 'Pages',
icon: 'monitor',
},
{
title: this.$t('admin_menu.languages'),
route: 'Language',
icon: 'globe',
},
],
},
]
// Push subscription if there is metered or fixed type
if (this.config.subscriptionType !== 'none') {
sections.push({
groupCollapsable: false,
groupTitle: this.$t('Subscription'),
groupLinks: subscriptionLinks,
})
}
// Push subscription if there is metered or fixed type
if (this.config.subscriptionType !== 'none') {
sections.push({
groupCollapsable: false,
groupTitle: this.$t('Subscription'),
groupLinks: subscriptionLinks,
})
}
return sections
return sections
},
},
components: {
@@ -6,19 +6,20 @@
{{ $t('Basic Setup') }}
</FormLabel>
<AppInputSwitch
:title="$t('Allow Google Adsense')"
:description="$t('Allow ads on app pages.')"
>
<AppInputSwitch :title="$t('Allow Google Adsense')" :description="$t('Allow ads on app pages.')">
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_adsense', adsense.allowedService)"
v-model="adsense.allowedService"
class="switch"
:state="adsense.allowedService"
/>
@input="$updateText('/admin/settings', 'allowed_adsense', adsense.allowedService)"
v-model="adsense.allowedService"
class="switch"
:state="adsense.allowedService"
/>
</AppInputSwitch>
<AppInputText :title="$t('Client Id')" :description="$t('Paste your Adsense Client ID e.g. ca-pub-XXXXXXXXXXXXXXXXX')" :is-last="true">
<AppInputText
:title="$t('Client Id')"
:description="$t('Paste your Adsense Client ID e.g. ca-pub-XXXXXXXXXXXXXXXXX')"
:is-last="true"
>
<input
@input="$updateText('/admin/settings', 'adsense_client_id', adsense.clientId, true)"
v-model="adsense.clientId"
@@ -35,37 +36,47 @@
{{ $t('Ads') }}
</FormLabel>
<AppInputText :title="$t('File Viewport Banner')" :description="$t('This banner will be showed above user files')">
<AppInputText
:title="$t('File Viewport Banner')"
:description="$t('This banner will be showed above user files')"
>
<textarea
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_01', adsense.banner01, true)"
v-model="adsense.banner01"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_01', adsense.banner01, true)"
v-model="adsense.banner01"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText :title="$t('Download Page Banner')" :description="$t('This banner will be showed below file download page')">
<AppInputText
:title="$t('Download Page Banner')"
:description="$t('This banner will be showed below file download page')"
>
<textarea
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_02', adsense.banner02, true)"
v-model="adsense.banner02"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_02', adsense.banner02, true)"
v-model="adsense.banner02"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText :title="$t('Homepage Banner')" :description="$t('This banner will be showed on the homepage')" :is-last="true">
<AppInputText
:title="$t('Homepage Banner')"
:description="$t('This banner will be showed on the homepage')"
:is-last="true"
>
<textarea
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_03', adsense.banner03, true)"
v-model="adsense.banner03"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
rows="3"
@input="$updateText('/admin/settings', 'adsense_banner_03', adsense.banner03, true)"
v-model="adsense.banner03"
:placeholder="$t('Paste the <ins></ins> tag here...')"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
</div>
</PageTab>
@@ -98,18 +109,18 @@ export default {
adsense: {
allowedService: undefined,
clientId: undefined,
banner01: undefined,
banner01: undefined,
},
}
},
created() {
this.adsense = {
allowedService: this.config.allowedAdsense,
clientId: this.config.adsenseClientId,
banner01: this.config.adsenseBanner01,
banner02: this.config.adsenseBanner02,
banner03: this.config.adsenseBanner03,
}
allowedService: this.config.allowedAdsense,
clientId: this.config.adsenseClientId,
banner01: this.config.adsenseBanner01,
banner02: this.config.adsenseBanner02,
banner03: this.config.adsenseBanner03,
}
},
}
</script>
@@ -6,7 +6,12 @@
</FormLabel>
<AppInputSwitch :title="$t('color_theme')" :description="$t('color_theme_description')">
<input @input="$updateText('/admin/settings', 'app_color', app.color)" v-model="app.color" :placeholder="$t('admin_settings.appearance.title_plac')" type="color" />
<input
@input="$updateText('/admin/settings', 'app_color', app.color)"
v-model="app.color"
:placeholder="$t('admin_settings.appearance.title_plac')"
type="color"
/>
</AppInputSwitch>
<AppInputText :title="$t('admin_settings.appearance.title')">
@@ -35,7 +40,11 @@
</FormLabel>
<AppInputText :title="$t('admin_settings.appearance.logo')">
<ImageInput @input="$updateImage('/admin/settings', 'app_logo', app.logo)" :image="$getImage(app.logo)" v-model="app.logo" />
<ImageInput
@input="$updateImage('/admin/settings', 'app_logo', app.logo)"
:image="$getImage(app.logo)"
v-model="app.logo"
/>
</AppInputText>
<AppInputText :title="$t('admin_settings.appearance.logo_horizontal')">
@@ -47,15 +56,27 @@
</AppInputText>
<AppInputText :title="$t('admin_settings.appearance.favicon')">
<ImageInput @input="$updateImage('/admin/settings', 'app_favicon', app.favicon)" :image="$getImage(app.favicon)" v-model="app.favicon" />
<ImageInput
@input="$updateImage('/admin/settings', 'app_favicon', app.favicon)"
:image="$getImage(app.favicon)"
v-model="app.favicon"
/>
</AppInputText>
<AppInputText :title="$t('og_image')" :description="$t('og_image_description')">
<ImageInput @input="$updateImage('/admin/settings', 'app_og_image', app.og_image)" :image="$getImage(app.og_image)" v-model="app.og_image" />
<ImageInput
@input="$updateImage('/admin/settings', 'app_og_image', app.og_image)"
:image="$getImage(app.og_image)"
v-model="app.og_image"
/>
</AppInputText>
<AppInputText :title="$t('app_touch_icon')" :description="$t('app_touch_icon_description')" :is-last="true">
<ImageInput @input="$updateImage('/admin/settings', 'app_touch_icon', app.touch_icon)" :image="$getImage(app.touch_icon)" v-model="app.touch_icon" />
<ImageInput
@input="$updateImage('/admin/settings', 'app_touch_icon', app.touch_icon)"
:image="$getImage(app.touch_icon)"
v-model="app.touch_icon"
/>
</AppInputText>
</div>
</PageTab>
@@ -1,101 +1,209 @@
<template>
<PageTab :is-loading="isLoading">
<ValidationObserver @submit.prevent="EmailSetupSubmit" ref="EmailSetup" v-slot="{ invalid }" tag="form" class="card shadow-card">
<ValidationObserver
@submit.prevent="EmailSetupSubmit"
ref="EmailSetup"
v-slot="{ invalid }"
tag="form"
class="card shadow-card"
>
<FormLabel>{{ $t('admin_settings.email.section_email') }}</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Mail Driver" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Driver" :error="errors[0]">
<SelectInput v-model="mailDriver" :default="mailDriver" :options="mailDriverList" placeholder="Select your mail driver" :isError="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Driver" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Driver" :error="errors[0]">
<SelectInput
v-model="mailDriver"
:default="mailDriver"
:options="mailDriverList"
placeholder="Select your mail driver"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
<div v-if="mailDriver === 'smtp'">
<ValidationProvider tag="div" mode="passive" name="Mail Host" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Host" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="smtp.host" placeholder="Type your mail host" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<div v-if="mailDriver === 'smtp'">
<ValidationProvider tag="div" mode="passive" name="Mail Host" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Host" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="smtp.host"
placeholder="Type your mail host"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Port" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Port" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="smtp.port" placeholder="Type your mail port" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Port" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Port" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="smtp.port"
placeholder="Type your mail port"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Username" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Username" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="smtp.username" placeholder="Type your mail username" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Username" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Username" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="smtp.username"
placeholder="Type your mail username"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Password" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Password" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="smtp.password" placeholder="Type your mail password" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Password" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Password" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="smtp.password"
placeholder="Type your mail password"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Mail Encryption" rules="required" v-slot="{ errors }">
<AppInputText title="Mail Encryption" :error="errors[0]">
<SelectInput v-model="smtp.encryption" :default="smtp.encryption" :options="mailEncryptionList" placeholder="Select your mail encryption" :isError="errors[0]" />
</AppInputText>
</ValidationProvider>
</div>
<ValidationProvider
tag="div"
mode="passive"
name="Mail Encryption"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="Mail Encryption" :error="errors[0]">
<SelectInput
v-model="smtp.encryption"
:default="smtp.encryption"
:options="mailEncryptionList"
placeholder="Select your mail encryption"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
</div>
<div v-if="mailDriver === 'mailgun'">
<ValidationProvider tag="div" mode="passive" name="Domain" rules="required" v-slot="{ errors }">
<AppInputText title="Domain" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="mailgun.domain" placeholder="Type your domain" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<div v-if="mailDriver === 'mailgun'">
<ValidationProvider tag="div" mode="passive" name="Domain" rules="required" v-slot="{ errors }">
<AppInputText title="Domain" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="mailgun.domain"
placeholder="Type your domain"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Secret" rules="required" v-slot="{ errors }">
<AppInputText title="Secret" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="mailgun.secret" placeholder="Type your secret" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Secret" rules="required" v-slot="{ errors }">
<AppInputText title="Secret" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="mailgun.secret"
placeholder="Type your secret"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Endpoint" rules="required" v-slot="{ errors }">
<AppInputText title="Endpoint" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="mailgun.endpoint" placeholder="Type your endpoint" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
</div>
<ValidationProvider tag="div" mode="passive" name="Endpoint" rules="required" v-slot="{ errors }">
<AppInputText title="Endpoint" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="mailgun.endpoint"
placeholder="Type your endpoint"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
</div>
<div v-if="mailDriver === 'postmark'">
<ValidationProvider tag="div" mode="passive" name="Token" rules="required" v-slot="{ errors }">
<AppInputText title="Token" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="postmark.token" placeholder="Type your token" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
</div>
<div v-if="mailDriver === 'postmark'">
<ValidationProvider tag="div" mode="passive" name="Token" rules="required" v-slot="{ errors }">
<AppInputText title="Token" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="postmark.token"
placeholder="Type your token"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
</div>
<div v-if="mailDriver === 'ses'">
<ValidationProvider tag="div" mode="passive" name="Access Key" rules="required" v-slot="{ errors }">
<AppInputText title="Access Key" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="ses.access_key" placeholder="Type your access key" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<div v-if="mailDriver === 'ses'">
<ValidationProvider tag="div" mode="passive" name="Access Key" rules="required" v-slot="{ errors }">
<AppInputText title="Access Key" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="ses.access_key"
placeholder="Type your access key"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Secret Access Key" rules="required" v-slot="{ errors }">
<AppInputText title="Secret Access Key" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="ses.secret_access_key" placeholder="Type your secret access key" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
mode="passive"
name="Secret Access Key"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="Secret Access Key" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="ses.secret_access_key"
placeholder="Type your secret access key"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Default Region" rules="required" v-slot="{ errors }">
<AppInputText title="Default Region" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="ses.default_region" placeholder="Type your default region" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Default Region" rules="required" v-slot="{ errors }">
<AppInputText title="Default Region" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="ses.default_region"
placeholder="Type your default region"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Session Token" v-slot="{ errors }">
<AppInputText title="Session Token" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="ses.session_token" placeholder="Type your session token" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
</div>
<ValidationProvider tag="div" mode="passive" name="Session Token" v-slot="{ errors }">
<AppInputText title="Session Token" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="ses.session_token"
placeholder="Type your session token"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
</div>
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit" button-style="theme" class="w-full sm:w-auto">
<ButtonBase
:loading="isSendingRequest"
:disabled="isSendingRequest"
type="submit"
button-style="theme"
class="w-full sm:w-auto"
>
{{ $t('admin_settings.email.save_button') }}
</ButtonBase>
</ValidationObserver>
@@ -116,7 +224,7 @@ import InfoBox from '../../../../components/Others/Forms/InfoBox'
import { required } from 'vee-validate/dist/rules'
import { events } from '../../../../bus'
import axios from 'axios'
import {mapGetters} from "vuex";
import { mapGetters } from 'vuex'
export default {
name: 'AppAppearance',
@@ -134,78 +242,73 @@ export default {
PageTab,
InfoBox,
},
computed: {
...mapGetters([
'mailEncryptionList',
'mailDriverList',
]),
},
computed: {
...mapGetters(['mailEncryptionList', 'mailDriverList']),
},
data() {
return {
isLoading: false,
isSendingRequest: false,
mailDriver: undefined,
ses: {
access_key: undefined,
secret_access_key: undefined,
default_region: undefined,
session_token: undefined,
},
smtp: {
host: undefined,
port: undefined,
username: undefined,
password: undefined,
encryption: undefined,
},
mailgun: {
domain: undefined,
secret: undefined,
endpoint: undefined,
},
postmark: {
token: undefined,
},
mailDriver: undefined,
ses: {
access_key: undefined,
secret_access_key: undefined,
default_region: undefined,
session_token: undefined,
},
smtp: {
host: undefined,
port: undefined,
username: undefined,
password: undefined,
encryption: undefined,
},
mailgun: {
domain: undefined,
secret: undefined,
endpoint: undefined,
},
postmark: {
token: undefined,
},
}
},
methods: {
async EmailSetupSubmit() {
// Validate fields
const isValid = await this.$refs.EmailSetup.validate()
// Validate fields
const isValid = await this.$refs.EmailSetup.validate()
if (!isValid) return
if (!isValid) return
// Start loading
this.isSendingRequest = true
// Start loading
this.isSendingRequest = true
// Send request to get verify account
axios
.post('/api/admin/settings/email', {
environment: this.environment,
storage: this.storage,
mailDriver: this.mailDriver,
smtp: this.smtp,
mailgun: this.mailgun,
ses: this.ses,
postmark: this.postmark,
})
.then(() => {
events.$emit('toaster', {
type: 'success',
message: this.$t('toaster.email_set'),
})
})
.catch((error) => {
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
})
.finally(() => {
this.isSendingRequest = false
})
// Send request to get verify account
axios
.post('/api/admin/settings/email', {
environment: this.environment,
storage: this.storage,
mailDriver: this.mailDriver,
smtp: this.smtp,
mailgun: this.mailgun,
ses: this.ses,
postmark: this.postmark,
})
.then(() => {
events.$emit('toaster', {
type: 'success',
message: this.$t('toaster.email_set'),
})
})
.catch((error) => {
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
})
.finally(() => {
this.isSendingRequest = false
})
},
},
}
@@ -7,7 +7,11 @@
{{ $t('Homepage') }}
</FormLabel>
<AppInputSwitch :title="$t('Allow Homepage')" :description="$t('When this is turned on, your visitors can visit your default homepage.')" :is-last="true">
<AppInputSwitch
:title="$t('Allow Homepage')"
:description="$t('When this is turned on, your visitors can visit your default homepage.')"
:is-last="true"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allow_homepage', app.allow_homepage)"
v-model="app.allow_homepage"
@@ -27,7 +31,13 @@
<div class="block-wrapper">
<label>Title:</label>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Title"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'header_title', app.header_title)"
v-model="app.header_title"
@@ -41,7 +51,13 @@
<div class="block-wrapper">
<label>Description:</label>
<ValidationProvider tag="div" mode="passive" name="App Description" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Description"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'header_description', app.header_description)"
rows="2"
@@ -81,7 +97,13 @@
<div class="block-wrapper">
<label>Title:</label>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Title"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'features_title', app.features_title)"
v-model="app.features_title"
@@ -95,9 +117,17 @@
<div class="block-wrapper">
<label>Description:</label>
<ValidationProvider tag="div" mode="passive" name="App Description" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Description"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'features_description', app.features_description)"
@input="
$updateText('/admin/settings', 'features_description', app.features_description)
"
rows="2"
v-model="app.features_description"
:class="{ 'border-red': errors[0] }"
@@ -120,7 +150,13 @@
<label class="input-label"> Show section: </label>
</div>
<SwitchInput
@input="$updateText('/admin/settings', 'section_feature_boxes', app.section_feature_boxes)"
@input="
$updateText(
'/admin/settings',
'section_feature_boxes',
app.section_feature_boxes
)
"
v-model="app.section_feature_boxes"
class="switch"
:state="app.section_feature_boxes"
@@ -135,7 +171,13 @@
</div>
<div class="block-wrapper">
<label>First Box Title:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Title 1" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Title 1"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'feature_title_1', app.feature_title_1)"
v-model="app.feature_title_1"
@@ -148,9 +190,21 @@
</div>
<div class="block-wrapper">
<label>First Box Description:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Description 1" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Description 1"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'feature_description_1', app.feature_description_1)"
@input="
$updateText(
'/admin/settings',
'feature_description_1',
app.feature_description_1
)
"
rows="2"
v-model="app.feature_description_1"
:class="{ 'border-red': errors[0] }"
@@ -161,7 +215,13 @@
</div>
<div class="block-wrapper">
<label>Second Box Title:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Title 2" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Title 2"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'feature_title_2', app.feature_title_2)"
v-model="app.feature_title_2"
@@ -174,9 +234,21 @@
</div>
<div class="block-wrapper">
<label>Second Box Description:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Description 2" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Description 2"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'feature_description_2', app.feature_description_2)"
@input="
$updateText(
'/admin/settings',
'feature_description_2',
app.feature_description_2
)
"
rows="2"
v-model="app.feature_description_2"
:class="{ 'border-red': errors[0] }"
@@ -187,7 +259,13 @@
</div>
<div class="block-wrapper">
<label>Third Box Title:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Title 3" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Title 3"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'feature_title_3', app.feature_title_3)"
v-model="app.feature_title_3"
@@ -200,9 +278,21 @@
</div>
<div class="block-wrapper">
<label>Third Box Description:</label>
<ValidationProvider tag="div" mode="passive" name="Feature Description 3" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Feature Description 3"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'feature_description_3', app.feature_description_3)"
@input="
$updateText(
'/admin/settings',
'feature_description_3',
app.feature_description_3
)
"
rows="2"
v-model="app.feature_description_3"
:class="{ 'border-red': errors[0] }"
@@ -225,7 +315,13 @@
<label class="input-label"> Show section: </label>
</div>
<SwitchInput
@input="$updateText('/admin/settings', 'section_pricing_content', app.section_pricing_content)"
@input="
$updateText(
'/admin/settings',
'section_pricing_content',
app.section_pricing_content
)
"
v-model="app.section_pricing_content"
class="switch"
:state="app.section_pricing_content"
@@ -236,11 +332,21 @@
<div v-if="app.section_pricing_content">
<div class="block-wrapper">
<img src="/assets/images/admin/pricing-content.jpg" alt="Main Features" class="page-image" />
<img
src="/assets/images/admin/pricing-content.jpg"
alt="Main Features"
class="page-image"
/>
</div>
<div class="block-wrapper">
<label>Title:</label>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Title"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'pricing_title', app.pricing_title)"
v-model="app.pricing_title"
@@ -254,9 +360,17 @@
<div class="block-wrapper">
<label>Description:</label>
<ValidationProvider tag="div" mode="passive" name="App Description" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Description"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'pricing_description', app.pricing_description)"
@input="
$updateText('/admin/settings', 'pricing_description', app.pricing_description)
"
rows="2"
v-model="app.pricing_description"
:class="{ 'border-red': errors[0] }"
@@ -279,7 +393,9 @@
<label class="input-label"> Show section: </label>
</div>
<SwitchInput
@input="$updateText('/admin/settings', 'section_get_started', app.section_get_started)"
@input="
$updateText('/admin/settings', 'section_get_started', app.section_get_started)
"
v-model="app.section_get_started"
class="switch"
:state="app.section_get_started"
@@ -290,11 +406,21 @@
<div v-if="app.section_get_started">
<div class="block-wrapper">
<img src="/assets/images/admin/get-started-content.jpg" alt="Main Features" class="page-image" />
<img
src="/assets/images/admin/get-started-content.jpg"
alt="Main Features"
class="page-image"
/>
</div>
<div class="block-wrapper">
<label>Title:</label>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Title"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'get_started_title', app.get_started_title)"
v-model="app.get_started_title"
@@ -308,9 +434,21 @@
<div class="block-wrapper">
<label>Description:</label>
<ValidationProvider tag="div" mode="passive" name="App Description" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Description"
rules="required"
v-slot="{ errors }"
>
<textarea
@input="$updateText('/admin/settings', 'get_started_description', app.get_started_description)"
@input="
$updateText(
'/admin/settings',
'get_started_description',
app.get_started_description
)
"
rows="2"
v-model="app.get_started_description"
:class="{ 'border-red': errors[0] }"
@@ -328,7 +466,13 @@
<div class="block-wrapper">
<label>Footer content:</label>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="App Title"
rules="required"
v-slot="{ errors }"
>
<input
@input="$updateText('/admin/settings', 'footer_content', app.footer_content)"
v-model="app.footer_content"
@@ -8,7 +8,10 @@
<!--Available only when is not metered billing-->
<div v-if="config.subscriptionType !== 'metered'">
<AppInputSwitch :title="$t('admin_settings.others.storage_limit')" :description="$t('admin_settings.others.storage_limit_help')">
<AppInputSwitch
:title="$t('admin_settings.others.storage_limit')"
:description="$t('admin_settings.others.storage_limit_help')"
>
<SwitchInput
@input="$updateText('/admin/settings', 'storage_limitation', app.storageLimitation)"
v-model="app.storageLimitation"
@@ -30,7 +33,10 @@
</AppInputText>
</div>
<AppInputText :title="$t('admin_settings.others.upload_limit')" :description="$t('admin_settings.others.upload_limit_help')">
<AppInputText
:title="$t('admin_settings.others.upload_limit')"
:description="$t('admin_settings.others.upload_limit_help')"
>
<input
@input="$updateText('/admin/settings', 'upload_limit', app.uploadLimit, true)"
v-model="app.uploadLimit"
@@ -42,7 +48,11 @@
/>
</AppInputText>
<AppInputText :title="$t('admin_settings.others.mimetypes_blacklist')" :description="$t('admin_settings.others.mimetypes_blacklist_help')" :is-last="true">
<AppInputText
:title="$t('admin_settings.others.mimetypes_blacklist')"
:description="$t('admin_settings.others.mimetypes_blacklist_help')"
:is-last="true"
>
<textarea
rows="2"
@input="$updateText('/admin/settings', 'mimetypes_blacklist', app.mimetypesBlacklist, true)"
@@ -60,8 +70,17 @@
{{ $t('Application') }}
</FormLabel>
<AppInputButton :title="$t('Cache')" :description="$t('Did you change anything in your .env file? Then clear your cache.')">
<ButtonBase @click.native="flushCache" :loading="isFlushingCache" :disabled="isFlushingCache" class="w-full sm:w-auto" button-style="theme">
<AppInputButton
:title="$t('Cache')"
:description="$t('Did you change anything in your .env file? Then clear your cache.')"
>
<ButtonBase
@click.native="flushCache"
:loading="isFlushingCache"
:disabled="isFlushingCache"
class="w-full sm:w-auto"
button-style="theme"
>
{{ $t('admin_settings.others.cache_clear') }}
</ButtonBase>
</AppInputButton>
@@ -153,7 +172,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -1,179 +1,208 @@
<template>
<PageTab v-if="! isLoading">
<!--Cron check-->
<div class="card shadow-card">
<FormLabel icon="info">
Cron
</FormLabel>
<PageTab v-if="!isLoading">
<!--Cron check-->
<div class="card shadow-card">
<FormLabel icon="info"> Cron </FormLabel>
<div class="flex items-center justify-between">
<div class="text-left">
<b class="text-sm font-bold block">Cron Jobs</b>
<small v-if="!cron.running" class="text-xs text-gray-600">
We detect, your cron jobs probably doesn't work correctly, please check it.
</small>
<small v-if="cron.running" class="text-xs text-gray-600">
Latest Update: {{ cron.lastUpdate }}
</small>
</div>
<div class="flex items-center">
<check-icon v-if="cron.running" size="16" class="vue-feather text-green-600 dark:text-green-600"/>
<x-icon v-if="!cron.running" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<div class="flex items-center justify-between">
<div class="text-left">
<b class="block text-sm font-bold">Cron Jobs</b>
<small v-if="!cron.running" class="text-xs text-gray-600">
We detect, your cron jobs probably doesn't work correctly, please check it.
</small>
<small v-if="cron.running" class="text-xs text-gray-600">
Latest Update: {{ cron.lastUpdate }}
</small>
</div>
<div class="flex items-center">
<check-icon v-if="cron.running" size="16" class="vue-feather text-green-600 dark:text-green-600" />
<x-icon v-if="!cron.running" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<span class="ml-3 text-sm font-bold" :class="cron.running ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'">
{{ cron.running ? 'Working correctly' : "Doesn't work" }}
</span>
</div>
</div>
</div>
<span
class="ml-3 text-sm font-bold"
:class="cron.running ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'"
>
{{ cron.running ? 'Working correctly' : "Doesn't work" }}
</span>
</div>
</div>
</div>
<!--Database Backups check-->
<div class="card shadow-card">
<FormLabel icon="database">
Latest Database Backups
</FormLabel>
<!--Database Backups check-->
<div class="card shadow-card">
<FormLabel icon="database"> Latest Database Backups </FormLabel>
<InfoBox v-if="! backups.length" class="!mb-0">
<p v-html="$t('There is not any database backup stored.')"></p>
</InfoBox>
<InfoBox v-if="!backups.length" class="!mb-0">
<p v-html="$t('There is not any database backup stored.')"></p>
</InfoBox>
<InfoBox v-if="backups.length" class="!mb-3">
<p v-html="$t('You can find your backups in <b>/storage/app/app-backups</b>.')"></p>
</InfoBox>
<InfoBox v-if="backups.length" class="!mb-3">
<p v-html="$t('You can find your backups in <b>/storage/app/app-backups</b>.')"></p>
</InfoBox>
<div v-if="backups.length" v-for="(filename, i) in backups" :key="i" class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<div class="text-left">
<b class="text-sm font-bold block">{{ filename }}</b>
</div>
<div class="flex items-center">
<check-icon size="16" class="vue-feather text-green-600 dark:text-green-600"/>
<div
v-if="backups.length"
v-for="(filename, i) in backups"
:key="i"
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<div class="text-left">
<b class="block text-sm font-bold">{{ filename }}</b>
</div>
<div class="flex items-center">
<check-icon size="16" class="vue-feather text-green-600 dark:text-green-600" />
<span class="ml-3 text-sm font-bold text-green-600 dark:text-green-600">
Stored Successfully
</span>
</div>
</div>
</div>
<span class="ml-3 text-sm font-bold text-green-600 dark:text-green-600"> Stored Successfully </span>
</div>
</div>
</div>
<!--PHP version and ini check-->
<div class="card shadow-card">
<FormLabel icon="info">
PHP Settings
</FormLabel>
<!--PHP version and ini check-->
<div class="card shadow-card">
<FormLabel icon="info"> PHP Settings </FormLabel>
<div class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<div class="text-left">
<b class="text-sm font-bold block">PHP Version</b>
<small v-if="!phpVersion.acceptable" class="text-xs text-gray-600">
You need PHP version at least {{ phpVersion.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="phpVersion.acceptable" size="16" class="vue-feather text-green-600 dark:text-green-600"/>
<x-icon v-if="!phpVersion.acceptable" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<div
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<div class="text-left">
<b class="block text-sm font-bold">PHP Version</b>
<small v-if="!phpVersion.acceptable" class="text-xs text-gray-600">
You need PHP version at least {{ phpVersion.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon
v-if="phpVersion.acceptable"
size="16"
class="vue-feather text-green-600 dark:text-green-600"
/>
<x-icon
v-if="!phpVersion.acceptable"
size="16"
class="vue-feather text-red-600 dark:text-red-600"
/>
<span class="ml-3 text-sm font-bold" :class="phpVersion.acceptable ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'">
{{ phpVersion.current }}
</span>
</div>
</div>
<span
class="ml-3 text-sm font-bold"
:class="
phpVersion.acceptable
? 'text-green-600 dark:text-green-600'
: 'text-red-600 dark:text-red-600'
"
>
{{ phpVersion.current }}
</span>
</div>
</div>
<div v-for="(values, setting, i) in ini" :key="i" class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<div class="text-left">
<b class="text-sm font-bold block">{{ setting }}</b>
<small v-if="!values.status" class="text-xs text-gray-600">
We recommend set this value at least {{ values.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="values.status" size="16" class="vue-feather text-green-600 dark:text-green-600"/>
<x-icon v-if="!values.status" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<div
v-for="(values, setting, i) in ini"
:key="i"
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<div class="text-left">
<b class="block text-sm font-bold">{{ setting }}</b>
<small v-if="!values.status" class="text-xs text-gray-600">
We recommend set this value at least {{ values.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="values.status" size="16" class="vue-feather text-green-600 dark:text-green-600" />
<x-icon v-if="!values.status" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<span class="ml-3 text-sm font-bold" :class="values.status ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'">
{{ values.current }}{{ setting !== 'max_execution_time' ? 'M' : '' }}
</span>
</div>
</div>
</div>
<span
class="ml-3 text-sm font-bold"
:class="values.status ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'"
>
{{ values.current }}{{ setting !== 'max_execution_time' ? 'M' : '' }}
</span>
</div>
</div>
</div>
<!--PHP Extension info-->
<div class="card shadow-card">
<FormLabel icon="info">
PHP Extensions
</FormLabel>
<!--PHP Extension info-->
<div class="card shadow-card">
<FormLabel icon="info"> PHP Extensions </FormLabel>
<div v-if="modules" v-for="(value, module, i) in modules" :key="i" class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<b class="text-sm font-bold">
{{ module }}
</b>
<div class="flex items-center">
<check-icon v-if="value" size="16" class="vue-feather text-green-600 dark:text-green-600"/>
<x-icon v-if="!value" size="16" class="vue-feather text-red-600 dark:text-red-600"/>
<div
v-if="modules"
v-for="(value, module, i) in modules"
:key="i"
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<b class="text-sm font-bold">
{{ module }}
</b>
<div class="flex items-center">
<check-icon v-if="value" size="16" class="vue-feather text-green-600 dark:text-green-600" />
<x-icon v-if="!value" size="16" class="vue-feather text-red-600 dark:text-red-600" />
<span class="ml-3 text-sm font-bold" :class="value ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'">
{{ value ? 'Module Installed' : 'Missing Module' }}
</span>
</div>
</div>
</div>
<span
class="ml-3 text-sm font-bold"
:class="value ? 'text-green-600 dark:text-green-600' : 'text-red-600 dark:text-red-600'"
>
{{ value ? 'Module Installed' : 'Missing Module' }}
</span>
</div>
</div>
</div>
</PageTab>
</template>
<script>
import InfoBox from "../../../../components/Others/Forms/InfoBox"
import InfoBox from '../../../../components/Others/Forms/InfoBox'
import FormLabel from '../../../../components/Others/Forms/FormLabel'
import PageTab from '../../../../components/Others/Layout/PageTab'
import { CheckIcon, XIcon } from 'vue-feather-icons'
import { mapGetters } from 'vuex'
import axios from "axios";
import axios from 'axios'
export default {
name: 'Server',
components: {
FormLabel,
InfoBox,
InfoBox,
PageTab,
CheckIcon,
XIcon,
CheckIcon,
XIcon,
},
computed: {
...mapGetters(['config']),
isCheckedAPI() {
return typeof this.apiRunning !== 'undefined'
},
isCheckedAPI() {
return typeof this.apiRunning !== 'undefined'
},
},
data() {
return {
isLoading: true,
ini: undefined,
cron: undefined,
modules: undefined,
phpVersion: undefined,
apiRunning: undefined,
backups: undefined,
isLoading: true,
ini: undefined,
cron: undefined,
modules: undefined,
phpVersion: undefined,
apiRunning: undefined,
backups: undefined,
}
},
created() {
// Get status
axios.get('/api/admin/status')
.then(response => {
this.isLoading = false
this.ini = response.data.ini
this.cron = response.data.cron
this.modules = response.data.modules
this.phpVersion = response.data.php_version
this.backups = response.data.backups
})
// Get status
axios.get('/api/admin/status').then((response) => {
this.isLoading = false
this.ini = response.data.ini
this.cron = response.data.cron
this.modules = response.data.modules
this.phpVersion = response.data.php_version
this.backups = response.data.backups
})
// Ping API
axios
.get('/api/ping')
.then((response) => {
this.apiRunning = response.data === 'pong';
})
.catch(() => {
this.apiRunning = false
})
// Ping API
axios
.get('/api/ping')
.then((response) => {
this.apiRunning = response.data === 'pong'
})
.catch(() => {
this.apiRunning = false
})
},
}
</script>
@@ -6,7 +6,10 @@
{{ $t('User Login/Registration') }}
</FormLabel>
<AppInputSwitch :title="$t('admin_settings.others.allow_registration')" :description="$t('admin_settings.others.allow_registration_help')">
<AppInputSwitch
:title="$t('admin_settings.others.allow_registration')"
:description="$t('admin_settings.others.allow_registration_help')"
>
<SwitchInput
@input="$updateText('/admin/settings', 'registration', app.userRegistration)"
v-model="app.userRegistration"
@@ -15,7 +18,11 @@
/>
</AppInputSwitch>
<AppInputSwitch :title="$t('Require Email Verification')" :description="$t('admin_settings.others.allow_user_verification_help')" :is-last="true">
<AppInputSwitch
:title="$t('Require Email Verification')"
:description="$t('admin_settings.others.allow_user_verification_help')"
:is-last="true"
>
<SwitchInput
@input="$updateText('/admin/settings', 'user_verification', app.userVerification)"
v-model="app.userVerification"
@@ -29,7 +36,11 @@
<div class="card shadow-card">
<img :src="$getSocialLogo('facebook')" alt="Facebook" class="mb-8 h-5" />
<AppInputSwitch :title="$t('Allow Login via Facebook')" :description="$t('You users will be able to login via Facebook account.')" :is-last="!facebook.allowedService">
<AppInputSwitch
:title="$t('Allow Login via Facebook')"
:description="$t('You users will be able to login via Facebook account.')"
:is-last="!facebook.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_facebook_login', facebook.allowedService)"
v-model="facebook.allowedService"
@@ -50,7 +61,9 @@
<!--Set up facebook credentials-->
<ValidationObserver
v-if="(!config.isFacebookLoginConfigured || facebook.isVisibleCredentialsForm) && facebook.allowedService"
v-if="
(!config.isFacebookLoginConfigured || facebook.isVisibleCredentialsForm) && facebook.allowedService
"
@submit.prevent="storeCredentials('facebook_login')"
ref="credentialsForm"
v-slot="{ invalid }"
@@ -85,7 +98,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -95,7 +114,11 @@
<div class="card shadow-card">
<img :src="$getSocialLogo('google')" alt="Google" class="mb-8 h-7" />
<AppInputSwitch :title="$t('Allow Login via Google')" :description="$t('You users will be able to login via Google account.')" :is-last="!google.allowedService">
<AppInputSwitch
:title="$t('Allow Login via Google')"
:description="$t('You users will be able to login via Google account.')"
:is-last="!google.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_google_login', google.allowedService)"
v-model="google.allowedService"
@@ -151,7 +174,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -161,7 +190,11 @@
<div class="card shadow-card">
<img :src="$getSocialLogo('github')" alt="Github" class="mb-8 h-5" />
<AppInputSwitch :title="$t('Allow Login via GitHub')" :description="$t('You users will be able to login via GitHub account.')" :is-last="!github.allowedService">
<AppInputSwitch
:title="$t('Allow Login via GitHub')"
:description="$t('You users will be able to login via GitHub account.')"
:is-last="!github.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_github_login', github.allowedService)"
v-model="github.allowedService"
@@ -217,7 +250,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
+53 -18
View File
@@ -5,18 +5,30 @@
<div v-if="config.isAdminVueFileManagerBar" class="mb-4 hidden justify-between md:mb-6 md:block md:flex">
<!--VueFileManager logo-->
<a href="https://vuefilemanager.com" target="_blank">
<img src="/assets/images/vuefilemanager-horizontal-logo.svg" alt="VueFileManager" class="light-mode" />
<img
src="/assets/images/vuefilemanager-horizontal-logo.svg"
alt="VueFileManager"
class="light-mode"
/>
</a>
<!--App Info-->
<div class="mt-4 flex items-center md:mt-0">
<a href="https://gist.github.com/MakingCG/9c07f8af392081ae5d5290d920a79b5d" target="_blank" class="mr-4 inline-block">
<a
href="https://gist.github.com/MakingCG/9c07f8af392081ae5d5290d920a79b5d"
target="_blank"
class="mr-4 inline-block"
>
<span class="text-sm font-bold"> {{ $t('admin_page_dashboard.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="mr-4 inline-block">
<a
href="https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986"
target="_blank"
class="mr-4 inline-block"
>
<span class="text-sm font-bold"> {{ $t('admin_page_dashboard.license') }}: </span>
<ColorLabel color="purple">
{{ data.app.license }}
@@ -28,7 +40,11 @@
{{ config.subscriptionType }}
</ColorLabel>
</b>
<a href="https://bit.ly/VueFileManager-survey" target="_blank" class="bg-theme-100 lg:ml-4 ml-8 inline-block hidden items-center rounded-lg py-1.5 px-3 md:flex">
<a
href="https://bit.ly/VueFileManager-survey"
target="_blank"
class="bg-theme-100 ml-8 inline-block hidden items-center rounded-lg py-1.5 px-3 md:flex lg:ml-4"
>
<thumbs-up-icon size="15" class="vue-feather text-theme mr-2.5" />
<span class="text-theme text-sm font-bold">
{{ $t('Write a Feedback') }}
@@ -37,17 +53,33 @@
</div>
</div>
<!--Create metered plan alert-->
<div v-if="config.subscriptionType === 'metered' && config.isEmptyPlans" class="p-5 bg-rose-200 rounded-xl shadow-card mb-6 flex items-center">
<alert-octagon-icon size="18" class="vue-feather text-rose-700 mr-4 shrink-0"/>
<p class="text-sm text-rose-700">As you installed app with metered subscription type, you have to <router-link :to="{name: 'CreateMeteredPlan'}" class="font-bold underline text-sm">create your plan</router-link> as soon as possible to prevent new user registration without automatically assigned subscription plan.</p>
</div>
<!--Create metered plan alert-->
<div
v-if="config.subscriptionType === 'metered' && config.isEmptyPlans"
class="mb-6 flex items-center rounded-xl bg-rose-200 p-5 shadow-card"
>
<alert-octagon-icon size="18" class="vue-feather mr-4 shrink-0 text-rose-700" />
<p class="text-sm text-rose-700">
As you installed app with metered subscription type, you have to
<router-link :to="{ name: 'CreateMeteredPlan' }" class="text-sm font-bold underline"
>create your plan</router-link
>
as soon as possible to prevent new user registration without automatically assigned subscription
plan.
</p>
</div>
<!--Cron Alert-->
<div v-if="! data.app.isRunningCron && !config.isDev" class="p-5 bg-rose-200 rounded-xl shadow-card mb-6 flex items-center">
<alert-octagon-icon size="18" class="vue-feather text-rose-700 mr-4 shrink-0"/>
<p class="text-sm text-rose-700">We detect your cron jobs probably doesn't work correctly, please check it, you need it for running app correctly. If you set your cron job, please get back one minute later.</p>
</div>
<!--Cron Alert-->
<div
v-if="!data.app.isRunningCron && !config.isDev"
class="mb-6 flex items-center rounded-xl bg-rose-200 p-5 shadow-card"
>
<alert-octagon-icon size="18" class="vue-feather mr-4 shrink-0 text-rose-700" />
<p class="text-sm text-rose-700">
We detect your cron jobs probably doesn't work correctly, please check it, you need it for running
app correctly. If you set your cron job, please get back one minute later.
</p>
</div>
<!--Metric widgets-->
<div class="mb-2 md:mb-6 md:flex md:space-x-6">
@@ -145,7 +177,10 @@
</div>
<!--Latest transactions widgets-->
<div v-if="['fixed', 'metered'].includes(this.config.subscriptionType)" class="card mb-4 shadow-card md:mb-6">
<div
v-if="['fixed', 'metered'].includes(this.config.subscriptionType)"
class="card mb-4 shadow-card md:mb-6"
>
<FormLabel icon="dollar">
{{ $t('Latest Transactions') }}
</FormLabel>
@@ -170,16 +205,16 @@ import BarChart from '../../components/UI/BarChart'
import { mapGetters } from 'vuex'
import axios from 'axios'
import WidgetLatestTransactions from '../../components/Admin/WidgetLatestTransactions'
import InfoBox from "../../components/Others/Forms/InfoBox";
import InfoBox from '../../components/Others/Forms/InfoBox'
export default {
name: 'Dashboard',
components: {
InfoBox,
InfoBox,
WidgetLatestTransactions,
WidgetLatestRegistrations,
ChevronRightIcon,
AlertOctagonIcon,
AlertOctagonIcon,
WidgetWrapper,
ThumbsUpIcon,
ColorLabel,
+22 -4
View File
@@ -1,22 +1,40 @@
<template>
<div>
<!--Datatable-->
<DatatableWrapper v-if="!config.isEmptyTransactions" class="card overflow-x-auto shadow-card" api="/api/admin/transactions" :paginator="true" :columns="columns">
<DatatableWrapper
v-if="!config.isEmptyTransactions"
class="card overflow-x-auto shadow-card"
api="/api/admin/transactions"
:paginator="true"
:columns="columns"
>
<template slot-scope="{ row }">
<!--Transaction rows-->
<MeteredTransactionRow v-if="config.subscriptionType === 'metered'" :row="row" :user="true" @showDetail="showTransactionDetail" />
<MeteredTransactionRow
v-if="config.subscriptionType === 'metered'"
:row="row"
:user="true"
@showDetail="showTransactionDetail"
/>
<FixedTransactionRow v-if="config.subscriptionType === 'fixed'" :row="row" :user="true" />
<!--Transaction detail-->
<MeteredTransactionDetailRow v-if="row.data.attributes.metadata && showedTransactionDetailById === row.data.id" :row="row" />
<MeteredTransactionDetailRow
v-if="row.data.attributes.metadata && showedTransactionDetailById === row.data.id"
:row="row"
/>
</template>
</DatatableWrapper>
<!--Empty State-->
<div v-if="config.isEmptyTransactions" class="flex h-full items-center justify-center">
<div class="text-center">
<img class="mb-6 inline-block w-28" src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f9ee.svg" alt="transaction" />
<img
class="mb-6 inline-block w-28"
src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f9ee.svg"
alt="transaction"
/>
<h1 class="mb-1 text-2xl font-bold">
{{ $t('There is Nothing') }}
</h1>
+54 -12
View File
@@ -5,7 +5,8 @@
<div
class="z-20 bg-white pt-3 sm:pt-5"
:class="{
'fixed top-0 left-0 right-0 z-10 rounded-none bg-white bg-opacity-70 px-6 backdrop-blur-lg backdrop-filter dark:bg-dark-foreground': fixedNav,
'fixed top-0 left-0 right-0 z-10 rounded-none bg-white bg-opacity-70 px-6 backdrop-blur-lg backdrop-filter dark:bg-dark-foreground':
fixedNav,
'card sticky top-0 z-10 block py-0 shadow-card md:hidden': !fixedNav,
}"
>
@@ -19,8 +20,12 @@
:key="language.data.id"
class="border-bottom-theme inline-block border-b-2 border-transparent px-4 py-5 text-sm font-bold"
:class="{
'text-theme router-link-active': selectedLanguage && selectedLanguage.data.attributes.locale === language.data.attributes.locale,
'text-gray-600': !selectedLanguage && selectedLanguage.data.attributes.locale !== language.data.attributes.locale,
'text-theme router-link-active':
selectedLanguage &&
selectedLanguage.data.attributes.locale === language.data.attributes.locale,
'text-gray-600':
!selectedLanguage &&
selectedLanguage.data.attributes.locale !== language.data.attributes.locale,
}"
>
{{ language.data.attributes.name }}
@@ -52,12 +57,19 @@
<label
class="text-base font-bold"
:class="{
'text-theme': selectedLanguage && selectedLanguage.data.attributes.locale === language.data.attributes.locale,
'text-theme':
selectedLanguage &&
selectedLanguage.data.attributes.locale === language.data.attributes.locale,
}"
>
{{ language.data.attributes.name }}
</label>
<x-icon v-if="language.data.attributes.locale !== 'en'" @click.stop="deleteLanguage(language)" class="opacity-0 group-hover:opacity-100" size="12" />
<x-icon
v-if="language.data.attributes.locale !== 'en'"
@click.stop="deleteLanguage(language)"
class="opacity-0 group-hover:opacity-100"
size="12"
/>
</div>
<!-- Create Language button -->
@@ -78,10 +90,22 @@
{{ $t('language_settings') }}
</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Language name" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Language name"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('language_name')" :error="errors[0]">
<input
@input="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'name', selectedLanguage.data.attributes.name)"
@input="
$updateText(
`/admin/languages/${selectedLanguage.data.id}`,
'name',
selectedLanguage.data.attributes.name
)
"
v-model="selectedLanguage.data.attributes.name"
:placeholder="$t('admin_settings.appearance.description_plac')"
type="text"
@@ -93,14 +117,19 @@
<AppInputSwitch
:title="$t('set_as_default_language')"
:description="$t('If this language is set as default, app will appear in this language for all users.')"
:description="
$t(
'If this language is set as default, app will appear in this language for all users.'
)
"
:is-last="true"
>
<SwitchInput
@input="setDefaultLanguage"
class="switch"
:class="{
'disable-switch': selectedLanguage.data.attributes.locale === this.defaultLanguageLocale,
'disable-switch':
selectedLanguage.data.attributes.locale === this.defaultLanguageLocale,
}"
:state="selectedLanguage.data.attributes.locale === this.defaultLanguageLocale"
/>
@@ -126,10 +155,21 @@
</div>
<ValidationProvider tag="div" name="Language string" rules="required" v-slot="{ errors }">
<AppInputText :title="referenceTranslations[key]" :error="errors[0]" v-for="(translation, key) in translationList" :key="key">
<AppInputText
:title="referenceTranslations[key]"
:error="errors[0]"
v-for="(translation, key) in translationList"
:key="key"
>
<textarea
v-model="selectedLanguage.data.attributes.translations[key]"
@input="$updateText(`/admin/languages/${selectedLanguage.data.id}/strings`, key, selectedLanguage.data.attributes.translations[key])"
@input="
$updateText(
`/admin/languages/${selectedLanguage.data.id}/strings`,
key,
selectedLanguage.data.attributes.translations[key]
)
"
:rows="selectedLanguage.data.attributes.translations[key].length >= 80 ? 3 : 1"
class="focus-border-theme input-dark"
:class="{ 'border-red': errors[0] }"
@@ -210,7 +250,9 @@ export default {
return this.searchedTranslationResults && this.query !== ''
},
translationList() {
return this.isSearching ? this.searchedTranslationResults : this.selectedLanguage.data.attributes.translations
return this.isSearching
? this.searchedTranslationResults
: this.selectedLanguage.data.attributes.translations
},
},
methods: {
+14 -2
View File
@@ -1,7 +1,13 @@
<template>
<div>
<div class="card shadow-card">
<DatatableWrapper @init="isLoading = false" api="/api/admin/pages" :paginator="false" :columns="columns" class="overflow-x-auto">
<DatatableWrapper
@init="isLoading = false"
api="/api/admin/pages"
:paginator="false"
:columns="columns"
class="overflow-x-auto"
>
<template slot-scope="{ row }">
<tr class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<td class="py-5 pr-3 md:pr-1">
@@ -24,7 +30,13 @@
<td class="px-3 md:px-1">
<span class="text-sm font-bold">
<SwitchInput
@input="$updateText(`/admin/pages/${row.data.id}`, 'visibility', row.data.attributes.visibility)"
@input="
$updateText(
`/admin/pages/${row.data.id}`,
'visibility',
row.data.attributes.visibility
)
"
v-model="row.data.attributes.visibility"
:state="row.data.attributes.visibility"
class="switch"
+4 -1
View File
@@ -4,7 +4,10 @@
<FormLabel>
{{ page.data.attributes.title }}
</FormLabel>
<AppInputSwitch :title="$t('admin_pages.form.visibility')" :description="$t('admin_pages.form.visibility_help')">
<AppInputSwitch
:title="$t('admin_pages.form.visibility')"
:description="$t('admin_pages.form.visibility_help')"
>
<SwitchInput @input="changeStatus" class="switch" :state="page.data.attributes.visibility" />
</AppInputSwitch>
<AppInputText :title="$t('admin_pages.form.title')">
@@ -63,7 +63,13 @@
<AppInputText :title="$t('admin_settings.billings.postal_code')" class="w-full">
<input
@input="$updateText('/admin/settings', 'billing_postal_code', billingInformation.billing_postal_code)"
@input="
$updateText(
'/admin/settings',
'billing_postal_code',
billingInformation.billing_postal_code
)
"
v-model="billingInformation.billing_postal_code"
:placeholder="$t('admin_settings.billings.postal_code_plac')"
type="text"
@@ -84,7 +90,9 @@
<AppInputText :title="$t('admin_settings.billings.phone_number')" :is-last="true">
<input
@input="$updateText('/admin/settings', 'billing_phone_number', billingInformation.billing_phone_number)"
@input="
$updateText('/admin/settings', 'billing_phone_number', billingInformation.billing_phone_number)
"
v-model="billingInformation.billing_phone_number"
:placeholder="$t('admin_settings.billings.phone_number_plac')"
type="text"
@@ -6,12 +6,25 @@
{{ $t('Subscription Payments') }}
</FormLabel>
<AppInputSwitch :title="$t('Allow Subscription Payments')" :description="$t('User can subscribe to fixed or metered plan')" :is-last="!allowedPayments">
<SwitchInput @input="$updateText('/admin/settings', 'allowed_payments', allowedPayments)" v-model="allowedPayments" :state="allowedPayments" />
<AppInputSwitch
:title="$t('Allow Subscription Payments')"
:description="$t('User can subscribe to fixed or metered plan')"
:is-last="!allowedPayments"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_payments', allowedPayments)"
v-model="allowedPayments"
:state="allowedPayments"
/>
</AppInputSwitch>
<AppInputText v-if="allowedPayments" :title="$t('Subscription Type')" :is-last="true">
<SelectInput @change="subscriptionTypeChange" :default="config.subscriptionType" :options="subscriptionTypes" :placeholder="$t('Select your subscription type')" />
<SelectInput
@change="subscriptionTypeChange"
:default="config.subscriptionType"
:options="subscriptionTypes"
:placeholder="$t('Select your subscription type')"
/>
</AppInputText>
</div>
@@ -21,7 +34,10 @@
{{ $t('Metered Billing Settings') }}
</FormLabel>
<AppInputSwitch :title="$t('Allow Registration Bonus')" :description="$t('Credit user automatically bonus to his balance after registration.')">
<AppInputSwitch
:title="$t('Allow Registration Bonus')"
:description="$t('Credit user automatically bonus to his balance after registration.')"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_registration_bonus', allowedRegistrationBonus)"
v-model="allowedRegistrationBonus"
@@ -43,7 +59,11 @@
/>
</AppInputText>
<AppInputButton :title="$t('Metered Plan')" :description="$t('Your price set up for billing multiple features by user usage.')" :is-last="true">
<AppInputButton
:title="$t('Metered Plan')"
:description="$t('Your price set up for billing multiple features by user usage.')"
:is-last="true"
>
<router-link
v-if="config.isCreatedMeteredPlan"
:to="{
@@ -68,8 +88,16 @@
<div v-if="allowedPayments" class="card shadow-card">
<img :src="$getPaymentLogo('stripe')" alt="Stripe" class="mb-8 h-8" />
<AppInputSwitch :title="$t('Allow Stripe Service')" :description="$t('Allow your users pay by their credit card')" :is-last="!stripe.allowedService">
<SwitchInput @input="$updateText('/admin/settings', 'allowed_stripe', stripe.allowedService)" v-model="stripe.allowedService" :state="stripe.allowedService" />
<AppInputSwitch
:title="$t('Allow Stripe Service')"
:description="$t('Allow your users pay by their credit card')"
:is-last="!stripe.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_stripe', stripe.allowedService)"
v-model="stripe.allowedService"
:state="stripe.allowedService"
/>
</AppInputSwitch>
<!--Stripe credentials are set up-->
@@ -82,15 +110,27 @@
>
<textarea
rows="2"
@input="$updateText('/admin/settings', 'stripe_payment_description', stripe.paymentDescription, true)"
@input="
$updateText(
'/admin/settings',
'stripe_payment_description',
stripe.paymentDescription,
true
)
"
v-model="stripe.paymentDescription"
:placeholder="$t('Describe in short which methods user can pay with this payment method...')"
:placeholder="
$t('Describe in short which methods user can pay with this payment method...')
"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText :title="$t('Your Webhook URL')" :description="$t('Please copy your url and paste it to the service webhook setup.')">
<AppInputText
:title="$t('Your Webhook URL')"
:description="$t('Please copy your url and paste it to the service webhook setup.')"
>
<CopyInput size="small" :str="getWebhookEndpoint('stripe')" />
</AppInputText>
@@ -116,7 +156,13 @@
<FormLabel v-if="!stripe.isConfigured" icon="shield">
{{ $t('Configure Your Credentials') }}
</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Publishable Key" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Publishable Key"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('admin_settings.payments.stripe_pub_key')" :error="errors[0]">
<input
v-model="stripe.credentials.key"
@@ -138,7 +184,13 @@
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Webhook Secret" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Webhook Secret"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('Webhook Secret')" :error="errors[0]">
<input
v-model="stripe.credentials.webhook"
@@ -150,7 +202,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -161,7 +219,11 @@
<div v-if="allowedPayments" class="card shadow-card">
<img :src="$getPaymentLogo('paystack')" alt="Paystack" class="mb-8 h-7" />
<AppInputSwitch :title="$t('Allow Paystack Service')" :description="$t('Allow your users pay by their credit card')" :is-last="!paystack.allowedService">
<AppInputSwitch
:title="$t('Allow Paystack Service')"
:description="$t('Allow your users pay by their credit card')"
:is-last="!paystack.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_paystack', paystack.allowedService)"
v-model="paystack.allowedService"
@@ -173,21 +235,35 @@
<div v-if="paystack.allowedService">
<div v-if="paystack.isConfigured">
<AppInputText
@input="$updateText('/admin/settings', 'paystack_payment_description', paystack.paymentDescription)"
@input="
$updateText('/admin/settings', 'paystack_payment_description', paystack.paymentDescription)
"
:title="$t('Payment Description')"
:description="$t('The description showed below user payment method selection.')"
>
<textarea
rows="2"
@input="$updateText('/admin/settings', 'paystack_payment_description', paystack.paymentDescription, true)"
@input="
$updateText(
'/admin/settings',
'paystack_payment_description',
paystack.paymentDescription,
true
)
"
v-model="paystack.paymentDescription"
:placeholder="$t('Describe in short which methods user can pay with this payment method...')"
:placeholder="
$t('Describe in short which methods user can pay with this payment method...')
"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText :title="$t('Your Webhook URL')" :description="$t('Please copy your url and paste it to the service webhook setup.')">
<AppInputText
:title="$t('Your Webhook URL')"
:description="$t('Please copy your url and paste it to the service webhook setup.')"
>
<CopyInput size="small" :str="getWebhookEndpoint('paystack')" />
</AppInputText>
@@ -213,7 +289,13 @@
<FormLabel v-if="!paystack.isConfigured" icon="shield">
{{ $t('Configure Your Credentials') }}
</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Publishable Key" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Publishable Key"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('admin_settings.payments.stripe_pub_key')" :error="errors[0]">
<input
v-model="paystack.credentials.key"
@@ -236,7 +318,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -247,15 +335,27 @@
<div v-if="allowedPayments" class="card shadow-card">
<img :src="$getPaymentLogo('paypal')" alt="PayPal" class="mb-8 h-8" />
<AppInputSwitch :title="$t('Allow PayPal Service')" :description="$t('Allow your users pay by their credit card')" :is-last="!paypal.allowedService">
<SwitchInput @input="$updateText('/admin/settings', 'allowed_paypal', paypal.allowedService)" v-model="paypal.allowedService" :state="paypal.allowedService" />
<AppInputSwitch
:title="$t('Allow PayPal Service')"
:description="$t('Allow your users pay by their credit card')"
:is-last="!paypal.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_paypal', paypal.allowedService)"
v-model="paypal.allowedService"
:state="paypal.allowedService"
/>
</AppInputSwitch>
<!--Stripe credentials are set up-->
<div v-if="paypal.allowedService">
<div v-if="paypal.isConfigured">
<AppInputSwitch :title="$t('Live Mode')" :description="$t('Toggle amid live and sandbox mode')">
<SwitchInput @input="$updateText('/admin/settings', 'paypal_live', config.isPayPalLive)" v-model="config.isPayPalLive" :state="config.isPayPalLive" />
<SwitchInput
@input="$updateText('/admin/settings', 'paypal_live', config.isPayPalLive)"
v-model="config.isPayPalLive"
:state="config.isPayPalLive"
/>
</AppInputSwitch>
<AppInputText
@@ -265,15 +365,27 @@
>
<textarea
rows="2"
@input="$updateText('/admin/settings', 'paypal_payment_description', paypal.paymentDescription, true)"
@input="
$updateText(
'/admin/settings',
'paypal_payment_description',
paypal.paymentDescription,
true
)
"
v-model="paypal.paymentDescription"
:placeholder="$t('Describe in short which methods user can pay with this payment method...')"
:placeholder="
$t('Describe in short which methods user can pay with this payment method...')
"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText :title="$t('Your Webhook URL')" :description="$t('Please copy your url and paste it to the service webhook setup.')">
<AppInputText
:title="$t('Your Webhook URL')"
:description="$t('Please copy your url and paste it to the service webhook setup.')"
>
<CopyInput size="small" :str="getWebhookEndpoint('paypal')" />
</AppInputText>
@@ -299,7 +411,13 @@
<FormLabel v-if="!paypal.isConfigured" icon="shield">
{{ $t('Configure Your Credentials') }}
</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Publishable Key" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Publishable Key"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('admin_settings.payments.stripe_pub_key')" :error="errors[0]">
<input
v-model="paypal.credentials.key"
@@ -333,7 +451,13 @@
</AppInputText>
</ValidationProvider>
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('Store Credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -390,7 +514,9 @@ export default {
computed: {
...mapGetters(['subscriptionTypes', 'config']),
submitButtonText() {
return this.isLoading ? this.$t('admin_settings.payments.button_testing') : this.$t('admin_settings.payments.button_submit')
return this.isLoading
? this.$t('admin_settings.payments.button_testing')
: this.$t('admin_settings.payments.button_submit')
},
},
data() {
@@ -528,9 +654,10 @@ export default {
},
},
created() {
events.$on('action:confirmed', (data) => {
if (data.operation === 'change-subscription-type') this.$updateText('/admin/settings', 'subscription_type', data.type)
})
events.$on('action:confirmed', (data) => {
if (data.operation === 'change-subscription-type')
this.$updateText('/admin/settings', 'subscription_type', data.type)
})
// Set payment description
this.stripe.paymentDescription = this.config.stripe_payment_description
+28 -5
View File
@@ -12,10 +12,20 @@
</div>
<!--Datatable-->
<DatatableWrapper @data="plans = $event" @init="isLoading = false" api="/api/subscriptions/admin/plans" :paginator="true" :columns="columns" class="overflow-x-auto">
<DatatableWrapper
@data="plans = $event"
@init="isLoading = false"
api="/api/subscriptions/admin/plans"
:paginator="true"
:columns="columns"
class="overflow-x-auto"
>
<template slot-scope="{ row }">
<!--Metered subscription-->
<tr v-if="config.subscriptionType === 'metered'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'metered'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-5 pr-3 md:pr-1">
<router-link
class="text-sm font-bold"
@@ -73,10 +83,19 @@
</tr>
<!--Fixed subscription-->
<tr v-if="config.subscriptionType === 'fixed'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'fixed'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-5 pr-3 md:pr-1">
<SwitchInput
@input="$updateInput(`/subscriptions/admin/plans/${row.data.id}`, 'visible', row.data.attributes.visible)"
@input="
$updateInput(
`/subscriptions/admin/plans/${row.data.id}`,
'visible',
row.data.attributes.visible
)
"
v-model="row.data.attributes.visible"
:state="row.data.attributes.visible"
class="switch"
@@ -144,7 +163,11 @@
<!--Empty State-->
<div v-if="config.isEmptyPlans" class="flex h-full items-center justify-center">
<div class="text-center">
<img class="mb-6 inline-block w-28" src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f9fe.svg" alt="transaction" />
<img
class="mb-6 inline-block w-28"
src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f9fe.svg"
alt="transaction"
/>
<h1 class="mb-1 text-2xl font-bold">
{{ $t('There is Nothing') }}
@@ -39,7 +39,14 @@
<div class="justify-items md:flex md:space-x-4">
<!--Price-->
<ValidationProvider tag="div" mode="passive" name="Price" rules="required" v-slot="{ errors }" class="w-full">
<ValidationProvider
tag="div"
mode="passive"
name="Price"
rules="required"
v-slot="{ errors }"
class="w-full"
>
<AppInputText :title="$t('admin_page_plans.form.price')" class="w-full">
<input
v-model="plan.amount"
@@ -55,9 +62,21 @@
</ValidationProvider>
<!--Currency-->
<ValidationProvider tag="div" mode="passive" name="Currency" rules="required" v-slot="{ errors }" class="w-full">
<ValidationProvider
tag="div"
mode="passive"
name="Currency"
rules="required"
v-slot="{ errors }"
class="w-full"
>
<AppInputText :title="$t('Currency')" class="w-full">
<SelectInput v-model="plan.currency" :options="currencyList" :placeholder="$t('Select plan currency')" :isError="errors[0]" />
<SelectInput
v-model="plan.currency"
:options="currencyList"
:placeholder="$t('Select plan currency')"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
</div>
@@ -65,7 +84,12 @@
<!--Interval-->
<ValidationProvider tag="div" mode="passive" name="Interval" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Interval')" :is-last="true">
<SelectInput v-model="plan.interval" :options="intervalList" :placeholder="$t('Select billing interval')" :isError="errors[0]" />
<SelectInput
v-model="plan.interval"
:options="intervalList"
:placeholder="$t('Select billing interval')"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
</div>
@@ -76,8 +100,17 @@
</FormLabel>
<!--Storage Capacity-->
<ValidationProvider tag="div" mode="passive" name="Max Storage Capacity" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('admin_page_plans.form.storage')" :description="$t('admin_page_plans.form.storage_helper')">
<ValidationProvider
tag="div"
mode="passive"
name="Max Storage Capacity"
rules="required"
v-slot="{ errors }"
>
<AppInputText
:title="$t('admin_page_plans.form.storage')"
:description="$t('admin_page_plans.form.storage_helper')"
>
<input
v-model="plan.features.max_storage_amount"
:placeholder="$t('admin_page_plans.form.storage_plac')"
@@ -92,7 +125,11 @@
<!--Team Members-->
<ValidationProvider tag="div" mode="passive" name="Max Team Members" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Team Members')" :description="$t('To set unlimited team members, type -1 into form')" :is-last="true">
<AppInputText
:title="$t('Team Members')"
:description="$t('To set unlimited team members, type -1 into form')"
:is-last="true"
>
<input
v-model="plan.features.max_team_members"
:placeholder="$t('Add max team members in number')"
@@ -33,7 +33,12 @@
<!--Currency-->
<ValidationProvider tag="div" mode="passive" name="Currency" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Currency')" class="w-full" :is-last="true">
<SelectInput v-model="plan.currency" :options="currencyList" :placeholder="$t('Select plan currency')" :isError="errors[0]" />
<SelectInput
v-model="plan.currency"
:options="currencyList"
:placeholder="$t('Select plan currency')"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
</div>
@@ -45,11 +50,26 @@
<!--Bandwidth-->
<div>
<AppInputSwitch :title="$t('Bandwidth Price per 1GB')" :description="$t('Charge your user by the amount of data he upload or download.')">
<SwitchInput v-model="plan.features.bandwidth.active" class="switch" :state="plan.features.bandwidth.active" />
<AppInputSwitch
:title="$t('Bandwidth Price per 1GB')"
:description="$t('Charge your user by the amount of data he upload or download.')"
>
<SwitchInput
v-model="plan.features.bandwidth.active"
class="switch"
:state="plan.features.bandwidth.active"
/>
</AppInputSwitch>
<ValidationProvider v-if="plan.features.bandwidth.active" class="-mt-3" tag="div" mode="passive" name="Bandwidth Price" rules="required" v-slot="{ errors }">
<ValidationProvider
v-if="plan.features.bandwidth.active"
class="-mt-3"
tag="div"
mode="passive"
name="Bandwidth Price"
rules="required"
v-slot="{ errors }"
>
<AppInputText class="w-full">
<input
v-model="plan.features.bandwidth.per_unit"
@@ -67,12 +87,27 @@
<!--Storage-->
<div>
<AppInputSwitch :title="$t('Storage Price per 1GB')" :description="$t('Charge your user by the amount of data he has stored on the disk per 1GB.')">
<SwitchInput v-model="plan.features.storage.active" class="switch" :state="plan.features.storage.active" />
<AppInputSwitch
:title="$t('Storage Price per 1GB')"
:description="$t('Charge your user by the amount of data he has stored on the disk per 1GB.')"
>
<SwitchInput
v-model="plan.features.storage.active"
class="switch"
:state="plan.features.storage.active"
/>
</AppInputSwitch>
</div>
<ValidationProvider v-if="plan.features.storage.active" class="-mt-3" tag="div" mode="passive" name="Storage Price" rules="required" v-slot="{ errors }">
<ValidationProvider
v-if="plan.features.storage.active"
class="-mt-3"
tag="div"
mode="passive"
name="Storage Price"
rules="required"
v-slot="{ errors }"
>
<AppInputText class="w-full">
<input
v-model="plan.features.storage.per_unit"
@@ -89,12 +124,27 @@
<!--Member-->
<div>
<AppInputSwitch :title="$t('Price per 1 Member')" :description="$t('Charge your user by the total members he use in his Team Folders.')">
<SwitchInput v-model="plan.features.member.active" class="switch" :state="plan.features.member.active" />
<AppInputSwitch
:title="$t('Price per 1 Member')"
:description="$t('Charge your user by the total members he use in his Team Folders.')"
>
<SwitchInput
v-model="plan.features.member.active"
class="switch"
:state="plan.features.member.active"
/>
</AppInputSwitch>
</div>
<ValidationProvider v-if="plan.features.member.active" class="-mt-3" tag="div" mode="passive" name="Member Price" rules="required" v-slot="{ errors }">
<ValidationProvider
v-if="plan.features.member.active"
class="-mt-3"
tag="div"
mode="passive"
name="Member Price"
rules="required"
v-slot="{ errors }"
>
<AppInputText class="w-full">
<input
v-model="plan.features.member.per_unit"
@@ -111,11 +161,27 @@
<!--Flat Fee-->
<div>
<AppInputSwitch :title="$t('Flat Fee per Cycle')" :description="$t('Charge monthly flat fee.')" :is-last="!plan.features.flatFee.active">
<SwitchInput v-model="plan.features.flatFee.active" class="switch" :state="plan.features.flatFee.active" />
<AppInputSwitch
:title="$t('Flat Fee per Cycle')"
:description="$t('Charge monthly flat fee.')"
:is-last="!plan.features.flatFee.active"
>
<SwitchInput
v-model="plan.features.flatFee.active"
class="switch"
:state="plan.features.flatFee.active"
/>
</AppInputSwitch>
<ValidationProvider v-if="plan.features.flatFee.active" class="-mt-3" tag="div" mode="passive" name="FlatFee Price" rules="required" v-slot="{ errors }">
<ValidationProvider
v-if="plan.features.flatFee.active"
class="-mt-3"
tag="div"
mode="passive"
name="FlatFee Price"
rules="required"
v-slot="{ errors }"
>
<AppInputText class="w-full" :is-last="true">
<input
v-model="plan.features.flatFee.per_unit"
@@ -273,7 +339,7 @@ export default {
}
})
.catch((error) => {
console.log(error);
console.log(error)
events.$emit('toaster', {
type: 'danger',
message: this.$t('popup_error.title'),
@@ -4,7 +4,13 @@
{{ $t('admin_page_plans.form.title_delete') }}
</FormLabel>
<ValidationObserver ref="deletePlan" @submit.prevent="deletePlan" v-slot="{ invalid }" tag="form">
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Plan name" :rules="'required|is:' + plan.attributes.name">
<ValidationProvider
tag="div"
v-slot="{ errors }"
mode="passive"
name="Plan name"
:rules="'required|is:' + plan.attributes.name"
>
<AppInputText
:title="
$t('admin_page_user.label_delete_user', {
@@ -23,7 +29,13 @@
:class="{ 'border-red': errors[0] }"
class="focus-border-theme input-dark"
/>
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit" button-style="danger" class="w-full sm:w-auto">
<ButtonBase
:loading="isSendingRequest"
:disabled="isSendingRequest"
type="submit"
button-style="danger"
class="w-full sm:w-auto"
>
{{ $t('admin_page_plans.delete_plan_button') }}
</ButtonBase>
</div>
@@ -6,9 +6,18 @@
</FormLabel>
<!--Visible-->
<AppInputSwitch :title="$t('admin_page_plans.form.status')" :description="$t('admin_page_plans.form.status_help')">
<AppInputSwitch
:title="$t('admin_page_plans.form.status')"
:description="$t('admin_page_plans.form.status_help')"
>
<SwitchInput
@input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'visible', plan.attributes.visible)"
@input="
$updateInput(
'/subscriptions/admin/plans/' + $route.params.id,
'visible',
plan.attributes.visible
)
"
v-model="plan.attributes.visible"
class="switch"
:state="plan.attributes.visible"
@@ -18,7 +27,9 @@
<!--Name-->
<AppInputText :title="$t('admin_page_plans.form.name')">
<input
@input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'name', plan.attributes.name)"
@input="
$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'name', plan.attributes.name)
"
v-model="plan.attributes.name"
:placeholder="$t('admin_page_plans.form.name_plac')"
type="text"
@@ -29,7 +40,13 @@
<!--Description-->
<AppInputText :title="$t('admin_page_plans.form.description')">
<textarea
@input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'description', plan.attributes.description)"
@input="
$updateInput(
'/subscriptions/admin/plans/' + $route.params.id,
'description',
plan.attributes.description
)
"
v-model="plan.attributes.description"
:placeholder="$t('admin_page_plans.form.description_plac')"
class="focus-border-theme input-dark"
@@ -38,7 +55,11 @@
<InfoBox style="margin-bottom: 0">
<p>
{{ $t('Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.') }}
{{
$t(
'Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.'
)
}}
</p>
</InfoBox>
</div>
@@ -48,9 +69,18 @@
</FormLabel>
<!--Storage Capacity-->
<AppInputText :title="$t('admin_page_plans.form.storage')" :description="$t('admin_page_plans.form.storage_helper')">
<AppInputText
:title="$t('admin_page_plans.form.storage')"
:description="$t('admin_page_plans.form.storage_helper')"
>
<input
@input="$updateInput(`/subscriptions/admin/plans/${$route.params.id}/features`, 'max_storage_amount', plan.attributes.features.max_storage_amount)"
@input="
$updateInput(
`/subscriptions/admin/plans/${$route.params.id}/features`,
'max_storage_amount',
plan.attributes.features.max_storage_amount
)
"
v-model="plan.attributes.features.max_storage_amount"
:placeholder="$t('admin_page_plans.form.storage_plac')"
type="number"
@@ -63,7 +93,13 @@
<!--Team Members-->
<AppInputText :title="$t('Max Team Members')" is-last="true">
<input
@input="$updateInput(`/subscriptions/admin/plans/${$route.params.id}/features`, 'max_team_members', plan.attributes.features.max_team_members)"
@input="
$updateInput(
`/subscriptions/admin/plans/${$route.params.id}/features`,
'max_team_members',
plan.attributes.features.max_team_members
)
"
v-model="plan.attributes.features.max_team_members"
:placeholder="$t('Add max team members in number')"
type="number"
@@ -8,7 +8,9 @@
<!--Name-->
<AppInputText :title="$t('admin_page_plans.form.name')">
<input
@input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'name', plan.attributes.name)"
@input="
$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'name', plan.attributes.name)
"
v-model="plan.attributes.name"
:placeholder="$t('admin_page_plans.form.name_plac')"
type="text"
@@ -19,7 +21,13 @@
<!--Description-->
<AppInputText :title="$t('admin_page_plans.form.description')" :is-last="true">
<textarea
@input="$updateInput('/subscriptions/admin/plans/' + $route.params.id, 'description', plan.attributes.description)"
@input="
$updateInput(
'/subscriptions/admin/plans/' + $route.params.id,
'description',
plan.attributes.description
)
"
v-model="plan.attributes.description"
:placeholder="$t('admin_page_plans.form.description_plac')"
class="focus-border-theme input-dark"
@@ -39,7 +47,9 @@
class="w-full"
>
<input
:value="formatCurrency(plan.attributes.currency, plan.attributes.features.bandwidth.tiers[0].per_unit)"
:value="
formatCurrency(plan.attributes.currency, plan.attributes.features.bandwidth.tiers[0].per_unit)
"
type="text"
class="focus-border-theme input-dark"
disabled
@@ -54,7 +64,9 @@
class="w-full"
>
<input
:value="formatCurrency(plan.attributes.currency, plan.attributes.features.storage.tiers[0].per_unit)"
:value="
formatCurrency(plan.attributes.currency, plan.attributes.features.storage.tiers[0].per_unit)
"
type="text"
class="focus-border-theme input-dark"
disabled
@@ -77,9 +89,16 @@
</AppInputText>
<!--Flat Fee-->
<AppInputText v-if="plan.attributes.features.flatFee" :title="$t('Flat Fee per Cycle')" :description="$t('Charge monthly flat fee.')" class="w-full">
<AppInputText
v-if="plan.attributes.features.flatFee"
:title="$t('Flat Fee per Cycle')"
:description="$t('Charge monthly flat fee.')"
class="w-full"
>
<input
:value="formatCurrency(plan.attributes.currency, plan.attributes.features.flatFee.tiers[0].per_unit)"
:value="
formatCurrency(plan.attributes.currency, plan.attributes.features.flatFee.tiers[0].per_unit)
"
type="text"
class="focus-border-theme input-dark"
disabled
@@ -88,7 +107,11 @@
<InfoBox style="margin-bottom: 0">
<p>
{{ $t('Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.') }}
{{
$t(
'Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.'
)
}}
</p>
</InfoBox>
</div>
@@ -10,7 +10,10 @@
>
<!--Table data content-->
<template slot-scope="{ row }">
<tr v-if="config.subscriptionType === 'metered'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'metered'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-3 pr-3 md:pr-1">
<router-link
class="flex items-center"
@@ -23,7 +26,10 @@
>
<MemberAvatar :is-border="false" :size="36" :member="row.data.relationships.user" />
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.user.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
@@ -38,10 +44,17 @@
</span>
</td>
<td class="pl-3 text-right md:pl-1">
<img class="inline-block max-h-5" :src="$getPaymentLogo(row.data.attributes.driver)" :alt="row.data.attributes.driver" />
<img
class="inline-block max-h-5"
:src="$getPaymentLogo(row.data.attributes.driver)"
:alt="row.data.attributes.driver"
/>
</td>
</tr>
<tr v-if="config.subscriptionType === 'fixed'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'fixed'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-3 pr-3 md:pr-1">
<router-link
class="flex items-center"
@@ -54,7 +67,10 @@
>
<MemberAvatar :is-border="false" :size="36" :member="row.data.relationships.user" />
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.user.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
@@ -76,7 +92,11 @@
<td class="px-3 md:px-1">
<span class="text-sm font-bold">
<!--todo: update renew attribute-->
{{ row.data.attributes.renews_at ? row.data.attributes.renews_at : row.data.attributes.created_at }}
{{
row.data.attributes.renews_at
? row.data.attributes.renews_at
: row.data.attributes.created_at
}}
</span>
</td>
<td class="px-3 md:px-1">
@@ -85,7 +105,11 @@
</span>
</td>
<td class="pl-3 text-right md:pl-1">
<img class="inline-block max-h-5" :src="$getPaymentLogo(row.data.attributes.driver)" :alt="row.data.attributes.driver" />
<img
class="inline-block max-h-5"
:src="$getPaymentLogo(row.data.attributes.driver)"
:alt="row.data.attributes.driver"
/>
</td>
</tr>
</template>
+19 -4
View File
@@ -24,7 +24,10 @@
>
<MemberAvatar :is-border="false" :size="36" :member="row.data.relationships.user" />
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.user.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
@@ -51,7 +54,11 @@
<td class="px-3 md:px-1">
<span class="text-sm font-bold">
<!--todo: update renew attribute-->
{{ row.data.attributes.renews_at ? row.data.attributes.renews_at : row.data.attributes.created_at }}
{{
row.data.attributes.renews_at
? row.data.attributes.renews_at
: row.data.attributes.created_at
}}
</span>
</td>
<td class="px-3 md:px-1">
@@ -60,7 +67,11 @@
</span>
</td>
<td class="pl-3 text-right md:pl-1">
<img class="inline-block max-h-5" :src="$getPaymentLogo(row.data.attributes.driver)" :alt="row.data.attributes.driver" />
<img
class="inline-block max-h-5"
:src="$getPaymentLogo(row.data.attributes.driver)"
:alt="row.data.attributes.driver"
/>
</td>
</tr>
</template>
@@ -69,7 +80,11 @@
<!--Empty State-->
<div v-if="config.isEmptySubscriptions" class="flex h-full items-center justify-center">
<div class="text-center">
<img class="mb-6 inline-block w-28" src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f5c3.svg" alt="transaction" />
<img
class="mb-6 inline-block w-28"
src="https://twemoji.maxcdn.com/v/13.1.0/svg/1f5c3.svg"
alt="transaction"
/>
<h1 class="mb-1 text-2xl font-bold">
{{ $t('There is Nothing') }}
+46 -10
View File
@@ -14,10 +14,19 @@
</div>
<!--Datatable-->
<DatatableWrapper @init="isLoading = false" api="/api/admin/users" :paginator="true" :columns="columns" class="overflow-x-auto">
<DatatableWrapper
@init="isLoading = false"
api="/api/admin/users"
:paginator="true"
:columns="columns"
class="overflow-x-auto"
>
<template slot-scope="{ row }">
<!--Not a subscription-->
<tr v-if="config.subscriptionType === 'none'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'none'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-3 pr-3 md:pr-1">
<router-link
:to="{
@@ -26,9 +35,16 @@
}"
>
<div class="flex items-center">
<MemberAvatar :is-border="false" :size="44" :member="row.data.relationships.settings" />
<MemberAvatar
:is-border="false"
:size="44"
:member="row.data.relationships.settings"
/>
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.settings.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
@@ -85,7 +101,10 @@
</tr>
<!--Fixed subscription-->
<tr v-if="config.subscriptionType === 'fixed'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'fixed'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-3 pr-3 md:pr-1">
<router-link
:to="{
@@ -94,9 +113,16 @@
}"
>
<div class="flex items-center">
<MemberAvatar :is-border="false" :size="44" :member="row.data.relationships.settings" />
<MemberAvatar
:is-border="false"
:size="44"
:member="row.data.relationships.settings"
/>
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.settings.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
@@ -158,7 +184,10 @@
</tr>
<!--Metered subscription-->
<tr v-if="config.subscriptionType === 'metered'" class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
<tr
v-if="config.subscriptionType === 'metered'"
class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5"
>
<td class="py-3 pr-3 md:pr-1">
<router-link
:to="{
@@ -167,9 +196,16 @@
}"
>
<div class="flex items-center">
<MemberAvatar :is-border="false" :size="44" :member="row.data.relationships.settings" />
<MemberAvatar
:is-border="false"
:size="44"
:member="row.data.relationships.settings"
/>
<div class="ml-3 pr-10">
<b class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold" style="max-width: 155px">
<b
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
style="max-width: 155px"
>
{{ row.data.relationships.settings.data.attributes.name }}
</b>
<span class="block text-xs text-gray-600 dark:text-gray-500">
+35 -6
View File
@@ -10,10 +10,15 @@
</AppInputText>
</ValidationProvider>
<!--User Role-->
<!--User Role-->
<ValidationProvider tag="div" mode="passive" name="permission" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('admin_page_user.select_role')" :error="errors[0]">
<SelectInput v-model="user.role" :options="$translateSelectOptions(roles)" :placeholder="$t('admin_page_user.select_role')" :isError="errors[0]" />
<SelectInput
v-model="user.role"
:options="$translateSelectOptions(roles)"
:placeholder="$t('admin_page_user.select_role')"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
@@ -45,7 +50,14 @@
<!--Password-->
<div class="flex space-x-4">
<ValidationProvider tag="div" mode="passive" name="password" rules="required" v-slot="{ errors }" class="w-full">
<ValidationProvider
tag="div"
mode="passive"
name="password"
rules="required"
v-slot="{ errors }"
class="w-full"
>
<AppInputText :title="$t('page_registration.label_pass')" :error="errors[0]" :is-last="true">
<input
v-model="user.password"
@@ -56,8 +68,19 @@
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="password confirm" rules="required" v-slot="{ errors }" class="w-full">
<AppInputText :title="$t('page_registration.label_confirm_pass')" :error="errors[0]" :is-last="true">
<ValidationProvider
tag="div"
mode="passive"
name="password confirm"
rules="required"
v-slot="{ errors }"
class="w-full"
>
<AppInputText
:title="$t('page_registration.label_confirm_pass')"
:error="errors[0]"
:is-last="true"
>
<input
v-model="user.password_confirmation"
:placeholder="$t('admin_page_user.create_user.label_conf_pass')"
@@ -70,7 +93,13 @@
</div>
</div>
<div class="form-group">
<ButtonBase :disabled="isLoading" :loading="isLoading" button-style="theme" type="submit" class="w-full sm:w-auto">
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full sm:w-auto"
>
{{ $t('admin_page_user.create_user.submit') }}
</ButtonBase>
</div>
@@ -23,7 +23,13 @@
class="focus-border-theme input-dark"
:class="{ 'border-red': errors[0] }"
/>
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit" button-style="danger" class="w-full sm:w-auto">
<ButtonBase
:loading="isSendingRequest"
:disabled="isSendingRequest"
type="submit"
button-style="danger"
class="w-full sm:w-auto"
>
{{ $t('admin_page_user.delete_user') }}
</ButtonBase>
</div>
@@ -7,10 +7,26 @@
</FormLabel>
<ValidationObserver ref="changeRole" @submit.prevent="changeRole" v-slot="{ invalid }" tag="form">
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Role" rules="required">
<AppInputText :title="$t('admin_page_user.select_role')" :description="$t('user_box_role.description')" :error="errors[0]" :is-last="true">
<AppInputText
:title="$t('admin_page_user.select_role')"
:description="$t('user_box_role.description')"
:error="errors[0]"
:is-last="true"
>
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
<SelectInput v-model="userRole" :options="$translateSelectOptions(roles)" :placeholder="$t('admin_page_user.select_role')" :isError="errors[0]" />
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit" button-style="theme" class="w-full sm:w-auto">
<SelectInput
v-model="userRole"
:options="$translateSelectOptions(roles)"
:placeholder="$t('admin_page_user.select_role')"
:isError="errors[0]"
/>
<ButtonBase
:loading="isSendingRequest"
:disabled="isSendingRequest"
type="submit"
button-style="theme"
class="w-full sm:w-auto"
>
{{ $t('admin_page_user.save_role') }}
</ButtonBase>
</div>
@@ -10,9 +10,19 @@
{{ user.data.relationships.balance.data.attributes.formatted }}
</b>
<ValidationObserver ref="creditUserBalance" @submit.prevent="increaseBalance" v-slot="{ invalid }" tag="form" class="mt-6">
<ValidationObserver
ref="creditUserBalance"
@submit.prevent="increaseBalance"
v-slot="{ invalid }"
tag="form"
class="mt-6"
>
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Balance Amount" rules="required">
<AppInputText :description="$t('User balance will be increased for the amount above.')" :error="errors[0]" :is-last="true">
<AppInputText
:description="$t('User balance will be increased for the amount above.')"
:error="errors[0]"
:is-last="true"
>
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
<input
v-model="balanceAmount"
@@ -23,7 +33,13 @@
class="focus-border-theme input-dark"
:class="{ 'border-red': errors[0] }"
/>
<ButtonBase type="submit" button-style="theme" class="w-full sm:w-auto" :loading="isUpdatingBalanceAmount" :disabled="isUpdatingBalanceAmount">
<ButtonBase
type="submit"
button-style="theme"
class="w-full sm:w-auto"
:loading="isUpdatingBalanceAmount"
:disabled="isUpdatingBalanceAmount"
>
{{ $t('Increase Balance') }}
</ButtonBase>
</div>
@@ -5,8 +5,18 @@
{{ $t('user_box_password.title') }}
</FormLabel>
<AppInputText :title="$t('Reset User Password')" :description="$t('user_box_password.description')" :is-last="true">
<ButtonBase @click.native="requestPasswordResetEmail" :loading="isSendingRequest" :disabled="isSendingRequest" class="w-full sm:w-auto" button-style="theme">
<AppInputText
:title="$t('Reset User Password')"
:description="$t('user_box_password.description')"
:is-last="true"
>
<ButtonBase
@click.native="requestPasswordResetEmail"
:loading="isSendingRequest"
:disabled="isSendingRequest"
class="w-full sm:w-auto"
button-style="theme"
>
{{ $t('admin_page_user.send_password_link') }}
</ButtonBase>
</AppInputText>
@@ -10,7 +10,12 @@
{{ storage.data.attributes.used }}
</b>
<b v-if="config.subscriptionType === 'fixed' || (config.subscriptionType === 'none' && config.storageLimit)" class="mt-0.5 block text-sm text-gray-400">
<b
v-if="
config.subscriptionType === 'fixed' || (config.subscriptionType === 'none' && config.storageLimit)
"
class="mt-0.5 block text-sm text-gray-400"
>
{{ $t('Total of') }} {{ storage.data.attributes.capacity }}
{{ $t('Used') }}
</b>
@@ -53,13 +58,26 @@
</div>
<!--Set Storage Size-->
<div v-if="config.storageLimit && !user.data.attributes.subscription && config.subscriptionType !== 'metered'" class="card shadow-card">
<div
v-if="config.storageLimit && !user.data.attributes.subscription && config.subscriptionType !== 'metered'"
class="card shadow-card"
>
<FormLabel>
{{ $t('user_box_storage.title') }}
</FormLabel>
<ValidationObserver ref="changeStorageCapacity" @submit.prevent="changeStorageCapacity" v-slot="{ invalid }" tag="form">
<ValidationObserver
ref="changeStorageCapacity"
@submit.prevent="changeStorageCapacity"
v-slot="{ invalid }"
tag="form"
>
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Capacity" rules="required">
<AppInputText :title="$t('admin_page_user.label_change_capacity')" :description="$t('user_box_storage.description')" :error="errors[0]" :is-last="true">
<AppInputText
:title="$t('admin_page_user.label_change_capacity')"
:description="$t('user_box_storage.description')"
:error="errors[0]"
:is-last="true"
>
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
<input
v-model="capacity"
@@ -70,7 +88,13 @@
class="focus-border-theme input-dark"
:class="{ 'border-red': errors[0] }"
/>
<ButtonBase :loading="isSendingRequest" :disabled="isSendingRequest" type="submit" button-style="theme" class="w-full sm:w-auto">
<ButtonBase
:loading="isSendingRequest"
:disabled="isSendingRequest"
type="submit"
button-style="theme"
class="w-full sm:w-auto"
>
{{ $t('admin_page_user.change_capacity') }}
</ButtonBase>
</div>
@@ -1,8 +1,16 @@
<template>
<PageTab :is-loading="isLoading">
<UserMeteredSubscription v-if="subscription && config.subscriptionType === 'metered'" :subscription="subscription" :user="user" />
<UserMeteredSubscription
v-if="subscription && config.subscriptionType === 'metered'"
:subscription="subscription"
:user="user"
/>
<UserFixedSubscription v-if="subscription && config.subscriptionType === 'fixed'" :subscription="subscription" :user="user" />
<UserFixedSubscription
v-if="subscription && config.subscriptionType === 'fixed'"
:subscription="subscription"
:user="user"
/>
<!--Free Plan-->
<div v-if="!subscription && config.subscriptionType === 'fixed'" class="card shadow-card">
@@ -34,11 +42,18 @@
>
<template slot-scope="{ row }">
<!--Transaction rows-->
<MeteredTransactionRow v-if="config.subscriptionType === 'metered'" :row="row" @showDetail="showTransactionDetail" />
<MeteredTransactionRow
v-if="config.subscriptionType === 'metered'"
:row="row"
@showDetail="showTransactionDetail"
/>
<FixedTransactionRow v-if="config.subscriptionType === 'fixed'" :row="row" />
<!--Transaction detail-->
<MeteredTransactionDetailRow v-if="row.data.attributes.metadata && showedTransactionDetailById === row.data.id" :row="row" />
<MeteredTransactionDetailRow
v-if="row.data.attributes.metadata && showedTransactionDetailById === row.data.id"
:row="row"
/>
</template>
<!--Empty page-->
@@ -89,7 +104,9 @@ export default {
fixed: ['type', 'user_id'],
}
return this.$store.getters.transactionColumns.filter((column) => !filter[config.subscriptionType].includes(column.field))
return this.$store.getters.transactionColumns.filter(
(column) => !filter[config.subscriptionType].includes(column.field)
)
},
},
data() {
+40 -7
View File
@@ -4,10 +4,25 @@
<AuthContent name="create-new-password" :visible="true">
<Headline :title="$t('page_create_password.title')" :description="$t('page_create_password.subtitle')" />
<ValidationObserver @submit.prevent="createNewPassword" ref="create_new_password" v-slot="{ invalid }" tag="form" class="mb-12 space-y-4 text-left">
<ValidationObserver
@submit.prevent="createNewPassword"
ref="create_new_password"
v-slot="{ invalid }"
tag="form"
class="mb-12 space-y-4 text-left"
>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_create_password.label_email') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="E-Mail" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_create_password.label_email') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="E-Mail"
rules="required"
v-slot="{ errors }"
>
<input
v-model="recoverPassword.email"
:placeholder="$t('page_login.placeholder_email')"
@@ -20,8 +35,17 @@
</div>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_create_password.label_new_pass') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="New Password" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_create_password.label_new_pass') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="New Password"
rules="required"
v-slot="{ errors }"
>
<input
v-model="recoverPassword.newPassword"
:placeholder="$t('page_create_password.label_new_pass')"
@@ -34,8 +58,17 @@
</div>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_create_password.label_confirm_pass') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="Confirm Password" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_create_password.label_confirm_pass') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="Confirm Password"
rules="required"
v-slot="{ errors }"
>
<input
v-model="recoverPassword.newPasswordConfirm"
:placeholder="$t('page_create_password.label_confirm_pass')"
+16 -3
View File
@@ -2,7 +2,10 @@
<AuthContentWrapper ref="auth" class="h-screen">
<!--Forgotten your password?-->
<AuthContent name="forgotten-password" :visible="true">
<Headline :title="$t('page_forgotten_password.title')" :description="$t('page_forgotten_password.subtitle')" />
<Headline
:title="$t('page_forgotten_password.title')"
:description="$t('page_forgotten_password.subtitle')"
/>
<ValidationObserver
@submit.prevent="forgottenPassword"
@@ -11,7 +14,14 @@
tag="form"
class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0"
>
<ValidationProvider tag="div" mode="passive" class="relative w-full text-left" name="E-Mail" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
class="relative w-full text-left"
name="E-Mail"
rules="required"
v-slot="{ errors }"
>
<input
v-model="recoverEmail"
:placeholder="$t('page_login.placeholder_email')"
@@ -41,7 +51,10 @@
<!--Password reset link send-->
<AuthContent name="password-reset-link-sended" :visible="false">
<Headline :title="$t('page_forgotten_password.pass_sennded_title')" :description="$t('page_forgotten_password.pass_sennded_subtitle')" />
<Headline
:title="$t('page_forgotten_password.pass_sennded_title')"
:description="$t('page_forgotten_password.pass_sennded_subtitle')"
/>
<span class="block">
{{ $t('page_forgotten_password.password_remember_text') }}
+6 -1
View File
@@ -6,7 +6,12 @@
<!--Default application logo-->
<div v-if="!$slots.default">
<!--Image logo-->
<img v-if="config.app_logo" class="mx-auto mb-6 w-28 md:w-32" :src="$getImage(config.app_logo)" :alt="config.app_name" />
<img
v-if="config.app_logo"
class="mx-auto mb-6 w-28 md:w-32"
:src="$getImage(config.app_logo)"
:alt="config.app_name"
/>
<!--Text logo if image isn't available-->
<b v-if="!config.app_logo" class="mb-10 block text-xl font-bold">
+104 -17
View File
@@ -4,8 +4,21 @@
<AuthContent name="log-in" :visible="true">
<Headline :title="$t('page_login.title')" :description="$t('page_login.subtitle')" />
<ValidationObserver @submit.prevent="logIn" ref="log_in" v-slot="{ invalid }" tag="form" class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0">
<ValidationProvider class="w-full text-left" tag="div" mode="passive" name="E-Mail" rules="required" v-slot="{ errors }">
<ValidationObserver
@submit.prevent="logIn"
ref="log_in"
v-slot="{ invalid }"
tag="form"
class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0"
>
<ValidationProvider
class="w-full text-left"
tag="div"
mode="passive"
name="E-Mail"
rules="required"
v-slot="{ errors }"
>
<input
class="focus-border-theme w-full appearance-none rounded-lg border border-transparent bg-light-background px-5 py-3.5 font-bold dark:bg-2x-dark-foreground"
:class="{ 'border-red': errors[0] }"
@@ -16,7 +29,13 @@
<span class="text-left text-xs text-red-600" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton class="w-full justify-center md:w-min" icon="chevron-right" :text="$t('page_login.button_next')" :loading="isLoading" :disabled="isLoading" />
<AuthButton
class="w-full justify-center md:w-min"
icon="chevron-right"
:text="$t('page_login.button_next')"
:loading="isLoading"
:disabled="isLoading"
/>
</ValidationObserver>
<SocialiteAuthenticationButtons />
@@ -31,12 +50,33 @@
<!--Log in By Password-->
<AuthContent name="sign-in" :visible="false">
<Headline v-if="checkedAccount" :title="$t('page_sign_in.title', { name: checkedAccount.name })" :description="$t('page_sign_in.subtitle')">
<img class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl" :src="checkedAccount.avatar.md" :alt="checkedAccount.name" />
<Headline
v-if="checkedAccount"
:title="$t('page_sign_in.title', { name: checkedAccount.name })"
:description="$t('page_sign_in.subtitle')"
>
<img
class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl"
:src="checkedAccount.avatar.md"
:alt="checkedAccount.name"
/>
</Headline>
<ValidationObserver @submit.prevent="singIn" ref="sign_in" v-slot="{ invalid }" tag="form" class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0">
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="User Password" rules="required" v-slot="{ errors }">
<ValidationObserver
@submit.prevent="singIn"
ref="sign_in"
v-slot="{ invalid }"
tag="form"
class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0"
>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="User Password"
rules="required"
v-slot="{ errors }"
>
<input
v-model="loginPassword"
:placeholder="$t('page_sign_in.placeholder_password')"
@@ -47,7 +87,13 @@
<span class="text-left text-xs text-red-600" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton class="w-full justify-center md:w-min" icon="chevron-right" :text="$t('page_sign_in.button_log_in')" :loading="isLoading" :disabled="isLoading" />
<AuthButton
class="w-full justify-center md:w-min"
icon="chevron-right"
:text="$t('page_sign_in.button_log_in')"
:loading="isLoading"
:disabled="isLoading"
/>
</ValidationObserver>
<span class="block">
@@ -60,8 +106,16 @@
<!--Resend verification email-->
<AuthContent name="not-verified" :visible="false">
<Headline v-if="checkedAccount" :title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })" :description="$t('page_not_verified.subtitle')">
<img class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl" :src="checkedAccount.avatar.md" :alt="checkedAccount.name" />
<Headline
v-if="checkedAccount"
:title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })"
:description="$t('page_not_verified.subtitle')"
>
<img
class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl"
:src="checkedAccount.avatar.md"
:alt="checkedAccount.name"
/>
</Headline>
<span class="block">
@@ -74,12 +128,27 @@
<!-- Log in by 2fa -->
<AuthContent name="two-factor-authentication" :visible="false">
<Headline v-if="checkedAccount" :title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })" :description="$t('page_sign_in_2fa_subtitle')">
<img class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl" :src="checkedAccount.avatar.md" :alt="checkedAccount.name" />
<Headline
v-if="checkedAccount"
:title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })"
:description="$t('page_sign_in_2fa_subtitle')"
>
<img
class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl"
:src="checkedAccount.avatar.md"
:alt="checkedAccount.name"
/>
</Headline>
<ValidationObserver ref="two_factor_authentication" v-slot="{ invalid }" tag="form" class="mb-12">
<ValidationProvider tag="div" mode="passive" class="mx-auto" name="Two Factor Authentication" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
class="mx-auto"
name="Two Factor Authentication"
rules="required"
v-slot="{ errors }"
>
<input
v-model="twoFactorCode"
ref="twoFactorCodeInput"
@@ -108,12 +177,27 @@
<!-- Log in by 2fa with recovery code -->
<AuthContent name="two-factor-recovery" :visible="false">
<Headline v-if="checkedAccount" :title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })" :description="$t('page_sign_in.2fa_recovery_subtitle')">
<img class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl" :src="checkedAccount.avatar.md" :alt="checkedAccount.name" />
<Headline
v-if="checkedAccount"
:title="$t('page_sign_in_2fa_title', { name: checkedAccount.name })"
:description="$t('page_sign_in.2fa_recovery_subtitle')"
>
<img
class="user-avatar mx-auto mb-6 w-28 rounded-xl shadow-xl"
:src="checkedAccount.avatar.md"
:alt="checkedAccount.name"
/>
</Headline>
<ValidationObserver ref="two_factor_recovery" v-slot="{ invalid }" tag="form" class="mb-12">
<ValidationProvider tag="div" mode="passive" class="mx-auto" name="Two Factor Recovery" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
class="mx-auto"
name="Two Factor Recovery"
rules="required"
v-slot="{ errors }"
>
<input
v-model="twoFactorRecoveryCode"
:placeholder="$t('page_sign_in.placeholder_2fa_recovery')"
@@ -299,7 +383,10 @@ export default {
},
async twoFactorChallenge(recovery) {
// Check if is normal authentication or recovery
if ((!recovery && this.twoFactorCode.length === 6) || (recovery && this.twoFactorRecoveryCode.length === 21)) {
if (
(!recovery && this.twoFactorCode.length === 6) ||
(recovery && this.twoFactorRecoveryCode.length === 21)
) {
this.isLoading = true
let payload = recovery ? { recovery_code: this.twoFactorRecoveryCode } : { code: this.twoFactorCode }
+51 -9
View File
@@ -4,10 +4,25 @@
<AuthContent name="sign-up" :visible="true" class="mt-4 mb-12">
<Headline :title="$t('page_registration.title')" :description="$t('page_registration.subtitle')" />
<ValidationObserver @submit.prevent="signUp" ref="sign_up" v-slot="{ invalid }" tag="form" class="mb-12 space-y-4 text-left">
<ValidationObserver
@submit.prevent="signUp"
ref="sign_up"
v-slot="{ invalid }"
tag="form"
class="mb-12 space-y-4 text-left"
>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_registration.label_email') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="E-Mail" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_registration.label_email') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="E-Mail"
rules="required"
v-slot="{ errors }"
>
<input
v-model="register.email"
:placeholder="$t('page_registration.placeholder_email')"
@@ -20,8 +35,17 @@
</div>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_registration.label_name') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="Full Name" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_registration.label_name') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="Full Name"
rules="required"
v-slot="{ errors }"
>
<input
v-model="register.name"
:placeholder="$t('page_registration.placeholder_name')"
@@ -34,8 +58,17 @@
</div>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_registration.label_pass') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="Your New Password" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_registration.label_pass') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="Your New Password"
rules="required"
v-slot="{ errors }"
>
<input
v-model="register.password"
:placeholder="$t('page_registration.placeholder_pass')"
@@ -48,8 +81,17 @@
</div>
<div class="mx-auto mb-5 md:flex md:max-w-lg md:items-center">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right"> {{ $t('page_registration.label_confirm_pass') }}: </label>
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="Confirm Your Password" rules="required" v-slot="{ errors }">
<label class="mb-1.5 block font-bold md:mb-0 md:w-72 md:pr-4 md:text-right">
{{ $t('page_registration.label_confirm_pass') }}:
</label>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="Confirm Your Password"
rules="required"
v-slot="{ errors }"
>
<input
v-model="register.password_confirmation"
:placeholder="$t('page_registration.placeholder_confirm_pass')"
@@ -1,7 +1,10 @@
<template>
<AuthContentWrapper class="h-screen">
<AuthContent :visible="true">
<Headline :title="$t('page_email_successfully_verified.title')" :description="$t('page_email_successfully_verified.subtitle')" />
<Headline
:title="$t('page_email_successfully_verified.title')"
:description="$t('page_email_successfully_verified.subtitle')"
/>
<router-link :to="{ name: 'SignIn' }">
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')" />
@@ -1,7 +1,10 @@
<template>
<AuthContentWrapper class="h-screen">
<AuthContent :visible="true">
<Headline :title="$t('page_email_successfully_send.title')" :description="$t('page_email_successfully_send.subtitle')" />
<Headline
:title="$t('page_email_successfully_send.title')"
:description="$t('page_email_successfully_send.subtitle')"
/>
<span class="block">
<router-link :to="{ name: 'Homepage' }" class="text-theme font-bold">
@@ -1,53 +1,84 @@
<template>
<ContentSidebar v-if="(navigationTree && navigationTree.length >= 1) && isVisibleNavigationBars" class="relative lg:!grid">
<!--Full screen button-->
<div @click="$store.dispatch('toggleNavigationBars')" class="absolute top-2.5 right-0 inline-block cursor-pointer p-3 opacity-0 transition-all duration-200 hover:opacity-70">
<ContentSidebar
v-if="navigationTree && navigationTree.length >= 1 && isVisibleNavigationBars"
class="relative lg:!grid"
>
<!--Full screen button-->
<div
@click="$store.dispatch('toggleNavigationBars')"
class="absolute top-2.5 right-0 inline-block cursor-pointer p-3 opacity-0 transition-all duration-200 hover:opacity-70"
>
<chevrons-left-icon size="18" />
</div>
<div class="mb-auto">
<!--Locations-->
<ContentGroup :title="$t('Base')">
<b @click="goHome" class="flex items-center py-2.5 cursor-pointer" :class="{'router-link-active': $route.params.id === sharedDetail.data.attributes.item_id}">
<home-icon size="17" class="vue-feather icon-active mr-2.5" />
<small class="text-active text-xs font-bold">
{{ $t('Home') }}
</small>
</b>
</ContentGroup>
<div class="mb-auto">
<!--Locations-->
<ContentGroup :title="$t('Base')">
<b
@click="goHome"
class="flex cursor-pointer items-center py-2.5"
:class="{ 'router-link-active': $route.params.id === sharedDetail.data.attributes.item_id }"
>
<home-icon size="17" class="vue-feather icon-active mr-2.5" />
<small class="text-active text-xs font-bold">
{{ $t('Home') }}
</small>
</b>
</ContentGroup>
<!--Navigator-->
<ContentGroup :title="$t('sidebar.navigator_title')" can-collapse="true">
<TreeMenuNavigator class="folder-tree" :depth="0" :nodes="folder" v-for="folder in navigationTree" :key="folder.id" />
</ContentGroup>
</div>
<!--Navigator-->
<ContentGroup :title="$t('sidebar.navigator_title')" can-collapse="true">
<TreeMenuNavigator
class="folder-tree"
:depth="0"
:nodes="folder"
v-for="folder in navigationTree"
:key="folder.id"
/>
</ContentGroup>
</div>
<ContentGroup class="mt-auto">
<router-link v-if="! config.isAuthenticated" :to="{name: 'SignIn'}" class="flex items-center cursor-pointer group py-2.5">
<ContentGroup class="mt-auto">
<router-link
v-if="!config.isAuthenticated"
:to="{ name: 'SignIn' }"
class="group flex cursor-pointer items-center py-2.5"
>
<div class="button-icon inline-block cursor-pointer rounded-xl pr-3">
<user-icon size="14" class="vue-feather group-hover-text-theme" />
</div>
<b class="text-xs group-hover-text-theme">
Sign In or Create Account
</b>
<b class="group-hover-text-theme text-xs"> Sign In or Create Account </b>
</router-link>
<div @click="$store.dispatch('toggleThemeMode')" :title="$t('dark_mode_toggle')" class="flex items-center cursor-pointer group py-2.5">
<div
@click="$store.dispatch('toggleThemeMode')"
:title="$t('dark_mode_toggle')"
class="group flex cursor-pointer items-center py-2.5"
>
<div class="button-icon inline-block cursor-pointer rounded-xl pr-3">
<sun-icon v-if="isDarkMode" size="14" class="vue-feather group-hover-text-theme" />
<moon-icon v-if="!isDarkMode" size="14" class="vue-feather group-hover-text-theme" />
</div>
<b class="text-xs group-hover-text-theme">
Set {{ isDarkMode ? 'Light' : 'Dark' }} Mode
</b>
<b class="group-hover-text-theme text-xs"> Set {{ isDarkMode ? 'Light' : 'Dark' }} Mode </b>
</div>
</ContentGroup>
</ContentGroup>
</ContentSidebar>
</template>
<script>
import { UserIcon, SunIcon, MoonIcon, ChevronsLeftIcon, FolderIcon, HomeIcon, LinkIcon, Trash2Icon, UploadCloudIcon, UserCheckIcon, UsersIcon, XIcon } from 'vue-feather-icons'
import {
UserIcon,
SunIcon,
MoonIcon,
ChevronsLeftIcon,
FolderIcon,
HomeIcon,
LinkIcon,
Trash2Icon,
UploadCloudIcon,
UserCheckIcon,
UsersIcon,
XIcon,
} from 'vue-feather-icons'
import TreeMenuNavigator from '../../../components/Others/TreeMenuNavigator'
import ContentSidebar from '../../../components/Sidebar/ContentSidebar'
import ContentGroup from '../../../components/Sidebar/ContentGroup'
@@ -60,11 +91,11 @@ export default {
TreeMenuNavigator,
ContentSidebar,
ContentGroup,
UserIcon,
SunIcon,
MoonIcon,
UserIcon,
SunIcon,
MoonIcon,
UploadCloudIcon,
ChevronsLeftIcon,
ChevronsLeftIcon,
UserCheckIcon,
FolderIcon,
Trash2Icon,
@@ -74,7 +105,15 @@ export default {
XIcon,
},
computed: {
...mapGetters(['sharedDetail', 'navigation', 'clipboard', 'config', 'user', 'isVisibleNavigationBars', 'isDarkMode']),
...mapGetters([
'sharedDetail',
'navigation',
'clipboard',
'config',
'user',
'isVisibleNavigationBars',
'isDarkMode',
]),
favourites() {
return this.user.data.relationships.favourites.data.attributes.folders
},
@@ -54,8 +54,8 @@
@dragover.prevent="dragEnter"
@dragleave="dragLeave"
@drop="dragFinish($event)"
:class="{'border-theme': area}"
class="pl-5 -ml-5 rounded-lg border-2 border-dashed border-transparent"
:class="{ 'border-theme': area }"
class="-ml-5 rounded-lg border-2 border-dashed border-transparent pl-5"
>
<!--Empty message-->
<small v-if="favourites.length === 0" class="text-xs text-gray-500 dark:text-gray-500" :key="0">
@@ -86,12 +86,9 @@
{{ folder.data.attributes.name }}
</span>
</div>
<div @click.stop="$removeFavourite(folder)" class="p-2 -m-2">
<x-icon
size="12"
class="mr-5 opacity-0 group-hover:opacity-100"
/>
</div>
<div @click.stop="$removeFavourite(folder)" class="-m-2 p-2">
<x-icon size="12" class="mr-5 opacity-0 group-hover:opacity-100" />
</div>
</div>
</div>
</ContentGroup>
+85 -15
View File
@@ -4,7 +4,11 @@
<OptionGroup v-if="item && isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -14,8 +18,17 @@
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup v-if="item">
<Option @click.native="$shareFileOrFolder(item)" :title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option @click.native="$convertAsTeamFolder(item)" v-if="isFolder" :title="$t('Convert as Team Folder')" icon="users" />
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
icon="share"
/>
<Option
@click.native="$convertAsTeamFolder(item)"
v-if="isFolder"
:title="$t('Convert as Team Folder')"
icon="users"
/>
</OptionGroup>
<OptionGroup v-if="item">
@@ -25,12 +38,27 @@
<MobileCreateMenu>
<OptionGroup :title="$t('Upload')">
<OptionUpload :class="{ 'is-inactive': !hasCapacity }" :title="$t('actions.upload')" type="file" :is-hover-disabled="true" />
<OptionUpload
:class="{ 'is-inactive': !hasCapacity }"
:title="$t('actions.upload')"
type="file"
:is-hover-disabled="true"
/>
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup :title="$t('Create')">
<Option @click.stop.native="$createTeamFolder" :title="$t('Create Team Folder')" icon="users" :is-hover-disabled="true" />
<Option @click.stop.native="createFolder" :title="$t('actions.create_folder')" icon="folder-plus" :is-hover-disabled="true" />
<Option
@click.stop.native="$createTeamFolder"
:title="$t('Create Team Folder')"
icon="users"
:is-hover-disabled="true"
/>
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
@@ -49,7 +77,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</MobileMultiSelectToolbar>
<ContextMenu>
@@ -59,7 +92,11 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$createFolder" :title="$t('context_menu.create_folder')" icon="create-folder" />
<Option
@click.native="$createFolder"
:title="$t('context_menu.create_folder')"
icon="create-folder"
/>
</OptionGroup>
</template>
@@ -67,26 +104,51 @@
<OptionGroup v-if="isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
:title="
item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')
"
icon="share"
/>
<Option @click.native="$convertAsTeamFolder(item)" v-if="isFolder" :title="$t('Convert as Team Folder')" icon="user-plus" />
<Option
@click.native="$convertAsTeamFolder(item)"
v-if="isFolder"
:title="$t('Convert as Team Folder')"
icon="user-plus"
/>
<Option
@click.native="$convertAsTeamFolder(item)"
v-if="isFolder"
:title="$t('Send Upload Request')"
icon="upload-cloud"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -94,7 +156,11 @@
<OptionGroup v-if="!hasFile">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -115,7 +181,11 @@
<MobileActionButton @click.native="$showMobileMenu('file-filter')" :icon="$getCurrentSectionIcon()">
{{ $getCurrentSectionName() }}
</MobileActionButton>
<MobileActionButton @click.native="$showMobileMenu('create-list')" v-if="$checkPermission(['master', 'editor'])" icon="cloud-plus">
<MobileActionButton
@click.native="$showMobileMenu('create-list')"
v-if="$checkPermission(['master', 'editor'])"
icon="cloud-plus"
>
{{ $t('mobile.create') }}
</MobileActionButton>
<MobileActionButton @click.native="$enableMultiSelectMode" icon="check-square">
+43 -8
View File
@@ -5,24 +5,38 @@
<OptionGroup v-if="isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
:title="
item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')
"
icon="share"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -30,7 +44,11 @@
<OptionGroup v-if="!hasFile">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -48,7 +66,11 @@
<OptionGroup v-if="isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -57,7 +79,15 @@
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$shareFileOrFolder(item)" :title="item && item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option
@click.native="$shareFileOrFolder(item)"
:title="
item && item.data.relationships.shared
? $t('context_menu.share_edit')
: $t('context_menu.share')
"
icon="share"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
@@ -86,7 +116,12 @@
<FileBrowser />
<MobileMultiSelectToolbar>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
<ToolbarButton @click.native="$shareCancel" class="action-btn" source="shared-off" />
</MobileMultiSelectToolbar>
</div>
+57 -12
View File
@@ -3,17 +3,35 @@
<MobileContextMenu>
<template v-slot:editor>
<OptionGroup>
<Option v-if="item" @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option v-if="item" @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option
v-if="item"
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option
v-if="item"
@click.native="$moveFileOrFolder(item)"
:title="$t('context_menu.move')"
icon="move-item"
/>
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
<template v-slot:visitor>
<OptionGroup>
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
</MobileContextMenu>
@@ -24,13 +42,23 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" :is-hover-disabled="true" />
</OptionGroup>
<OptionGroup>
<Option @click.stop.native="createFolder" :title="$t('actions.create_folder')" icon="folder-plus" :is-hover-disabled="true" />
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
<MobileMultiSelectToolbar>
<template v-slot:visitor>
<ToolbarButton @click.native="$downloadSelection()" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection()"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</template>
<template v-slot:editor>
<ToolbarButton
@@ -47,7 +75,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection()" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection()"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</template>
</MobileMultiSelectToolbar>
@@ -58,19 +91,31 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$createFolder" :title="$t('context_menu.create_folder')" icon="create-folder" />
<Option
@click.native="$createFolder"
:title="$t('context_menu.create_folder')"
icon="create-folder"
/>
</OptionGroup>
</template>
<template v-slot:single-select v-if="item">
<OptionGroup v-if="$checkPermission('editor')">
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -188,7 +233,7 @@ export default {
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
},
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
},
}
</script>
+28 -5
View File
@@ -3,20 +3,30 @@
<ContextMenu>
<template v-slot:single-select v-if="item">
<OptionGroup>
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
:title="
item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')
"
icon="share"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -36,7 +46,15 @@
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
<Option @click.native="$shareFileOrFolder(item)" :title="item && item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option
@click.native="$shareFileOrFolder(item)"
:title="
item && item.data.relationships.shared
? $t('context_menu.share_edit')
: $t('context_menu.share')
"
icon="share"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
@@ -83,7 +101,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</MobileMultiSelectToolbar>
</div>
</template>
+35 -7
View File
@@ -17,13 +17,22 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" :is-hover-disabled="true" />
</OptionGroup>
<OptionGroup :title="$t('Create')">
<Option @click.stop.native="createFolder" :title="$t('actions.create_folder')" icon="folder-plus" :is-hover-disabled="true" />
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
<MobileTeamContextMenu>
<OptionGroup>
<Option @click.native="$detachMeFromTeamFolder(teamFolder)" :title="$t('Leave the Team Folder')" icon="user-minus" />
<Option
@click.native="$detachMeFromTeamFolder(teamFolder)"
:title="$t('Leave the Team Folder')"
icon="user-minus"
/>
</OptionGroup>
</MobileTeamContextMenu>
@@ -44,7 +53,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</MobileMultiSelectToolbar>
<ContextMenu>
@@ -54,19 +68,31 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup v-if="!isTeamFolderHomepage">
<Option @click.stop.native="$createFolder" :title="$t('actions.create_folder')" icon="folder-plus" />
<Option
@click.stop.native="$createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
/>
</OptionGroup>
</template>
<template v-slot:single-select v-if="item">
<OptionGroup v-if="canEdit">
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -182,7 +208,9 @@ export default {
},
canEdit() {
if (this.currentTeamFolder && this.user) {
let member = this.currentTeamFolder.data.relationships.members.data.find((member) => member.data.id === this.user.data.id)
let member = this.currentTeamFolder.data.relationships.members.data.find(
(member) => member.data.id === this.user.data.id
)
return member.data.attributes.permission === 'can-edit'
}
+73 -14
View File
@@ -4,7 +4,11 @@
<OptionGroup v-if="item && isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -15,8 +19,17 @@
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup v-if="item">
<Option @click.native="$shareFileOrFolder(item)" :title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')" icon="share" />
<Option @click.native="$updateTeamFolder(item)" v-if="isFolder" :title="$t('Edit Team Members')" icon="users" />
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
icon="share"
/>
<Option
@click.native="$updateTeamFolder(item)"
v-if="isFolder"
:title="$t('Edit Team Members')"
icon="users"
/>
</OptionGroup>
<OptionGroup v-if="item">
@@ -30,8 +43,18 @@
<OptionUpload :title="$t('actions.upload_folder')" type="folder" :is-hover-disabled="true" />
</OptionGroup>
<OptionGroup :title="$t('Create')">
<Option @click.stop.native="$createTeamFolder" :title="$t('Create Team Folder')" icon="users" :is-hover-disabled="true" />
<Option @click.stop.native="createFolder" :title="$t('actions.create_folder')" icon="folder-plus" :is-hover-disabled="true" />
<Option
@click.stop.native="$createTeamFolder"
:title="$t('Create Team Folder')"
icon="users"
:is-hover-disabled="true"
/>
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
@@ -57,7 +80,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</MobileMultiSelectToolbar>
<ContextMenu>
@@ -65,7 +93,11 @@
<OptionGroup v-if="!isTeamFolderHomepage">
<OptionUpload :title="$t('actions.upload')" type="file" />
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
<Option @click.stop.native="$createFolder" :title="$t('actions.create_folder')" icon="folder-plus" />
<Option
@click.stop.native="$createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
/>
</OptionGroup>
<OptionGroup v-if="isTeamFolderHomepage">
<Option @click.native="$createTeamFolder" :title="$t('Create Team Folder')" icon="users" />
@@ -76,26 +108,45 @@
<OptionGroup v-if="isFolder">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option
@click.native="$shareFileOrFolder(item)"
:title="item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')"
:title="
item.data.relationships.shared ? $t('context_menu.share_edit') : $t('context_menu.share')
"
icon="share"
/>
<Option @click.native="$updateTeamFolder(item)" v-if="isFolder" :title="$t('Edit Team Members')" icon="users" />
<Option
@click.native="$updateTeamFolder(item)"
v-if="isFolder"
:title="$t('Edit Team Members')"
icon="users"
/>
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
@@ -103,7 +154,11 @@
<OptionGroup v-if="!hasFile">
<Option
@click.native="addToFavourites"
:title="isInFavourites ? $t('context_menu.remove_from_favourites') : $t('context_menu.add_to_favourites')"
:title="
isInFavourites
? $t('context_menu.remove_from_favourites')
: $t('context_menu.add_to_favourites')
"
icon="favourites"
/>
</OptionGroup>
@@ -124,7 +179,11 @@
<MobileActionButton @click.native="$showMobileMenu('file-filter')" :icon="$getCurrentSectionIcon()">
{{ $getCurrentSectionName() }}
</MobileActionButton>
<MobileActionButton @click.native="$showMobileMenu('create-list')" v-if="$checkPermission(['master', 'editor'])" icon="cloud-plus">
<MobileActionButton
@click.native="$showMobileMenu('create-list')"
v-if="$checkPermission(['master', 'editor'])"
icon="cloud-plus"
>
{{ $t('mobile.create') }}
</MobileActionButton>
<MobileActionButton @click.native="$enableMultiSelectMode" icon="check-square">
+35 -6
View File
@@ -9,19 +9,38 @@
<template v-slot:single-select v-if="item">
<OptionGroup>
<Option @click.native="$restoreFileOrFolder(item)" v-if="item" :title="$t('context_menu.restore')" icon="restore" />
<Option @click.native="$deleteFileOrFolder(item)" v-if="item" :title="$t('context_menu.delete')" icon="trash" />
<Option
@click.native="$restoreFileOrFolder(item)"
v-if="item"
:title="$t('context_menu.restore')"
icon="restore"
/>
<Option
@click.native="$deleteFileOrFolder(item)"
v-if="item"
:title="$t('context_menu.delete')"
icon="trash"
/>
<Option @click.native="$emptyTrash" :title="$t('context_menu.empty_trash')" icon="empty-trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
<Option @click.native="$downloadSelection(item)" :title="$t('context_menu.download')" icon="download" />
<Option
@click.native="$downloadSelection(item)"
:title="$t('context_menu.download')"
icon="download"
/>
</OptionGroup>
</template>
<template v-slot:multiple-select v-if="item">
<OptionGroup>
<Option @click.native="$restoreFileOrFolder(item)" v-if="item" :title="$t('context_menu.restore')" icon="restore" />
<Option
@click.native="$restoreFileOrFolder(item)"
v-if="item"
:title="$t('context_menu.restore')"
icon="restore"
/>
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
<Option @click.native="$emptyTrash" :title="$t('context_menu.empty_trash')" icon="empty-trash" />
</OptionGroup>
@@ -33,7 +52,12 @@
<MobileContextMenu>
<OptionGroup v-if="item">
<Option @click.native="$restoreFileOrFolder(item)" v-if="item" :title="$t('context_menu.restore')" icon="restore" />
<Option
@click.native="$restoreFileOrFolder(item)"
v-if="item"
:title="$t('context_menu.restore')"
icon="restore"
/>
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
@@ -74,7 +98,12 @@
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
<ToolbarButton @click.native="$downloadSelection(item)" class="action-btn" source="download" :action="$t('actions.download')" />
<ToolbarButton
@click.native="$downloadSelection(item)"
class="action-btn"
source="download"
:action="$t('actions.download')"
/>
</MobileMultiSelectToolbar>
</div>
</template>
@@ -0,0 +1,198 @@
<template>
<div>
<MobileContextMenu>
<OptionGroup v-if="item">
<Option @click.native="$renameFileOrFolder(item)" :title="$t('context_menu.rename')" icon="rename" />
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
</MobileContextMenu>
<MobileCreateMenu>
<OptionGroup :title="$t('Upload')">
<OptionUpload :title="$t('actions.upload')" type="file" :is-hover-disabled="true" />
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup :title="$t('Create')">
<Option
@click.stop.native="createFolder"
:title="$t('actions.create_folder')"
icon="folder-plus"
:is-hover-disabled="true"
/>
</OptionGroup>
</MobileCreateMenu>
<MobileMultiSelectToolbar>
<ToolbarButton
@click.native="$moveFileOrFolder(clipboard)"
class="action-btn"
source="move"
:action="$t('actions.move')"
:class="{ 'is-inactive': clipboard.length < 1 }"
/>
<ToolbarButton
@click.native="$deleteFileOrFolder(clipboard)"
class="action-btn"
source="trash"
:class="{ 'is-inactive': clipboard.length < 1 }"
:action="$t('actions.delete')"
/>
</MobileMultiSelectToolbar>
<ContextMenu>
<template v-slot:empty-select>
<OptionGroup>
<OptionUpload :title="$t('actions.upload')" type="file" />
<OptionUpload :title="$t('actions.upload_folder')" type="folder" />
</OptionGroup>
<OptionGroup>
<Option
@click.native="$createFolder"
:title="$t('context_menu.create_folder')"
icon="create-folder"
/>
</OptionGroup>
</template>
<template v-slot:single-select v-if="item">
<OptionGroup>
<Option
@click.native="$renameFileOrFolder(item)"
:title="$t('context_menu.rename')"
icon="rename"
/>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$openInDetailPanel(item)" :title="$t('context_menu.detail')" icon="detail" />
</OptionGroup>
</template>
<template v-slot:multiple-select v-if="item">
<OptionGroup>
<Option @click.native="$moveFileOrFolder(item)" :title="$t('context_menu.move')" icon="move-item" />
<Option @click.native="$deleteFileOrFolder(item)" :title="$t('context_menu.delete')" icon="trash" />
</OptionGroup>
<OptionGroup>
<Option @click.native="$downloadSelection()" :title="$t('context_menu.download')" icon="download" />
</OptionGroup>
</template>
</ContextMenu>
<FileActionsMobile v-if="entries.length">
<MobileActionButton @click.native="$openSpotlight()" icon="search">
{{ $t('Spotlight') }}
</MobileActionButton>
<MobileActionButton
@click.native="$showMobileMenu('create-list')"
v-if="$checkPermission(['master', 'editor'])"
icon="cloud-plus"
>
{{ $t('mobile.create') }}
</MobileActionButton>
<MobileActionButton @click.native="$enableMultiSelectMode" icon="check-square">
{{ $t('context_menu.select') }}
</MobileActionButton>
<MobileActionButton @click.native="$showMobileMenu('file-sorting')" icon="preview-sorting">
{{ $t('preview_sorting.preview_sorting_button') }}
</MobileActionButton>
</FileActionsMobile>
<EmptyFilePage>
<div v-if="uploadRequest" class="relative mx-auto mb-8 w-24 text-center">
<VueFolderIcon class="inline-block w-28" />
<MemberAvatar
:member="uploadRequest.user"
class="absolute -bottom-2.5 -right-2"
:is-border="true"
:size="32"
/>
</div>
<h1 class="title">
{{ $t('Jane Request You for File Upload') }}
</h1>
<p class="description max-w-[420px]">
{{
$t(
'Your files will be uploaded automatically and after that, you can organize your files in folders.'
)
}}
</p>
<ButtonUpload button-style="theme">
{{ $t('empty_page.call_to_action') }}
</ButtonUpload>
</EmptyFilePage>
<FileBrowser />
</div>
</template>
<script>
import MobileMultiSelectToolbar from '../../components/FilesView/MobileMultiSelectToolbar'
import MobileActionButton from '../../components/FilesView/MobileActionButton'
import FileActionsMobile from '../../components/FilesView/FileActionsMobile'
import MobileContextMenu from '../../components/FilesView/MobileContextMenu'
import VueFolderIcon from '../../components/FilesView/Icons/VueFolderIcon'
import MobileCreateMenu from '../../components/FilesView/MobileCreateMenu'
import EmptyFilePage from '../../components/FilesView/EmptyFilePage'
import ToolbarButton from '../../components/FilesView/ToolbarButton'
import MemberAvatar from '../../components/FilesView/MemberAvatar'
import ButtonUpload from '../../components/FilesView/ButtonUpload'
import OptionUpload from '../../components/FilesView/OptionUpload'
import FileBrowser from '../../components/FilesView/FileBrowser'
import ContextMenu from '../../components/FilesView/ContextMenu'
import OptionGroup from '../../components/FilesView/OptionGroup'
import Option from '../../components/FilesView/Option'
import { events } from '../../bus'
import { mapGetters } from 'vuex'
export default {
name: 'Files',
components: {
MobileMultiSelectToolbar,
MobileActionButton,
FileActionsMobile,
MobileContextMenu,
MobileCreateMenu,
EmptyFilePage,
VueFolderIcon,
ToolbarButton,
MemberAvatar,
ButtonUpload,
OptionUpload,
OptionGroup,
FileBrowser,
ContextMenu,
Option,
},
computed: {
...mapGetters(['fastPreview', 'clipboard', 'config', 'user', 'entries', 'uploadRequest']),
isFolder() {
return this.item && this.item.data.type === 'folder'
},
},
data() {
return {
item: undefined,
}
},
methods: {
createFolder() {
events.$emit('popup:open', { name: 'create-folder' })
},
},
created() {
//this.$store.dispatch('getFolder', this.$route.params.id)
this.$store.commit('LOADING_STATE', { loading: false, data: [] })
axios.get('/api/request').then((response) => this.$store.commit('SET_UPLOAD_REQUEST', response.data))
events.$on('context-menu:show', (event, item) => (this.item = item))
events.$on('context-menu:current-folder', (folder) => (this.item = folder))
events.$on('mobile-context-menu:show', (item) => (this.item = item))
},
}
</script>
+20 -3
View File
@@ -6,9 +6,20 @@
<!--Page content-->
<div class="page-wrapper small">
<!--Headline-->
<PageTitle class="headline" :title="$t('page_contact_us.title')" :description="$t('page_contact_us.description')"></PageTitle>
<PageTitle
class="headline"
:title="$t('page_contact_us.title')"
:description="$t('page_contact_us.description')"
></PageTitle>
<ValidationObserver v-if="!isSuccess" @submit.prevent="contactForm" ref="contactForm" v-slot="{ invalid }" tag="form" class="form block-form">
<ValidationObserver
v-if="!isSuccess"
@submit.prevent="contactForm"
ref="contactForm"
v-slot="{ invalid }"
tag="form"
class="form block-form"
>
<div class="block-wrapper">
<label>{{ $t('page_contact_us.form.email') }}:</label>
<ValidationProvider tag="div" mode="passive" name="E-Mail" rules="required" v-slot="{ errors }">
@@ -42,7 +53,13 @@
</InfoBox>
<div>
<AuthButton class="submit-button" icon="chevron-right" :text="$t('page_contact_us.form.submit_button')" :loading="isLoading" :disabled="isLoading" />
<AuthButton
class="submit-button"
icon="chevron-right"
:text="$t('page_contact_us.form.submit_button')"
:loading="isLoading"
:disabled="isLoading"
/>
</div>
</ValidationObserver>
<InfoBox v-if="isSuccess">
+2 -2
View File
@@ -10,8 +10,8 @@
<!--VueFileManager ScreenShot-->
<HeroScreenshot />
<!--Google Adsense banner-->
<div v-if="config.allowedAdsense" v-html="config.adsenseBanner01" class="min-h-[120px] mb-5"></div>
<!--Google Adsense banner-->
<div v-if="config.allowedAdsense" v-html="config.adsenseBanner01" class="mb-5 min-h-[120px]"></div>
<!--Main Features-->
<MainFeatures />
+1 -1
View File
@@ -41,7 +41,7 @@
<MobileToolbar />
<!--Google Adsense banner-->
<div v-if="config.allowedAdsense" v-html="config.adsenseBanner01" class="min-h-[120px] mb-5"></div>
<div v-if="config.allowedAdsense" v-html="config.adsenseBanner01" class="mb-5 min-h-[120px]"></div>
<!--File list & info sidebar-->
<div class="flex space-x-3 lg:overflow-hidden">
+8 -2
View File
@@ -26,13 +26,19 @@
<MobileNavigationToolbar />
<div v-if="user" class="relative mx-auto w-full overflow-x-hidden px-2.5 pb-12 md:max-w-4xl md:px-6 lg:pt-6 lg:pb-0 xl:max-w-screen-lg">
<div
v-if="user"
class="relative mx-auto w-full overflow-x-hidden px-2.5 pb-12 md:max-w-4xl md:px-6 lg:pt-6 lg:pb-0 xl:max-w-screen-lg"
>
<div v-if="!isLoading" id="page-content">
<div class="card sticky top-0 z-10 shadow-card" style="padding-bottom: 0">
<!--User thumbnail-->
<div class="mb-3 flex items-center">
<!--Image input for replace avatar-->
<AvatarInput v-model="avatar" :avatar="user.data.relationships.settings.data.attributes.avatar.md" />
<AvatarInput
v-model="avatar"
:avatar="user.data.relationships.settings.data.attributes.avatar.md"
/>
<!--User name & email-->
<div class="ml-4">
+7 -8
View File
@@ -3,13 +3,12 @@
</template>
<script>
export default {
name: 'SetupWizard',
mounted() {
let status = this.$root.$data.config.installation
export default {
name: 'SetupWizard',
mounted() {
let status = this.$root.$data.config.installation
if (status && status === 'installation-done')
this.$router.push({ name: 'SignIn' })
},
}
if (status && status === 'installation-done') this.$router.push({ name: 'SignIn' })
},
}
</script>
+102 -50
View File
@@ -1,54 +1,108 @@
<template>
<AuthContentWrapper ref="auth">
<!--Database Credentials-->
<AuthContent name="database-credentials" :visible="true" class="!max-w-2xl mt-6 mb-12">
<Headline class="mx-auto max-w-screen-sm !mb-10" title="Setup Wizard" description="Create your admin account.">
<settings-icon size="40" class="vue-feather text-theme mx-auto animate-[spin_5s_linear_infinite] mb-3" />
<AuthContent name="database-credentials" :visible="true" class="mt-6 mb-12 !max-w-2xl">
<Headline
class="mx-auto !mb-10 max-w-screen-sm"
title="Setup Wizard"
description="Create your admin account."
>
<settings-icon
size="40"
class="vue-feather text-theme mx-auto mb-3 animate-[spin_5s_linear_infinite]"
/>
</Headline>
<ValidationObserver @submit.prevent="adminAccountSubmit" ref="adminAccount" v-slot="{ invalid }" tag="form" class="card shadow-card text-left">
<FormLabel>
Create Admin Account
</FormLabel>
<ValidationObserver
@submit.prevent="adminAccountSubmit"
ref="adminAccount"
v-slot="{ invalid }"
tag="form"
class="card text-left shadow-card"
>
<FormLabel> Create Admin Account </FormLabel>
<ValidationProvider tag="div" mode="passive" name="Avatar" v-slot="{ errors }">
<AppInputText title="Avatar (optional)" :error="errors[0]">
<ValidationProvider tag="div" mode="passive" name="Avatar" v-slot="{ errors }">
<AppInputText title="Avatar (optional)" :error="errors[0]">
<ImageInput v-model="admin.avatar" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Full Name" rules="required" v-slot="{ errors }">
<AppInputText title="Full Name" :error="errors[0]">
<input v-model="admin.name" class="focus-border-theme input-dark" placeholder="Type your full name" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Full Name" rules="required" v-slot="{ errors }">
<AppInputText title="Full Name" :error="errors[0]">
<input
v-model="admin.name"
class="focus-border-theme input-dark"
placeholder="Type your full name"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Email" rules="required" v-slot="{ errors }">
<AppInputText title="Email" :error="errors[0]">
<input v-model="admin.email" class="focus-border-theme input-dark" placeholder="Type your email" type="email" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Email" rules="required" v-slot="{ errors }">
<AppInputText title="Email" :error="errors[0]">
<input
v-model="admin.email"
class="focus-border-theme input-dark"
placeholder="Type your email"
type="email"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Password" rules="required|confirmed:confirmation" v-slot="{ errors }">
<AppInputText title="Password" :error="errors[0]">
<input v-model="admin.password" class="focus-border-theme input-dark" placeholder="Type your password" type="password" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
mode="passive"
name="Password"
rules="required|confirmed:confirmation"
v-slot="{ errors }"
>
<AppInputText title="Password" :error="errors[0]">
<input
v-model="admin.password"
class="focus-border-theme input-dark"
placeholder="Type your password"
type="password"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" name="confirmation" rules="required" vid="confirmation" v-slot="{ errors }">
<AppInputText title="Password Confirmation" :error="errors[0]" :is-last="true">
<input v-model="admin.password_confirmation" class="focus-border-theme input-dark" placeholder="Confirm your password" type="password" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
name="confirmation"
rules="required"
vid="confirmation"
v-slot="{ errors }"
>
<AppInputText title="Password Confirmation" :error="errors[0]" :is-last="true">
<input
v-model="admin.password_confirmation"
class="focus-border-theme input-dark"
placeholder="Confirm your password"
type="password"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
</ValidationObserver>
<AuthButton @click.native="adminAccountSubmit" class="w-full justify-center" icon="chevron-right" text="Create Admin and Login" :loading="isLoading" :disabled="isLoading" />
<AuthButton
@click.native="adminAccountSubmit"
class="w-full justify-center"
icon="chevron-right"
text="Create Admin and Login"
:loading="isLoading"
:disabled="isLoading"
/>
</AuthContent>
</AuthContentWrapper>
</template>
<script>
import AppInputText from "../../components/Admin/AppInputText";
import AppInputText from '../../components/Admin/AppInputText'
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import AuthContentWrapper from '../../components/Auth/AuthContentWrapper'
import SelectInput from '../../components/Others/Forms/SelectInput'
@@ -60,7 +114,7 @@ import AuthContent from '../../components/Auth/AuthContent'
import AuthButton from '../../components/Auth/AuthButton'
import { required } from 'vee-validate/dist/rules'
import { SettingsIcon } from 'vue-feather-icons'
import Headline from "../Auth/Headline"
import Headline from '../Auth/Headline'
import { events } from '../../bus'
import axios from 'axios'
@@ -70,7 +124,7 @@ export default {
AuthContentWrapper,
ValidationProvider,
ValidationObserver,
AppInputText,
AppInputText,
SettingsIcon,
SelectInput,
SwitchInput,
@@ -79,7 +133,7 @@ export default {
AuthButton,
FormLabel,
required,
Headline,
Headline,
InfoBox,
},
data() {
@@ -125,12 +179,10 @@ export default {
},
})
.then((response) => {
// Go to sign page
window.location = '/sign-in'
window.location = '/sign-in'
})
.catch((error) => {
if (error.response.status === 500) {
events.$emit('alert:open', {
emoji: '🤔',
@@ -152,22 +204,22 @@ export default {
})
}
}
}).finally(() => this.isLoading = false)
})
.finally(() => (this.isLoading = false))
},
},
created() {
this.$scrollTop()
if (this.$root.$data.config.isSetupWizardDebug) {
this.admin = {
name: 'Jane Doe',
email: 'howdy@hi5ve.digital',
avatar: undefined,
password: 'vuefilemanager',
password_confirmation: 'vuefilemanager',
}
}
if (this.$root.$data.config.isSetupWizardDebug) {
this.admin = {
name: 'Jane Doe',
email: 'howdy@hi5ve.digital',
avatar: undefined,
password: 'vuefilemanager',
password_confirmation: 'vuefilemanager',
}
}
},
}
</script>
+217 -133
View File
@@ -1,126 +1,217 @@
<template>
<AuthContentWrapper ref="auth">
<!--Database Credentials-->
<AuthContent name="database-credentials" :visible="true" class="!max-w-2xl mt-6 mb-12">
<Headline class="mx-auto max-w-screen-sm !mb-10" title="Setup Wizard" description="Set up your application appearance, analytics, etc.">
<settings-icon size="40" class="vue-feather text-theme mx-auto animate-[spin_5s_linear_infinite] mb-3" />
<AuthContent name="database-credentials" :visible="true" class="mt-6 mb-12 !max-w-2xl">
<Headline
class="mx-auto !mb-10 max-w-screen-sm"
title="Setup Wizard"
description="Set up your application appearance, analytics, etc."
>
<settings-icon
size="40"
class="vue-feather text-theme mx-auto mb-3 animate-[spin_5s_linear_infinite]"
/>
</Headline>
<ValidationObserver @submit.prevent="appSetupSubmit" ref="appSetup" v-slot="{ invalid }" tag="form">
<div class="card text-left shadow-card">
<FormLabel>General Settings</FormLabel>
<div class="card shadow-card text-left">
<FormLabel>General Settings</FormLabel>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<AppInputText title="App Title" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="app.title"
placeholder="Type your app title"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Title" rules="required" v-slot="{ errors }">
<AppInputText title="App Title" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="app.title" placeholder="Type your app title" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
mode="passive"
name="App Description"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="App Description" :error="errors[0]" :is-last="true">
<textarea
class="focus-border-theme input-dark"
v-model="app.description"
placeholder="Type your app description"
type="text"
:class="{ 'border-red': errors[0] }"
></textarea>
</AppInputText>
</ValidationProvider>
</div>
<ValidationProvider tag="div" mode="passive" name="App Description" rules="required" v-slot="{ errors }">
<AppInputText title="App Description" :error="errors[0]" :is-last="true">
<textarea class="focus-border-theme input-dark" v-model="app.description" placeholder="Type your app description" type="text" :class="{ 'border-red': errors[0] }"></textarea>
</AppInputText>
</ValidationProvider>
</div>
<div class="card text-left shadow-card">
<FormLabel>Appearance</FormLabel>
<div class="card shadow-card text-left">
<FormLabel>Appearance</FormLabel>
<ValidationProvider tag="div" mode="passive" name="Theme Color" v-slot="{ errors }">
<AppInputSwitch title="Color Theme">
<input v-model="app.color" type="color" />
</AppInputSwitch>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Theme Color" v-slot="{ errors }">
<AppInputSwitch title="Color Theme">
<input v-model="app.color" type="color" />
</AppInputSwitch>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Logo" v-slot="{ errors }">
<AppInputText title="App Logo (optional)" :error="errors[0]">
<ImageInput v-model="app.logo" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Logo" v-slot="{ errors }">
<AppInputText title="App Logo (optional)" :error="errors[0]">
<ImageInput v-model="app.logo" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Logo" v-slot="{ errors }">
<AppInputText title="App Logo Horizontal (optional)" :error="errors[0]">
<ImageInput v-model="app.logo_horizontal" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Logo" v-slot="{ errors }">
<AppInputText title="App Logo Horizontal (optional)" :error="errors[0]">
<ImageInput v-model="app.logo_horizontal" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText title="App Favicon (optional)" :error="errors[0]">
<ImageInput v-model="app.favicon" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText title="App Favicon (optional)" :error="errors[0]">
<ImageInput v-model="app.favicon" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText
title="OG Image (optional)"
description="Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627"
:error="errors[0]"
>
<ImageInput v-model="app.og_image" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText title="OG Image (optional)" description="Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627" :error="errors[0]">
<ImageInput v-model="app.og_image" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText
title="App Touch Icon (optional)"
description="If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156"
:error="errors[0]"
:is-last="true"
>
<ImageInput v-model="app.touch_icon" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
</div>
<ValidationProvider tag="div" mode="passive" name="App Favicon" v-slot="{ errors }">
<AppInputText title="App Touch Icon (optional)" description="If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156" :error="errors[0]" :is-last="true">
<ImageInput v-model="app.touch_icon" :error="errors[0]" />
</AppInputText>
</ValidationProvider>
</div>
<div class="card text-left shadow-card">
<FormLabel>Application</FormLabel>
<div class="card shadow-card text-left">
<FormLabel>Application</FormLabel>
<ValidationProvider
tag="div"
mode="passive"
name="Contact Email"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="Contact Email" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="app.contactMail"
placeholder="Type your contact email"
type="email"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Contact Email" rules="required" v-slot="{ errors }">
<AppInputText title="Contact Email" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="app.contactMail" placeholder="Type your contact email" type="email" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Google Analytics Code" v-slot="{ errors }">
<AppInputText title="Google Analytics Code (optional)" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="app.googleAnalytics"
placeholder="Paste your Google Analytics Code"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Google Analytics Code" v-slot="{ errors }">
<AppInputText title="Google Analytics Code (optional)" :error="errors[0]">
<input class="focus-border-theme input-dark" v-model="app.googleAnalytics" placeholder="Paste your Google Analytics Code" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<AppInputSwitch
title="Storage Limitation"
description="If this value is off, all users will have infinity storage capacity and you won't be able to charge your users for storage plan."
>
<SwitchInput v-model="app.storageLimitation" :state="app.storageLimitation" />
</AppInputSwitch>
<AppInputSwitch title="Storage Limitation" description="If this value is off, all users will have infinity storage capacity and you won't be able to charge your users for storage plan.">
<SwitchInput v-model="app.storageLimitation" :state="app.storageLimitation" />
</AppInputSwitch>
<ValidationProvider
tag="div"
mode="passive"
name="Default Storage Space"
rules="required"
v-slot="{ errors }"
>
<AppInputText
v-if="app.storageLimitation"
title="Default Storage Space for Accounts"
:error="errors[0]"
>
<input
class="focus-border-theme input-dark"
v-model="app.defaultStorage"
min="1"
max="999999999"
placeholder="Set default storage space in GB"
type="number"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Default Storage Space" rules="required" v-slot="{ errors }">
<AppInputText v-if="app.storageLimitation" title="Default Storage Space for Accounts" :error="errors[0]">
<input
class="focus-border-theme input-dark"
v-model="app.defaultStorage"
min="1"
max="999999999"
placeholder="Set default storage space in GB"
type="number"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<AppInputSwitch
title="Allow User Registration"
description="You can disable public registration for new users. You will still able to create new users in administration panel."
>
<SwitchInput v-model="app.userRegistration" class="switch" :state="app.userRegistration" />
</AppInputSwitch>
<AppInputSwitch title="Allow User Registration" description="You can disable public registration for new users. You will still able to create new users in administration panel.">
<SwitchInput v-model="app.userRegistration" class="switch" :state="app.userRegistration" />
</AppInputSwitch>
<AppInputSwitch
title="Require Email Verification"
description="Turn on, if you want to allow user email verification."
:is-last="true"
>
<SwitchInput v-model="app.userVerification" class="switch" :state="app.userVerification" />
</AppInputSwitch>
</div>
<AppInputSwitch title="Require Email Verification" description="Turn on, if you want to allow user email verification." :is-last="true">
<SwitchInput v-model="app.userVerification" class="switch" :state="app.userVerification" />
</AppInputSwitch>
</div>
<div v-if="isExtended" class="card text-left shadow-card">
<FormLabel>Subscription</FormLabel>
<div v-if="isExtended" class="card shadow-card text-left">
<FormLabel>Subscription</FormLabel>
<ValidationProvider
tag="div"
mode="passive"
name="Contact Email"
rules="required"
v-slot="{ errors }"
>
<AppInputText
:title="$t('Subscription Type')"
description="Choose your preferred subscription system in advance. After installation and any other user registration, you can't change this setting later."
>
<SelectInput
v-model="app.subscriptionType"
:default="app.subscriptionType"
:options="$store.getters.subscriptionTypes"
:placeholder="$t('Select your subscription type')"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Contact Email" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Subscription Type')" description="Choose your preferred subscription system in advance. After installation and any other user registration, you can't change this setting later.">
<SelectInput v-model="app.subscriptionType" :default="app.subscriptionType" :options="$store.getters.subscriptionTypes" :placeholder="$t('Select your subscription type')" />
</AppInputText>
</ValidationProvider>
<InfoBox class="!mb-2">
<p>Any other subscription related settings you will be able set up later in admin panel.</p>
</InfoBox>
</div>
<InfoBox class="!mb-2">
<p>Any other subscription related settings you will be able set up later in admin panel.</p>
</InfoBox>
</div>
<AuthButton class="w-full justify-center" icon="chevron-right" text="Save and Create Admin" :loading="isLoading" :disabled="isLoading" />
<AuthButton
class="w-full justify-center"
icon="chevron-right"
text="Save and Create Admin"
:loading="isLoading"
:disabled="isLoading"
/>
</ValidationObserver>
</AuthContent>
</AuthContentWrapper>
@@ -131,10 +222,10 @@ import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-va
import AuthContentWrapper from '../../components/Auth/AuthContentWrapper'
import SelectInput from '../../components/Others/Forms/SelectInput'
import SwitchInput from '../../components/Others/Forms/SwitchInput'
import AppInputSwitch from "../../components/Admin/AppInputSwitch"
import AppInputSwitch from '../../components/Admin/AppInputSwitch'
import ImageInput from '../../components/Others/Forms/ImageInput'
import FormLabel from '../../components/Others/Forms/FormLabel'
import AppInputText from "../../components/Admin/AppInputText"
import AppInputText from '../../components/Admin/AppInputText'
import InfoBox from '../../components/Others/Forms/InfoBox'
import AuthContent from '../../components/Auth/AuthContent'
import AuthButton from '../../components/Auth/AuthButton'
@@ -146,8 +237,8 @@ import axios from 'axios'
export default {
name: 'EnvironmentSetup',
components: {
AppInputText,
AppInputSwitch,
AppInputText,
AppInputSwitch,
AuthContentWrapper,
ValidationProvider,
ValidationObserver,
@@ -165,10 +256,10 @@ export default {
data() {
return {
isLoading: false,
isExtended: undefined,
isExtended: undefined,
app: {
color: '#00BC7E',
subscriptionType: undefined,
subscriptionType: undefined,
title: '',
description: '',
logo: undefined,
@@ -181,15 +272,15 @@ export default {
defaultStorage: '5',
userRegistration: 1,
storageLimitation: 1,
userVerification: 0,
userVerification: 0,
},
}
},
methods: {
async appSetupSubmit() {
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({name: 'AdminAccount'})
}
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({ name: 'AdminAccount' })
}
// Validate fields
const isValid = await this.$refs.appSetup.validate()
@@ -212,26 +303,19 @@ export default {
formData.append('userRegistration', Boolean(this.app.userRegistration) ? 1 : 0)
formData.append('storageLimitation', Boolean(this.app.storageLimitation) ? 1 : 0)
if (this.app.googleAnalytics)
formData.append('googleAnalytics', this.app.googleAnalytics)
if (this.app.googleAnalytics) formData.append('googleAnalytics', this.app.googleAnalytics)
if (this.app.defaultStorage)
formData.append('defaultStorage', this.app.defaultStorage)
if (this.app.defaultStorage) formData.append('defaultStorage', this.app.defaultStorage)
if (this.app.logo)
formData.append('logo', this.app.logo)
if (this.app.logo) formData.append('logo', this.app.logo)
if (this.app.logo_horizontal)
formData.append('logo_horizontal', this.app.logo_horizontal)
if (this.app.logo_horizontal) formData.append('logo_horizontal', this.app.logo_horizontal)
if (this.app.og_image)
formData.append('og_image', this.app.og_image)
if (this.app.og_image) formData.append('og_image', this.app.og_image)
if (this.app.touch_icon)
formData.append('touch_icon', this.app.touch_icon)
if (this.app.touch_icon) formData.append('touch_icon', this.app.touch_icon)
if (this.app.favicon)
formData.append('favicon', this.app.favicon)
if (this.app.favicon) formData.append('favicon', this.app.favicon)
// Send request to get verify account
axios
@@ -256,19 +340,19 @@ export default {
created() {
this.$scrollTop()
this.isExtended = localStorage.getItem('license') === 'Extended'
this.isExtended = localStorage.getItem('license') === 'Extended'
if (this.$root.$data.config.isSetupWizardDebug) {
this.app.subscriptionType = 'metered'
this.app.title = 'VueFileManager'
this.app.description = 'Your private cloud storage software build on Laravel & Vue.js.'
this.app.contactMail = 'howdy@hi5ve.digital'
this.app.googleAnalytics = 'UA-123456789'
this.app.defaultStorage = '5'
this.app.userRegistration = 1
this.app.storageLimitation = 1
this.app.userVerification = 0
}
if (this.$root.$data.config.isSetupWizardDebug) {
this.app.subscriptionType = 'metered'
this.app.title = 'VueFileManager'
this.app.description = 'Your private cloud storage software build on Laravel & Vue.js.'
this.app.contactMail = 'howdy@hi5ve.digital'
this.app.googleAnalytics = 'UA-123456789'
this.app.defaultStorage = '5'
this.app.userRegistration = 1
this.app.storageLimitation = 1
this.app.userVerification = 0
}
},
}
</script>
+130 -65
View File
@@ -1,79 +1,144 @@
<template>
<AuthContentWrapper ref="auth">
<!--Database Credentials-->
<AuthContent name="database-credentials" :visible="true" class="!max-w-2xl mt-6 mb-12">
<Headline class="mx-auto max-w-screen-sm !mb-10" title="Setup Wizard" description="Set up your database connection to install application database.">
<settings-icon size="40" class="vue-feather text-theme mx-auto animate-[spin_5s_linear_infinite] mb-3" />
<AuthContent name="database-credentials" :visible="true" class="mt-6 mb-12 !max-w-2xl">
<Headline
class="mx-auto !mb-10 max-w-screen-sm"
title="Setup Wizard"
description="Set up your database connection to install application database."
>
<settings-icon
size="40"
class="vue-feather text-theme mx-auto mb-3 animate-[spin_5s_linear_infinite]"
/>
</Headline>
<ValidationObserver @submit.prevent="databaseCredentialsSubmit" ref="verifyPurchaseCode" v-slot="{ invalid }" tag="form" class="card shadow-card text-left">
<FormLabel>
Database Credentials
</FormLabel>
<ValidationObserver
@submit.prevent="databaseCredentialsSubmit"
ref="verifyPurchaseCode"
v-slot="{ invalid }"
tag="form"
class="card text-left shadow-card"
>
<FormLabel> Database Credentials </FormLabel>
<InfoBox>
<p>
We strongly recommend use MySQL or MariaDB database. Create new database, set all privileges and get credentials. For those who use cPanel or Plesk, here is
useful resources:
We strongly recommend use MySQL or MariaDB database. Create new database, set all privileges and
get credentials. For those who use cPanel or Plesk, here is useful resources:
</p>
<ul>
<li>
<a href="https://www.inmotionhosting.com/support/edu/cpanel/create-database-2/" target="_blank">1. cPanel - MySQL Database Wizard</a>
<a href="https://docs.plesk.com/en-US/obsidian/customer-guide/65157/" target="_blank">2. Plesk - Website databases</a>
<a
href="https://www.inmotionhosting.com/support/edu/cpanel/create-database-2/"
target="_blank"
>1. cPanel - MySQL Database Wizard</a
>
<a href="https://docs.plesk.com/en-US/obsidian/customer-guide/65157/" target="_blank"
>2. Plesk - Website databases</a
>
</li>
</ul>
</InfoBox>
<ValidationProvider tag="div" mode="passive" name="Connection" rules="required" v-slot="{ errors }">
<AppInputText title="Connection" :error="errors[0]">
<SelectInput
v-model="databaseCredentials.connection"
:options="connectionList"
default="mysql"
placeholder="Select your database connection"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Connection" rules="required" v-slot="{ errors }">
<AppInputText title="Connection" :error="errors[0]">
<SelectInput
v-model="databaseCredentials.connection"
:options="connectionList"
default="mysql"
placeholder="Select your database connection"
:isError="errors[0]"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Host" rules="required" v-slot="{ errors }">
<AppInputText title="Host" :error="errors[0]">
<input v-model="databaseCredentials.host" class="focus-border-theme input-dark" placeholder="Type your database host" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Host" rules="required" v-slot="{ errors }">
<AppInputText title="Host" :error="errors[0]">
<input
v-model="databaseCredentials.host"
class="focus-border-theme input-dark"
placeholder="Type your database host"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Port" rules="required" v-slot="{ errors }">
<AppInputText title="Port" :error="errors[0]">
<input v-model="databaseCredentials.port" class="focus-border-theme input-dark" placeholder="Type your database port" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Port" rules="required" v-slot="{ errors }">
<AppInputText title="Port" :error="errors[0]">
<input
v-model="databaseCredentials.port"
class="focus-border-theme input-dark"
placeholder="Type your database port"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Database Name" rules="required" v-slot="{ errors }">
<AppInputText title="Database Name" :error="errors[0]">
<input v-model="databaseCredentials.name" class="focus-border-theme input-dark" placeholder="Select your database name" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Database Name" rules="required" v-slot="{ errors }">
<AppInputText title="Database Name" :error="errors[0]">
<input
v-model="databaseCredentials.name"
class="focus-border-theme input-dark"
placeholder="Select your database name"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Database Username" rules="required" v-slot="{ errors }">
<AppInputText title="Database Username" :error="errors[0]">
<input v-model="databaseCredentials.username" class="focus-border-theme input-dark" placeholder="Select your database name" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
mode="passive"
name="Database Username"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="Database Username" :error="errors[0]">
<input
v-model="databaseCredentials.username"
class="focus-border-theme input-dark"
placeholder="Select your database name"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Database Password" rules="required" v-slot="{ errors }">
<AppInputText title="Database Password" :error="errors[0]" :is-last="true">
<input v-model="databaseCredentials.password" class="focus-border-theme input-dark" placeholder="Select your database password" type="text" :class="{ 'border-red': errors[0] }" />
</AppInputText>
</ValidationProvider>
<ValidationProvider
tag="div"
mode="passive"
name="Database Password"
rules="required"
v-slot="{ errors }"
>
<AppInputText title="Database Password" :error="errors[0]" :is-last="true">
<input
v-model="databaseCredentials.password"
class="focus-border-theme input-dark"
placeholder="Select your database password"
type="text"
:class="{ 'border-red': errors[0] }"
/>
</AppInputText>
</ValidationProvider>
<InfoBox v-if="isError" type="error" style="margin-bottom: 10px">
<p>We couldn't establish database connection. Please double check your database credentials.</p>
<br />
<p>Detailed error: {{ errorMessage }}</p>
</InfoBox>
</ValidationObserver>
<AuthButton @click.native="databaseCredentialsSubmit" class="w-full justify-center" icon="chevron-right" :text="submitButtonText" :loading="isLoading" :disabled="isLoading" />
<AuthButton
@click.native="databaseCredentialsSubmit"
class="w-full justify-center"
icon="chevron-right"
:text="submitButtonText"
:loading="isLoading"
:disabled="isLoading"
/>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -82,7 +147,7 @@
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import AuthContentWrapper from '../../components/Auth/AuthContentWrapper'
import SelectInput from '../../components/Others/Forms/SelectInput'
import AppInputText from "../../components/Admin/AppInputText"
import AppInputText from '../../components/Admin/AppInputText'
import FormLabel from '../../components/Others/Forms/FormLabel'
import InfoBox from '../../components/Others/Forms/InfoBox'
import AuthContent from '../../components/Auth/AuthContent'
@@ -99,7 +164,7 @@ export default {
AuthContentWrapper,
ValidationProvider,
ValidationObserver,
AppInputText,
AppInputText,
SettingsIcon,
SelectInput,
AuthContent,
@@ -137,10 +202,10 @@ export default {
},
methods: {
async databaseCredentialsSubmit() {
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({name: 'EnvironmentSetup'})
return
}
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({ name: 'EnvironmentSetup' })
return
}
// Validate fields
const isValid = await this.$refs.verifyPurchaseCode.validate()
@@ -175,16 +240,16 @@ export default {
created() {
this.$scrollTop()
if (this.$root.$data.config.isSetupWizardDebug) {
this.databaseCredentials = {
connection: 'mysql',
host: '127.0.0.1',
port: '3306',
name: 'vuefilemanager-v2',
username: 'root',
password: 'secret',
}
}
if (this.$root.$data.config.isSetupWizardDebug) {
this.databaseCredentials = {
connection: 'mysql',
host: '127.0.0.1',
port: '3306',
name: 'vuefilemanager-v2',
username: 'root',
password: 'secret',
}
}
},
}
</script>
File diff suppressed because it is too large Load Diff
+64 -21
View File
@@ -1,22 +1,63 @@
<template>
<AuthContentWrapper ref="auth" class="h-screen dark:bg-dark-background bg-white">
<AuthContentWrapper ref="auth" class="h-screen bg-white dark:bg-dark-background">
<!--Licence Verify-->
<AuthContent name="licence-verify" :visible="true">
<Headline title="Setup Wizard" description="Please set your purchase code before continue to set up your application.">
<settings-icon size="40" class="vue-feather text-theme mx-auto animate-[spin_5s_linear_infinite] mb-3" />
<Headline
title="Setup Wizard"
description="Please set your purchase code before continue to set up your application."
>
<settings-icon
size="40"
class="vue-feather text-theme mx-auto mb-3 animate-[spin_5s_linear_infinite]"
/>
</Headline>
<ValidationObserver @submit.prevent="verifyPurchaseCode" ref="verifyPurchaseCode" v-slot="{ invalid }" tag="form" class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0">
<ValidationProvider tag="div" mode="passive" class="w-full text-left" name="Purchase Code" rules="required" v-slot="{ errors }">
<input v-model="purchaseCode" placeholder="Paste your purchase code" type="text" class="focus-border-theme w-full appearance-none rounded-lg border border-transparent bg-light-background px-5 py-3.5 font-bold dark:bg-2x-dark-foreground" :class="{ 'border-red': errors[0] }" />
<ValidationObserver
@submit.prevent="verifyPurchaseCode"
ref="verifyPurchaseCode"
v-slot="{ invalid }"
tag="form"
class="mb-12 items-start space-y-4 md:flex md:space-x-4 md:space-y-0"
>
<ValidationProvider
tag="div"
mode="passive"
class="w-full text-left"
name="Purchase Code"
rules="required"
v-slot="{ errors }"
>
<input
v-model="purchaseCode"
placeholder="Paste your purchase code"
type="text"
class="focus-border-theme w-full appearance-none rounded-lg border border-transparent bg-light-background px-5 py-3.5 font-bold dark:bg-2x-dark-foreground"
:class="{ 'border-red': errors[0] }"
/>
<span class="text-left text-xs text-red-600" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" text="Verify" class="w-full justify-center md:w-min" :loading="isLoading" :disabled="isLoading" />
<AuthButton
icon="chevron-right"
text="Verify"
class="w-full justify-center md:w-min"
:loading="isLoading"
:disabled="isLoading"
/>
</ValidationObserver>
<p class="block">
<a href="https://help.market.envato.com/hc/en-us/articles/202822600-Where-Is-My-Purchase-Code-" target="_blank" class="text-theme font-bold">Where I can find purchase code? </a>
<a class="black-link" href="https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986" target="_blank">Dont have purchase code? </a>
<a
href="https://help.market.envato.com/hc/en-us/articles/202822600-Where-Is-My-Purchase-Code-"
target="_blank"
class="text-theme font-bold"
>Where I can find purchase code?
</a>
<a
class="black-link"
href="https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986"
target="_blank"
>Dont have purchase code?
</a>
</p>
</AuthContent>
</AuthContentWrapper>
@@ -55,9 +96,9 @@ export default {
},
methods: {
async verifyPurchaseCode() {
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({name: 'Database'})
}
if (this.$root.$data.config.isSetupWizardDemo) {
this.$router.push({ name: 'Database' })
}
// Validate fields
const isValid = await this.$refs.verifyPurchaseCode.validate()
@@ -76,15 +117,15 @@ export default {
// End loading
this.isLoading = false
console.log(response);
console.log(response)
if (response.data === 'b6896a44017217c36f4a6fdc56699728') {
this.isExtended = true
localStorage.setItem('license', 'Extended')
} else {
this.isExtended = false
localStorage.setItem('license', 'Regular')
}
if (response.data === 'b6896a44017217c36f4a6fdc56699728') {
this.isExtended = true
localStorage.setItem('license', 'Extended')
} else {
this.isExtended = false
localStorage.setItem('license', 'Regular')
}
localStorage.setItem('purchase_code', this.purchaseCode)
@@ -101,7 +142,9 @@ export default {
})
} else if (error.response.status === 404) {
this.$refs.verifyPurchaseCode.setErrors({
'Purchase Code': ['You may have misconfigured the app, please read the readme file and try it again.'],
'Purchase Code': [
'You may have misconfigured the app, please read the readme file and try it again.',
],
})
} else {
this.$refs.verifyPurchaseCode.setErrors({
+125 -94
View File
@@ -1,119 +1,146 @@
<template>
<AuthContentWrapper ref="auth">
<!--Server Check-->
<AuthContent :visible="true" class="!max-w-2xl mt-6 mb-12">
<AuthContent :visible="true" class="mt-6 mb-12 !max-w-2xl">
<Headline
class="mx-auto max-w-screen-sm !mb-10"
class="mx-auto !mb-10 max-w-screen-sm"
title="Server Check"
description="At first, we have to check if all modules and setup is ready for running VueFileManager"
>
<settings-icon size="40" class="vue-feather text-theme mx-auto animate-[spin_5s_linear_infinite] mb-3" />
<settings-icon
size="40"
class="vue-feather text-theme mx-auto mb-3 animate-[spin_5s_linear_infinite]"
/>
</Headline>
<!--PHP version and ini check-->
<div class="card shadow-card">
<FormLabel>
PHP Setup
</FormLabel>
<InfoBox class="!mb-2">
<p>Those PHP settings are needed for accurate running VueFileManager on your server, please check and tweak in your php.ini if needed.</p>
</InfoBox>
<div class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<div class="text-left">
<b class="text-sm font-bold block">PHP Version</b>
<small v-if="!phpVersion.acceptable" class="text-xs text-gray-600">
You need PHP version at least {{ phpVersion.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="phpVersion.acceptable" size="16" class="vue-feather text-theme"/>
<x-icon v-if="!phpVersion.acceptable" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="phpVersion.acceptable ? 'text-green-600' : 'text-red-600'">
{{ phpVersion.current }}
</span>
</div>
</div>
<div v-for="(values, setting, i) in ini" :key="i" class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<div class="text-left">
<b class="text-sm font-bold block">{{ setting }}</b>
<small v-if="!values.status" class="text-xs text-gray-600">
We recommend set this value at least {{ values.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="values.status" size="16" class="vue-feather text-theme"/>
<x-icon v-if="!values.status" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="values.status ? 'text-green-600' : 'text-red-600'">
{{ values.current }}{{ setting !== 'max_execution_time' ? 'M' : '' }}
</span>
</div>
</div>
</div>
<!--PHP Extension info-->
<!--PHP version and ini check-->
<div class="card shadow-card">
<FormLabel>
Required PHP Extensions
</FormLabel>
<FormLabel> PHP Setup </FormLabel>
<InfoBox class="!mb-2">
<p>Those PHP modules are needed for accurate running VueFileManager on your server, please check and install if some is missing.</p>
<p>
Those PHP settings are needed for accurate running VueFileManager on your server, please check
and tweak in your php.ini if needed.
</p>
</InfoBox>
<div v-if="modules" v-for="(value, module, i) in modules" :key="i" class="py-3 flex items-center justify-between border-b border-dashed border-light dark:border-opacity-5">
<b class="text-sm font-bold">
{{ module }}
</b>
<div class="flex items-center">
<check-icon v-if="value" size="16" class="vue-feather text-theme"/>
<x-icon v-if="!value" size="16" class="vue-feather text-red-600"/>
<div
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<div class="text-left">
<b class="block text-sm font-bold">PHP Version</b>
<small v-if="!phpVersion.acceptable" class="text-xs text-gray-600">
You need PHP version at least {{ phpVersion.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="phpVersion.acceptable" size="16" class="vue-feather text-theme" />
<x-icon v-if="!phpVersion.acceptable" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="value ? 'text-green-600' : 'text-red-600'">
{{ value ? 'Module Installed' : 'Missing Module' }}
</span>
</div>
</div>
</div>
<span
class="ml-3 text-sm font-bold"
:class="phpVersion.acceptable ? 'text-green-600' : 'text-red-600'"
>
{{ phpVersion.current }}
</span>
</div>
</div>
<!--API check-->
<div class="card shadow-card">
<FormLabel>
API
</FormLabel>
<div
v-for="(values, setting, i) in ini"
:key="i"
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<div class="text-left">
<b class="block text-sm font-bold">{{ setting }}</b>
<small v-if="!values.status" class="text-xs text-gray-600">
We recommend set this value at least {{ values.minimal }}.
</small>
</div>
<div class="flex items-center">
<check-icon v-if="values.status" size="16" class="vue-feather text-theme" />
<x-icon v-if="!values.status" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="values.status ? 'text-green-600' : 'text-red-600'">
{{ values.current }}{{ setting !== 'max_execution_time' ? 'M' : '' }}
</span>
</div>
</div>
</div>
<!--PHP Extension info-->
<div class="card shadow-card">
<FormLabel> Required PHP Extensions </FormLabel>
<InfoBox class="!mb-2">
<p>
Those PHP modules are needed for accurate running VueFileManager on your server, please check
and install if some is missing.
</p>
</InfoBox>
<div
v-if="modules"
v-for="(value, module, i) in modules"
:key="i"
class="flex items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
>
<b class="text-sm font-bold">
{{ module }}
</b>
<div class="flex items-center">
<check-icon v-if="value" size="16" class="vue-feather text-theme" />
<x-icon v-if="!value" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="value ? 'text-green-600' : 'text-red-600'">
{{ value ? 'Module Installed' : 'Missing Module' }}
</span>
</div>
</div>
</div>
<!--API check-->
<div class="card shadow-card">
<FormLabel> API </FormLabel>
<InfoBox class="!mb-2">
<p>The check, if your domain is set correctly.</p>
</InfoBox>
<div class="pt-3 flex items-center justify-between">
<div class="text-left">
<b class="text-sm font-bold block">API</b>
<small v-if="isCheckedAPI && !apiRunning" class="text-xs text-gray-600">
We detect, your domain root is not set correctly, please check it.
</small>
</div>
<div v-if="isCheckedAPI" class="flex items-center">
<check-icon v-if="apiRunning" size="16" class="vue-feather text-theme"/>
<x-icon v-if="!apiRunning" size="16" class="vue-feather text-red-600" />
<div class="flex items-center justify-between pt-3">
<div class="text-left">
<b class="block text-sm font-bold">API</b>
<small v-if="isCheckedAPI && !apiRunning" class="text-xs text-gray-600">
We detect, your domain root is not set correctly, please check it.
</small>
</div>
<div v-if="isCheckedAPI" class="flex items-center">
<check-icon v-if="apiRunning" size="16" class="vue-feather text-theme" />
<x-icon v-if="!apiRunning" size="16" class="vue-feather text-red-600" />
<span class="ml-3 text-sm font-bold" :class="apiRunning ? 'text-green-600' : 'text-red-600'">
{{ apiRunning ? 'Working correctly' : "Doesn't work" }}
</span>
</div>
<span v-if="!isCheckedAPI" class="ml-3 text-sm font-bold text-gray-600">Checking your API...</span>
</div>
<span class="ml-3 text-sm font-bold" :class="apiRunning ? 'text-green-600' : 'text-red-600'">
{{ apiRunning ? 'Working correctly' : "Doesn't work" }}
</span>
</div>
<span v-if="!isCheckedAPI" class="ml-3 text-sm font-bold text-gray-600">Checking your API...</span>
</div>
<InfoBox v-if="isError" type="error" class="!mb-2">
<p>We can't proceed to the next step because there are unresolved issues. Please solve it at first and next continue.</p>
<p>
We can't proceed to the next step because there are unresolved issues. Please solve it at first
and next continue.
</p>
</InfoBox>
</div>
</div>
<AuthButton @click.native="lastCheckBeforeNextPage" class="w-full justify-center" icon="chevron-right" text="Awesome, I'm done!" :loading="isLoading" :disabled="isLoading" />
<AuthButton
@click.native="lastCheckBeforeNextPage"
class="w-full justify-center"
icon="chevron-right"
text="Awesome, I'm done!"
:loading="isLoading"
:disabled="isLoading"
/>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -172,9 +199,13 @@ export default {
},
methods: {
lastCheckBeforeNextPage() {
let modulesCheck = Object.values(this.$root.$data.config.statusCheck.modules).every((module) => module === true)
let modulesCheck = Object.values(this.$root.$data.config.statusCheck.modules).every(
(module) => module === true
)
let iniCheck = Object.values(this.$root.$data.config.statusCheck.ini).every((setting) => setting.status === true)
let iniCheck = Object.values(this.$root.$data.config.statusCheck.ini).every(
(setting) => setting.status === true
)
if (modulesCheck && iniCheck && this.apiRunning && this.phpVersion.acceptable) {
this.$router.push({ name: 'PurchaseCode' })
@@ -186,7 +217,7 @@ export default {
axios
.get('/api/ping')
.then((response) => {
this.apiRunning = response.data === 'pong';
this.apiRunning = response.data === 'pong'
})
.catch(() => {
this.apiRunning = false
@@ -198,4 +229,4 @@ export default {
this.pingAPI()
},
}
</script>
</script>
+6 -5
View File
@@ -61,13 +61,13 @@ import DragUI from '../components/FilesView/DragUI'
import Alert from '../components/FilesView/Alert'
import { mapGetters } from 'vuex'
import { events } from '../bus'
import router from "../router";
import DesktopSharepageToolbar from "../components/FilesView/DesktopSharepageToolbar";
import router from '../router'
import DesktopSharepageToolbar from '../components/FilesView/DesktopSharepageToolbar'
export default {
name: 'Shared',
components: {
DesktopSharepageToolbar,
DesktopSharepageToolbar,
MobileToolbar,
InfoSidebar,
NavigationSharePanel,
@@ -102,8 +102,9 @@ export default {
events.$on('mobile-menu:show', () => (this.isScaledDown = true))
events.$on('mobile-menu:hide', () => (this.isScaledDown = false))
this.$store.dispatch('getShareDetail', this.$router.currentRoute.params.token)
.then(() => this.$store.dispatch('getFolderTree'))
this.$store
.dispatch('getShareDetail', this.$router.currentRoute.params.token)
.then(() => this.$store.dispatch('getFolderTree'))
},
}
</script>
+2 -2
View File
@@ -83,7 +83,7 @@ export default {
})
.then((response) => {
// Show file browser
if ( response.data.data.attributes.type === 'folder' ) {
if (response.data.data.attributes.type === 'folder') {
this.$router.replace({
name: 'Public',
params: {
@@ -94,7 +94,7 @@ export default {
}
// Show single file
if ( response.data.data.attributes.type !== 'folder' ) {
if (response.data.data.attributes.type !== 'folder') {
this.$router.push({ name: 'SharedSingleFile' })
}
})
+65 -54
View File
@@ -1,61 +1,73 @@
<template>
<div class="flex h-screen items-center justify-center p-4">
<!--App logo-->
<div v-if="file && !isVideo" class="fixed top-4 left-0 right-0">
<router-link :to="{ name: 'SignIn' }" class="block">
<!--Image logo-->
<img
v-if="config.app_logo_horizontal"
class="mx-auto w-44"
:src="$getImage(config.app_logo_horizontal)"
:alt="config.app_name"
/>
<!--App logo-->
<div v-if="file && !isVideo" class="fixed top-4 left-0 right-0">
<router-link :to="{name: 'SignIn'}" class="block">
<!--Image logo-->
<img v-if="config.app_logo_horizontal" class="mx-auto w-44" :src="$getImage(config.app_logo_horizontal)" :alt="config.app_name" />
<!--Text logo if image isn't available-->
<b v-if="!config.app_logo_horizontal" class="mb-4 block text-xl font-bold">
{{ config.app_name }}
</b>
</router-link>
</div>
<!--Text logo if image isn't available-->
<b v-if="! config.app_logo_horizontal" class="mb-4 block text-xl font-bold">
{{ config.app_name }}
</b>
</router-link>
</div>
<!--File preview-->
<!--File preview-->
<div v-if="file" class="w-full text-center">
<!--App logo-->
<router-link v-if="isVideo" :to="{ name: 'SignIn' }" class="block">
<!--Image logo-->
<img
v-if="config.app_logo_horizontal"
class="mx-auto w-44"
:src="$getImage(config.app_logo_horizontal)"
:alt="config.app_name"
/>
<!--App logo-->
<router-link v-if="isVideo" :to="{name: 'SignIn'}" class="block">
<!--Image logo-->
<img v-if="config.app_logo_horizontal" class="mx-auto w-44" :src="$getImage(config.app_logo_horizontal)" :alt="config.app_name" />
<!--Text logo if image isn't available-->
<b v-if="!config.app_logo_horizontal" class="mb-4 block text-xl font-bold">
{{ config.app_name }}
</b>
</router-link>
<!--Text logo if image isn't available-->
<b v-if="! config.app_logo_horizontal" class="mb-4 block text-xl font-bold">
{{ config.app_name }}
</b>
</router-link>
<!--File item-->
<ItemGrid v-if="!isVideo" :entry="file" :mobile-handler="false" class="mt-2" />
<!--File item-->
<ItemGrid v-if="! isVideo" :entry="file" :mobile-handler="false" class="mt-2" />
<!--Video preview-->
<div v-if="isVideo" class="mb-4">
<!--Video preview-->
<Video
:file="file"
class="mx-auto my-10 w-full self-center rounded-lg shadow-xl lg:max-w-xl xl:max-w-3xl 2xl:max-w-5xl"
/>
<!--Video preview-->
<div v-if="isVideo" class="mb-4">
<!--Item Info-->
<div class="text-center">
<!--Item Title-->
<b class="inline-block w-full text-sm tracking-tight md:px-6">
{{ file.data.attributes.name }}
</b>
<!--Video preview-->
<Video :file="file" class="w-full lg:max-w-xl xl:max-w-3xl 2xl:max-w-5xl self-center mx-auto my-10 shadow-xl rounded-lg"/>
<!--Item sub line-->
<div class="flex items-center justify-center">
<!--File & Image sub line-->
<small class="block text-xs text-gray-500 dark:text-gray-500">
{{ file.data.attributes.filesize
}}<span class="text-xs text-gray-500 lg:inline-block"
>, {{ file.data.attributes.created_at }}</span
>
</small>
</div>
</div>
</div>
<!--Item Info-->
<div class="text-center">
<!--Item Title-->
<b class="tracking-tight inline-block w-full text-sm md:px-6">
{{ file.data.attributes.name }}
</b>
<!--Item sub line-->
<div class="flex items-center justify-center">
<!--File & Image sub line-->
<small class="block text-xs text-gray-500 dark:text-gray-500">
{{ file.data.attributes.filesize }}<span class="text-xs text-gray-500 lg:inline-block">, {{ file.data.attributes.created_at }}</span>
</small>
</div>
</div>
</div>
<!--Download button-->
<!--Download button-->
<ButtonBase @click.native="$downloadSelection(file)" button-style="theme" class="mx-auto">
{{ $t('page_shared.download_file') }}
</ButtonBase>
@@ -68,7 +80,7 @@
<script>
import ButtonBase from '../components/FilesView/ButtonBase'
import Video from "../components/FilePreview/Media/Video"
import Video from '../components/FilePreview/Media/Video'
import ItemGrid from '../components/FilesView/ItemGrid'
import { mapGetters } from 'vuex'
import axios from 'axios'
@@ -78,13 +90,13 @@ export default {
components: {
ButtonBase,
ItemGrid,
Video,
Video,
},
computed: {
...mapGetters(['config']),
isVideo() {
return this.file.data.type === 'video'
}
isVideo() {
return this.file.data.type === 'video'
},
},
data() {
return {
@@ -98,8 +110,7 @@ export default {
this.file = response.data
})
.catch((error) => {
if (error.response.status === 403)
this.$router.push({ name: 'SharedAuthentication' })
if (error.response.status === 403) this.$router.push({ name: 'SharedAuthentication' })
})
},
}
+5 -6
View File
@@ -166,12 +166,11 @@ export default {
axios
.put(`/api/teams/invitations/${this.$router.currentRoute.params.id}`)
.then(() => {
if (this.invitation.data.attributes.isExistedUser) {
this.goToAuthPage('accepted')
} else {
this.$router.push({name: 'SignUp'})
}
if (this.invitation.data.attributes.isExistedUser) {
this.goToAuthPage('accepted')
} else {
this.$router.push({ name: 'SignUp' })
}
})
.catch(() => {
this.$isSomethingWrong()
+4 -1
View File
@@ -1,7 +1,10 @@
<template>
<AuthContentWrapper ref="auth" class="h-screen">
<AuthContent :visible="true">
<Headline :title="$t('Temporary Unavailable')" :description="$t('Unfortunately, this shared link is temporary unavailable. Please try it later.')" />
<Headline
:title="$t('Temporary Unavailable')"
:description="$t('Unfortunately, this shared link is temporary unavailable. Please try it later.')"
/>
<span class="additional-link"
>{{ $t('page_registration.have_an_account') }}
+90
View File
@@ -0,0 +1,90 @@
<template>
<div class="lg:flex lg:h-screen lg:overflow-hidden">
<!--On Top of App Components-->
<FilePreview />
<Spotlight />
<!--Popups-->
<CreateFolderPopup />
<RenameItemPopup />
<MoveItemPopup />
<!--Mobile components-->
<FileSortingMobile />
<FileFilterMobile />
<!--Others-->
<DragUI />
<div
@contextmenu.prevent.capture="contextMenu($event, undefined)"
class="transition-transform duration-200 lg:grid lg:flex-grow lg:content-start lg:px-3.5"
>
<DesktopUploadRequestToolbar v-if="entries.length" />
<!--<MobileToolbar />-->
<!--Google Adsense banner-->
<div v-if="config.allowedAdsense" v-html="config.adsenseBanner01" class="mb-5 min-h-[120px]"></div>
<!--File list & info sidebar-->
<div class="flex space-x-3 lg:overflow-hidden">
<router-view id="file-view" class="relative w-full" :key="$route.fullPath" />
<!--<InfoSidebar v-if="isVisibleSidebar" />-->
</div>
</div>
</div>
</template>
<script>
import DesktopUploadRequestToolbar from '../components/FilesView/DesktopUploadRequestToolbar'
import FileSortingMobile from '../components/FilesView/FileSortingMobile'
import FileFilterMobile from '../components/FilesView/FileFilterMobile'
import CreateFolderPopup from '../components/Others/CreateFolderPopup'
import DesktopToolbar from '../components/FilesView/DesktopToolbar'
import RenameItemPopup from '../components/Others/RenameItemPopup'
import MobileToolbar from '../components/FilesView/MobileToolbar'
import FilePreview from '../components/FilePreview/FilePreview'
import MoveItemPopup from '../components/Others/MoveItemPopup'
import InfoSidebar from '../components/FilesView/InfoSidebar'
import Spotlight from '../components/Spotlight/Spotlight'
import DragUI from '../components/FilesView/DragUI'
import { mapGetters } from 'vuex'
import { events } from '../bus'
export default {
name: 'UploadRequest',
components: {
DesktopUploadRequestToolbar,
CreateFolderPopup,
FileSortingMobile,
FileFilterMobile,
RenameItemPopup,
DesktopToolbar,
MoveItemPopup,
MobileToolbar,
InfoSidebar,
FilePreview,
Spotlight,
DragUI,
},
computed: {
...mapGetters(['isVisibleSidebar', 'config', 'entries']),
},
data() {
return {
isScaledDown: false,
}
},
methods: {
contextMenu(event, item) {
events.$emit('context-menu:show', event, item)
},
},
mounted() {
// TODO: new scaledown effect
events.$on('mobile-menu:show', () => (this.isScaledDown = true))
events.$on('mobile-menu:hide', () => (this.isScaledDown = false))
},
}
</script>
+30 -5
View File
@@ -5,8 +5,16 @@
<FormLabel icon="smartphone">
{{ $t('2fa.settings.title') }}
</FormLabel>
<AppInputSwitch :title="$t('popup_2fa.switch_title')" :description="$t('popup_2fa.switch_info')" :is-last="!user.data.attributes.two_factor_authentication">
<SwitchInput v-model="user.data.attributes.two_factor_authentication" class="switch" :state="user.data.attributes.two_factor_authentication" />
<AppInputSwitch
:title="$t('popup_2fa.switch_title')"
:description="$t('popup_2fa.switch_info')"
:is-last="!user.data.attributes.two_factor_authentication"
>
<SwitchInput
v-model="user.data.attributes.two_factor_authentication"
class="switch"
:state="user.data.attributes.two_factor_authentication"
/>
</AppInputSwitch>
<AppInputButton
v-if="user && user.data.attributes.two_factor_authentication"
@@ -56,13 +64,24 @@
</div>
</div>
<ButtonBase @click.native="openCreateTokenPopup" type="submit" button-style="theme" class="w-full sm:w-auto">
<ButtonBase
@click.native="openCreateTokenPopup"
type="submit"
button-style="theme"
class="w-full sm:w-auto"
>
{{ $t('personal_token.create_token') }}
</ButtonBase>
</div>
<!--Change password-->
<ValidationObserver ref="password" @submit.prevent="resetPassword" v-slot="{ invalid }" tag="form" class="card shadow-card">
<ValidationObserver
ref="password"
@submit.prevent="resetPassword"
v-slot="{ invalid }"
tag="form"
class="card shadow-card"
>
<FormLabel>
{{ $t('user_password.title') }}
</FormLabel>
@@ -91,7 +110,13 @@
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Confirm Your Password" rules="required" v-slot="{ errors }">
<ValidationProvider
tag="div"
mode="passive"
name="Confirm Your Password"
rules="required"
v-slot="{ errors }"
>
<AppInputText :title="$t('page_create_password.label_confirm_pass')" :error="errors[0]">
<input
v-model="passwordForm.password_confirmation"
+86 -32
View File
@@ -28,7 +28,13 @@
<AppInputText :title="$t('GMT')" :is-last="true">
<SelectInput
@input="$updateText('/user/settings', 'timezone', user.data.relationships.settings.data.attributes.timezone)"
@input="
$updateText(
'/user/settings',
'timezone',
user.data.relationships.settings.data.attributes.timezone
)
"
v-model="user.data.relationships.settings.data.attributes.timezone"
:default="user.data.relationships.settings.data.attributes.timezone"
:options="timezones"
@@ -43,7 +49,13 @@
</FormLabel>
<AppInputText :title="$t('user_settings.address')">
<input
@keyup="$updateText('/user/settings', 'address', user.data.relationships.settings.data.attributes.address)"
@keyup="
$updateText(
'/user/settings',
'address',
user.data.relationships.settings.data.attributes.address
)
"
v-model="user.data.relationships.settings.data.attributes.address"
:placeholder="$t('user_settings.address_plac')"
type="text"
@@ -53,7 +65,9 @@
<div class="flex space-x-4">
<AppInputText :title="$t('user_settings.city')" class="w-full">
<input
@keyup="$updateText('/user/settings', 'city', user.data.relationships.settings.data.attributes.city)"
@keyup="
$updateText('/user/settings', 'city', user.data.relationships.settings.data.attributes.city)
"
v-model="user.data.relationships.settings.data.attributes.city"
:placeholder="$t('user_settings.city_plac')"
type="text"
@@ -62,7 +76,13 @@
</AppInputText>
<AppInputText :title="$t('user_settings.postal_code')" class="w-full">
<input
@keyup="$updateText('/user/settings', 'postal_code', user.data.relationships.settings.data.attributes.postal_code)"
@keyup="
$updateText(
'/user/settings',
'postal_code',
user.data.relationships.settings.data.attributes.postal_code
)
"
v-model="user.data.relationships.settings.data.attributes.postal_code"
:placeholder="$t('user_settings.postal_code_plac')"
type="text"
@@ -72,7 +92,13 @@
</div>
<AppInputText :title="$t('user_settings.country')">
<SelectInput
@input="$updateText('/user/settings', 'country', user.data.relationships.settings.data.attributes.country)"
@input="
$updateText(
'/user/settings',
'country',
user.data.relationships.settings.data.attributes.country
)
"
v-model="user.data.relationships.settings.data.attributes.country"
:default="user.data.relationships.settings.data.attributes.country"
:options="countries"
@@ -81,7 +107,9 @@
</AppInputText>
<AppInputText :title="$t('user_settings.state')" :description="$t('State, county, province, or region.')">
<input
@keyup="$updateText('/user/settings', 'state', user.data.relationships.settings.data.attributes.state)"
@keyup="
$updateText('/user/settings', 'state', user.data.relationships.settings.data.attributes.state)
"
v-model="user.data.relationships.settings.data.attributes.state"
:placeholder="$t('user_settings.state_plac')"
type="text"
@@ -90,7 +118,13 @@
</AppInputText>
<AppInputText :title="$t('user_settings.phone_number')" :is-last="true">
<input
@keyup="$updateText('/user/settings', 'phone_number', user.data.relationships.settings.data.attributes.phone_number)"
@keyup="
$updateText(
'/user/settings',
'phone_number',
user.data.relationships.settings.data.attributes.phone_number
)
"
v-model="user.data.relationships.settings.data.attributes.phone_number"
:placeholder="$t('user_settings.phone_number_plac')"
type="text"
@@ -99,48 +133,60 @@
</AppInputText>
</div>
<div class="card shadow-card">
<div class="card shadow-card">
<FormLabel>
{{ $t('Appearance') }}
</FormLabel>
<AppInputText :title="$t('Theme Mode')" :description="$t('Set your theme mode on dark, light or based on your system settings.')" :is-last="!$isApple()">
<AppInputText
:title="$t('Theme Mode')"
:description="$t('Set your theme mode on dark, light or based on your system settings.')"
:is-last="!$isApple()"
>
<div class="items-center space-y-4 md:flex md:space-x-6 md:space-x-4 md:space-y-0">
<div
v-for="(theme, i) in themeSetup"
:key="i"
:title="theme.title"
@click="$store.dispatch('toggleThemeMode', theme.type)"
class="w-full cursor-pointer overflow-hidden rounded-xl border-3 shadow-lg"
:class="{
v-for="(theme, i) in themeSetup"
:key="i"
:title="theme.title"
@click="$store.dispatch('toggleThemeMode', theme.type)"
class="w-full cursor-pointer overflow-hidden rounded-xl border-3 shadow-lg"
:class="{
'border-theme': config.defaultThemeMode === theme.type,
'border-transparent': config.defaultThemeMode !== theme.type,
}"
>
<img :src="theme.image" :alt="theme.type" class="w-full"/>
>
<img :src="theme.image" :alt="theme.type" class="w-full" />
</div>
</div>
</AppInputText>
<AppInputText
v-if="$isApple()"
:title="$t('Default Emojis')"
:description="$t('Set your default emojis for your folder custom icons. You can set Twemoji or default Apple emojis.')"
:is-last="true"
>
v-if="$isApple()"
:title="$t('Default Emojis')"
:description="
$t(
'Set your default emojis for your folder custom icons. You can set Twemoji or default Apple emojis.'
)
"
:is-last="true"
>
<div class="items-center space-y-4 md:flex md:space-x-6 md:space-x-4 md:space-y-0">
<div
v-for="(emoji, i) in emojiSetup"
:key="i"
:title="emoji.title"
@click="$store.dispatch('toggleEmojiType', emoji.type)"
class="w-full cursor-pointer overflow-hidden rounded-xl border-3 shadow-lg"
:class="{
v-for="(emoji, i) in emojiSetup"
:key="i"
:title="emoji.title"
@click="$store.dispatch('toggleEmojiType', emoji.type)"
class="w-full cursor-pointer overflow-hidden rounded-xl border-3 shadow-lg"
:class="{
'border-theme': currentEmojis === emoji.type,
'border-transparent': currentEmojis !== emoji.type,
}"
>
<img :src="isDarkMode ? emoji.image.dark : emoji.image.light" :alt="emoji.type" class="w-full" />
>
<img
:src="isDarkMode ? emoji.image.dark : emoji.image.light"
:alt="emoji.type"
class="w-full"
/>
</div>
</div>
</AppInputText>
@@ -213,11 +259,19 @@ export default {
methods: {
updateFirstName() {
this.$store.commit('UPDATE_FIRST_NAME', this.user.data.relationships.settings.data.attributes.first_name)
this.$updateText('/user/settings', 'first_name', this.user.data.relationships.settings.data.attributes.first_name)
this.$updateText(
'/user/settings',
'first_name',
this.user.data.relationships.settings.data.attributes.first_name
)
},
updateLastName() {
this.$store.commit('UPDATE_LAST_NAME', this.user.data.relationships.settings.data.attributes.last_name)
this.$updateText('/user/settings', 'last_name', this.user.data.relationships.settings.data.attributes.last_name)
this.$updateText(
'/user/settings',
'last_name',
this.user.data.relationships.settings.data.attributes.last_name
)
},
},
}
+6 -1
View File
@@ -9,7 +9,12 @@
{{ storage.data.attributes.used }}
</b>
<b v-if="config.subscriptionType === 'fixed' || (config.subscriptionType === 'none' && config.storageLimit)" class="mt-0.5 block text-sm text-gray-400">
<b
v-if="
config.subscriptionType === 'fixed' || (config.subscriptionType === 'none' && config.storageLimit)
"
class="mt-0.5 block text-sm text-gray-400"
>
{{ $t('Total of') }} {{ storage.data.attributes.capacity }}
{{ $t('Used') }}
</b>