mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-19 16:32:15 +00:00
vue components refactoring
This commit is contained in:
61
resources/js/views/Admin/Settings/AppSettings.vue
Normal file
61
resources/js/views/Admin/Settings/AppSettings.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--Page Tab links-->
|
||||
<div class="card z-10 shadow-card" style="padding-bottom: 0; padding-top: 0">
|
||||
<CardNavigation :pages="pages" class="-mx-1" />
|
||||
</div>
|
||||
|
||||
<!--Page Content-->
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CardNavigation from '../../../components/UI/Others/CardNavigation'
|
||||
|
||||
export default {
|
||||
name: 'AppSettings',
|
||||
components: {
|
||||
CardNavigation,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
title: this.$t('admin_settings.tabs.others'),
|
||||
route: 'AppOthers',
|
||||
},
|
||||
{
|
||||
title: this.$t('login_and_registration'),
|
||||
route: 'AppSignInUp',
|
||||
},
|
||||
{
|
||||
title: this.$t('appearance'),
|
||||
route: 'AppAppearance',
|
||||
},
|
||||
{
|
||||
title: this.$t('Adsense'),
|
||||
route: 'AppAdsense',
|
||||
},
|
||||
{
|
||||
title: this.$t('homepage'),
|
||||
route: 'AppIndex',
|
||||
},
|
||||
{
|
||||
title: this.$t('environment'),
|
||||
route: 'AppEnvironment',
|
||||
},
|
||||
{
|
||||
title: this.$t('server'),
|
||||
route: 'AppServer',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$route.path === '/admin/settings') {
|
||||
this.$router.push({ name: 'AppOthers' })
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
126
resources/js/views/Admin/Settings/AppSettingsTabs/Adsense.vue
Normal file
126
resources/js/views/Admin/Settings/AppSettingsTabs/Adsense.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<!--Adsense basic setup-->
|
||||
<div v-if="adsense" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Basic Setup') }}
|
||||
</FormLabel>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<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"
|
||||
:placeholder="$t('Client Id...')"
|
||||
type="text"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<!--Adsense places-->
|
||||
<div v-if="adsense" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('Ads') }}
|
||||
</FormLabel>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SwitchInput from '../../../../components/Inputs/SwitchInput'
|
||||
import AppInputButton from '../../../../components/Forms/Layouts/AppInputButton'
|
||||
import AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Adsense',
|
||||
components: {
|
||||
AppInputButton,
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
SwitchInput,
|
||||
FormLabel,
|
||||
PageTab,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
adsense: {
|
||||
allowedService: undefined,
|
||||
clientId: 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,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
163
resources/js/views/Admin/Settings/AppSettingsTabs/Appearance.vue
Normal file
163
resources/js/views/Admin/Settings/AppSettingsTabs/Appearance.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<PageTab :is-loading="isLoading">
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('admin_settings.appearance.section_general') }}
|
||||
</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"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputText :title="$t('admin_settings.appearance.title')">
|
||||
<input
|
||||
@input="$updateText('/admin/settings', 'app_title', app.title)"
|
||||
v-model="app.title"
|
||||
:placeholder="$t('admin_settings.appearance.title_plac')"
|
||||
type="text"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText :title="$t('admin_settings.appearance.description')" :is-last="true">
|
||||
<input
|
||||
@input="$updateText('/admin/settings', 'app_description', app.description)"
|
||||
v-model="app.description"
|
||||
:placeholder="$t('admin_settings.appearance.description_plac')"
|
||||
type="text"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('branding') }}
|
||||
</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"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText :title="$t('app_logo_dark_mode')">
|
||||
<ImageInput
|
||||
@input="$updateImage('/admin/settings', 'app_logo_dark', app.logo_dark)"
|
||||
:image="$getImage(app.logo_dark)"
|
||||
v-model="app.logo_dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText :title="$t('admin_settings.appearance.logo_horizontal')">
|
||||
<ImageInput
|
||||
@input="$updateImage('/admin/settings', 'app_logo_horizontal', app.logo_horizontal)"
|
||||
:image="$getImage(app.logo_horizontal)"
|
||||
v-model="app.logo_horizontal"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText :title="$t('app_logo_horizontal_dark_mode')">
|
||||
<ImageInput
|
||||
@input="$updateImage('/admin/settings', 'app_logo_horizontal_dark', app.logo_horizontal_dark)"
|
||||
:image="$getImage(app.logo_horizontal_dark)"
|
||||
v-model="app.logo_horizontal_dark"
|
||||
/>
|
||||
</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"
|
||||
/>
|
||||
</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"
|
||||
/>
|
||||
</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"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
||||
import PageTabGroup from '../../../../components/Layout/PageTabGroup'
|
||||
import SelectInput from '../../../../components/Inputs/SelectInput'
|
||||
import ImageInput from '../../../../components/Inputs/ImageInput'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import InfoBox from '../../../../components/UI/Others/InfoBox'
|
||||
import { required } from 'vee-validate/dist/rules'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'AppAppearance',
|
||||
components: {
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
ValidationObserver,
|
||||
ValidationProvider,
|
||||
PageTabGroup,
|
||||
SelectInput,
|
||||
ImageInput,
|
||||
ButtonBase,
|
||||
FormLabel,
|
||||
required,
|
||||
PageTab,
|
||||
InfoBox,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
app: undefined,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios
|
||||
.get('/api/admin/settings', {
|
||||
params: {
|
||||
column: 'app_title|app_description|app_logo|app_logo_dark|app_favicon|app_logo_horizontal|app_logo_horizontal_dark|app_color|app_og_image|app_touch_icon',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
this.app = {
|
||||
logo_horizontal: response.data.app_logo_horizontal,
|
||||
logo_horizontal_dark: response.data.app_logo_horizontal_dark,
|
||||
description: response.data.app_description,
|
||||
favicon: response.data.app_favicon,
|
||||
title: response.data.app_title,
|
||||
color: response.data.app_color,
|
||||
logo: response.data.app_logo,
|
||||
logo_dark: response.data.app_logo_dark,
|
||||
og_image: response.data.app_og_image,
|
||||
touch_icon: response.data.app_touch_icon,
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,370 @@
|
||||
<template>
|
||||
<PageTab :is-loading="isLoading">
|
||||
<!--Broadcasting setup-->
|
||||
<ValidationObserver
|
||||
@submit.prevent="broadcastSetupSubmit"
|
||||
ref="broadcastSetup"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="card shadow-card"
|
||||
>
|
||||
<FormLabel icon="wifi">
|
||||
{{ $t('broadcasting') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Broadcast Driver" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Broadcast Driver" :error="errors[0]">
|
||||
<SelectInput
|
||||
v-model="broadcast.driver"
|
||||
:options="broadcastDrivers"
|
||||
placeholder="Select your broadcast driver"
|
||||
:isError="errors[0]"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<div v-if="broadcast.driver === 'native'">
|
||||
<ValidationProvider tag="div" mode="passive" name="Host" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Hostname or IP" :error="errors[0]">
|
||||
<input
|
||||
class="focus-border-theme input-dark"
|
||||
v-model="broadcast.host"
|
||||
placeholder="Type your hostname or IP"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Port" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Port" :error="errors[0]">
|
||||
<input
|
||||
class="focus-border-theme input-dark"
|
||||
v-model="broadcast.port"
|
||||
placeholder="Type your port"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div v-if="broadcast.driver === 'pusher'">
|
||||
<ValidationProvider tag="div" mode="passive" name="App ID" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="App ID" :error="errors[0]">
|
||||
<input
|
||||
class="focus-border-theme input-dark"
|
||||
v-model="broadcast.id"
|
||||
placeholder="Type your app id"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Key" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Key" :error="errors[0]">
|
||||
<input
|
||||
class="focus-border-theme input-dark"
|
||||
v-model="broadcast.key"
|
||||
placeholder="Paste your key"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': 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="broadcast.secret"
|
||||
placeholder="Paste your secret"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Cluster" rules="required" v-slot="{ errors }">
|
||||
<AppInputText title="Cluster" :error="errors[0]">
|
||||
<SelectInput
|
||||
v-model="broadcast.cluster"
|
||||
:options="pusherClusters"
|
||||
placeholder="Select your cluster"
|
||||
:isError="errors[0]"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<ButtonBase
|
||||
:loading="isSendingBroadcastForm"
|
||||
:disabled="isSendingBroadcastForm"
|
||||
type="submit"
|
||||
button-style="theme"
|
||||
class="w-full sm:w-auto"
|
||||
>
|
||||
{{ $t('save_broadcast_settings') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
|
||||
<!--Storage setup-->
|
||||
<ValidationObserver
|
||||
@submit.prevent="storageSetupSubmit"
|
||||
ref="storageSetup"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="card shadow-card"
|
||||
>
|
||||
<StorageSetup v-model="storage" />
|
||||
|
||||
<ButtonBase
|
||||
:loading="isSendingStorageForm"
|
||||
:disabled="isSendingStorageForm"
|
||||
type="submit"
|
||||
button-style="theme"
|
||||
class="mt-6 w-full sm:mt-7 sm:w-auto"
|
||||
>
|
||||
{{ $t('save_storage_settings') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
|
||||
<!--Mail setup-->
|
||||
<ValidationObserver
|
||||
@submit.prevent="emailSetupSubmit"
|
||||
ref="EmailSetup"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="card shadow-card"
|
||||
>
|
||||
<MailSetup v-model="mail" />
|
||||
|
||||
<ButtonBase
|
||||
:loading="isSendingEmailForm"
|
||||
:disabled="isSendingEmailForm"
|
||||
type="submit"
|
||||
button-style="theme"
|
||||
class="mt-6 w-full sm:mt-7 sm:w-auto"
|
||||
>
|
||||
{{ $t('admin_settings.email.save_button') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ValidationObserver, ValidationProvider } from 'vee-validate/dist/vee-validate.full'
|
||||
import SelectInput from '../../../../components/Inputs/SelectInput'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import StorageSetup from '../../../../components/Forms/StorageSetup'
|
||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import MailSetup from '../../../../components/Forms/MailSetup'
|
||||
import { events } from '../../../../bus'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'AppEnvironment',
|
||||
components: {
|
||||
ValidationObserver,
|
||||
ValidationProvider,
|
||||
StorageSetup,
|
||||
AppInputText,
|
||||
SelectInput,
|
||||
ButtonBase,
|
||||
MailSetup,
|
||||
FormLabel,
|
||||
PageTab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
storage: undefined,
|
||||
mail: undefined,
|
||||
isLoading: false,
|
||||
isSendingEmailForm: false,
|
||||
isSendingStorageForm: false,
|
||||
isSendingBroadcastForm: false,
|
||||
broadcast: {
|
||||
driver: undefined,
|
||||
id: undefined,
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
cluster: undefined,
|
||||
port: undefined,
|
||||
host: undefined,
|
||||
},
|
||||
broadcastDrivers: [
|
||||
{
|
||||
label: 'Pusher',
|
||||
value: 'pusher',
|
||||
},
|
||||
{
|
||||
label: 'VueFileManager Broadcast Server',
|
||||
value: 'native',
|
||||
},
|
||||
{
|
||||
label: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
],
|
||||
pusherClusters: [
|
||||
{
|
||||
label: 'US East (N. Virginia)',
|
||||
value: 'mt1',
|
||||
},
|
||||
{
|
||||
label: 'Asia Pacific (Singapore)',
|
||||
value: 'ap1',
|
||||
},
|
||||
{
|
||||
label: 'Asia Pacific (Mumbai)',
|
||||
value: 'ap2',
|
||||
},
|
||||
{
|
||||
label: 'US East (Ohio)',
|
||||
value: 'us2',
|
||||
},
|
||||
{
|
||||
label: 'Asia Pacific (Tokyo)',
|
||||
value: 'ap3',
|
||||
},
|
||||
{
|
||||
label: 'US West (Oregon)',
|
||||
value: 'us3',
|
||||
},
|
||||
{
|
||||
label: 'Asia Pacific (Sydney)',
|
||||
value: 'ap4',
|
||||
},
|
||||
{
|
||||
label: 'EU (Ireland)',
|
||||
value: 'eu',
|
||||
},
|
||||
{
|
||||
label: 'South America (São Paulo)',
|
||||
value: 'sa1',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async broadcastSetupSubmit() {
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.broadcastSetup.validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
// Start loading
|
||||
this.isSendingBroadcastForm = true
|
||||
|
||||
axios
|
||||
.post('/api/admin/settings/broadcast', { ...this.broadcast })
|
||||
.then(() => {
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('broadcast_driver_updated'),
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
events.$emit('toaster', {
|
||||
type: 'danger',
|
||||
message: this.$t('popup_error.title'),
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.isSendingBroadcastForm = false
|
||||
|
||||
this.broadcast = {
|
||||
driver: undefined,
|
||||
id: undefined,
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
cluster: undefined,
|
||||
host: undefined,
|
||||
port: undefined,
|
||||
}
|
||||
})
|
||||
},
|
||||
async storageSetupSubmit() {
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.storageSetup.validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
// Start loading
|
||||
this.isSendingStorageForm = true
|
||||
|
||||
axios
|
||||
.post('/api/admin/settings/storage', {
|
||||
storage: this.storage,
|
||||
})
|
||||
.then(() => {
|
||||
this.storage = undefined
|
||||
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('storage_driver_updated'),
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
if ([401, 500].includes(error.response.status)) {
|
||||
events.$emit('alert:open', {
|
||||
title: error.response.data.title || this.$t('popup_error.title'),
|
||||
message: error.response.data.message,
|
||||
})
|
||||
} else {
|
||||
events.$emit('toaster', {
|
||||
type: 'danger',
|
||||
message: this.$t('popup_error.title'),
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.isSendingStorageForm = false
|
||||
})
|
||||
},
|
||||
async emailSetupSubmit() {
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.EmailSetup.validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
// Start loading
|
||||
this.isSendingEmailForm = true
|
||||
|
||||
axios
|
||||
.post('/api/admin/settings/email', {
|
||||
mailDriver: this.mail.driver,
|
||||
postmark: this.mail.postmark,
|
||||
mailgun: this.mail.mailgun,
|
||||
smtp: this.mail.smtp,
|
||||
ses: this.mail.ses,
|
||||
})
|
||||
.then(() => {
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('toaster.email_set'),
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status === 401 && error.response.data.type === 'mailer-connection-error') {
|
||||
events.$emit('alert:open', {
|
||||
title: 'Mailer Connection Error - Wrong Credentials',
|
||||
message: error.response.data.message,
|
||||
})
|
||||
} else {
|
||||
events.$emit('toaster', {
|
||||
type: 'danger',
|
||||
message: this.$t('popup_error.title'),
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.isSendingEmailForm = false
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
588
resources/js/views/Admin/Settings/AppSettingsTabs/Index.vue
Normal file
588
resources/js/views/Admin/Settings/AppSettingsTabs/Index.vue
Normal file
@@ -0,0 +1,588 @@
|
||||
<template>
|
||||
<PageTab :is-loading="isLoading">
|
||||
<PageTabGroup v-if="app">
|
||||
<div class="form block-form">
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('homepage') }}
|
||||
</FormLabel>
|
||||
|
||||
<AppInputSwitch
|
||||
:title="$t('allow_homepage')"
|
||||
:description="$t('allow_homepage_note')"
|
||||
:is-last="true"
|
||||
>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'allow_homepage', app.allow_homepage)"
|
||||
v-model="app.allow_homepage"
|
||||
class="switch"
|
||||
:state="app.allow_homepage"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
</div>
|
||||
|
||||
<!--Header-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>Header Title</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<img src="/assets/images/admin/main-header.jpg" alt="Main Header" class="page-image" />
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Description:</label>
|
||||
<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"
|
||||
v-model="app.header_description"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Features title-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>Features Title</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<div>
|
||||
<div class="inline-wrapper">
|
||||
<div class="switch-label">
|
||||
<label class="input-label"> Show section: </label>
|
||||
</div>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'section_features', app.section_features)"
|
||||
v-model="app.section_features"
|
||||
class="switch"
|
||||
:state="app.section_features"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="app.section_features">
|
||||
<div class="block-wrapper">
|
||||
<img src="/assets/images/admin/main-features.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 }"
|
||||
>
|
||||
<input
|
||||
@input="$updateText('/admin/settings', 'features_title', app.features_title)"
|
||||
v-model="app.features_title"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Description:</label>
|
||||
<ValidationProvider
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="App Description"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<textarea
|
||||
@input="
|
||||
$updateText('/admin/settings', 'features_description', app.features_description)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.features_description"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Feature boxes-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>Feature Boxes</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<div>
|
||||
<div class="inline-wrapper">
|
||||
<div class="switch-label">
|
||||
<label class="input-label"> Show section: </label>
|
||||
</div>
|
||||
<SwitchInput
|
||||
@input="
|
||||
$updateText(
|
||||
'/admin/settings',
|
||||
'section_feature_boxes',
|
||||
app.section_feature_boxes
|
||||
)
|
||||
"
|
||||
v-model="app.section_feature_boxes"
|
||||
class="switch"
|
||||
:state="app.section_feature_boxes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="app.section_feature_boxes">
|
||||
<div class="block-wrapper">
|
||||
<img src="/assets/images/admin/feature-boxes.jpg" alt="Main Features" class="page-image" />
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>First Box Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>First Box Description:</label>
|
||||
<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
|
||||
)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.feature_description_1"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Second Box Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Second Box Description:</label>
|
||||
<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
|
||||
)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.feature_description_2"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Third Box Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Third Box Description:</label>
|
||||
<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
|
||||
)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.feature_description_3"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Pricing Content-->
|
||||
<div v-if="config.isSaaS" class="card shadow-card">
|
||||
<FormLabel>Pricing Content</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<div>
|
||||
<div class="inline-wrapper">
|
||||
<div class="switch-label">
|
||||
<label class="input-label"> Show section: </label>
|
||||
</div>
|
||||
<SwitchInput
|
||||
@input="
|
||||
$updateText(
|
||||
'/admin/settings',
|
||||
'section_pricing_content',
|
||||
app.section_pricing_content
|
||||
)
|
||||
"
|
||||
v-model="app.section_pricing_content"
|
||||
class="switch"
|
||||
:state="app.section_pricing_content"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Description:</label>
|
||||
<ValidationProvider
|
||||
tag="div"
|
||||
mode="passive"
|
||||
name="App Description"
|
||||
rules="required"
|
||||
v-slot="{ errors }"
|
||||
>
|
||||
<textarea
|
||||
@input="
|
||||
$updateText('/admin/settings', 'pricing_description', app.pricing_description)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.pricing_description"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Get Started-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>Get Started Content</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<div>
|
||||
<div class="inline-wrapper">
|
||||
<div class="switch-label">
|
||||
<label class="input-label"> Show section: </label>
|
||||
</div>
|
||||
<SwitchInput
|
||||
@input="
|
||||
$updateText('/admin/settings', 'section_get_started', app.section_get_started)
|
||||
"
|
||||
v-model="app.section_get_started"
|
||||
class="switch"
|
||||
:state="app.section_get_started"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
<div class="block-wrapper">
|
||||
<label>Title:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Description:</label>
|
||||
<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
|
||||
)
|
||||
"
|
||||
rows="2"
|
||||
v-model="app.get_started_description"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
></textarea>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Footer-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel>Footer</FormLabel>
|
||||
|
||||
<div class="block-wrapper">
|
||||
<label>Footer content:</label>
|
||||
<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"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
|
||||
</ValidationProvider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageTabGroup>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
||||
import PageTabGroup from '../../../../components/Layout/PageTabGroup'
|
||||
import SelectInput from '../../../../components/Inputs/SelectInput'
|
||||
import SwitchInput from '../../../../components/Inputs/SwitchInput'
|
||||
import ImageInput from '../../../../components/Inputs/ImageInput'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import InfoBox from '../../../../components/UI/Others/InfoBox'
|
||||
import { required } from 'vee-validate/dist/rules'
|
||||
import axios from 'axios'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AppIndex',
|
||||
components: {
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
ValidationObserver,
|
||||
ValidationProvider,
|
||||
PageTabGroup,
|
||||
SwitchInput,
|
||||
SelectInput,
|
||||
ImageInput,
|
||||
ButtonBase,
|
||||
FormLabel,
|
||||
required,
|
||||
PageTab,
|
||||
InfoBox,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
app: undefined,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios
|
||||
.get('/api/admin/settings', {
|
||||
params: {
|
||||
column: 'allow_homepage|footer_content|get_started_description|get_started_title|pricing_description|pricing_title|feature_description_3|feature_title_3|feature_description_2|feature_title_2|feature_description_1|feature_title_1|features_description|features_title|header_description|header_title|section_get_started|section_pricing_content|section_feature_boxes|section_features',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
this.app = {
|
||||
allow_homepage: parseInt(response.data.allow_homepage),
|
||||
section_features: parseInt(response.data.section_features),
|
||||
section_feature_boxes: parseInt(response.data.section_feature_boxes),
|
||||
section_pricing_content: parseInt(response.data.section_pricing_content),
|
||||
section_get_started: parseInt(response.data.section_get_started),
|
||||
header_title: response.data.header_title,
|
||||
header_description: response.data.header_description,
|
||||
features_title: response.data.features_title,
|
||||
features_description: response.data.features_description,
|
||||
feature_title_1: response.data.feature_title_1,
|
||||
feature_description_1: response.data.feature_description_1,
|
||||
feature_title_2: response.data.feature_title_2,
|
||||
feature_description_2: response.data.feature_description_2,
|
||||
feature_title_3: response.data.feature_title_3,
|
||||
feature_description_3: response.data.feature_description_3,
|
||||
pricing_title: response.data.pricing_title,
|
||||
pricing_description: response.data.pricing_description,
|
||||
get_started_title: response.data.get_started_title,
|
||||
get_started_description: response.data.get_started_description,
|
||||
footer_content: response.data.footer_content,
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../../../sass/vuefilemanager/variables';
|
||||
@import '../../../../../sass/vuefilemanager/mixins';
|
||||
@import '../../../../../sass/vuefilemanager/forms';
|
||||
|
||||
.block-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.page-image {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ececec;
|
||||
}
|
||||
</style>
|
||||
481
resources/js/views/Admin/Settings/AppSettingsTabs/Others.vue
Normal file
481
resources/js/views/Admin/Settings/AppSettingsTabs/Others.vue
Normal file
@@ -0,0 +1,481 @@
|
||||
<template>
|
||||
<PageTab :is-loading="isLoading">
|
||||
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('upload_settings') }}
|
||||
</FormLabel>
|
||||
|
||||
<AppInputText
|
||||
:description="$t('admin_settings.others.upload_limit_help')"
|
||||
:title="$t('admin_settings.others.upload_limit')"
|
||||
>
|
||||
<input
|
||||
v-model="app.uploadLimit"
|
||||
:placeholder="$t('admin_settings.others.upload_limit_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
min="0"
|
||||
step="1"
|
||||
type="number"
|
||||
@input="$updateText('/admin/settings', 'upload_limit', app.uploadLimit, true)"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText
|
||||
:description="$t('When you upload file on the server, your file will be sliced into many chunks in this size. Small size of the chunk can prevent many limits you can suffer from your server or provider. Default value is 64MB if is not set.')"
|
||||
:title="$t('File Chunk Size (in MB)')"
|
||||
>
|
||||
<input
|
||||
v-model="app.chunkSize"
|
||||
:placeholder="$t('Type the chunk size in MB')"
|
||||
class="focus-border-theme input-dark"
|
||||
min="0"
|
||||
step="1"
|
||||
type="number"
|
||||
@input="$updateText('/admin/settings', 'chunk_size', app.chunkSize, true)"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText
|
||||
:description="$t('admin_settings.others.mimetypes_blacklist_help')"
|
||||
:is-last="true"
|
||||
:title="$t('admin_settings.others.mimetypes_blacklist')"
|
||||
>
|
||||
<textarea
|
||||
v-model="app.mimetypesBlacklist"
|
||||
:placeholder="$t('admin_settings.others.mimetypes_blacklist_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
rows="2"
|
||||
type="text"
|
||||
@input="$updateText('/admin/settings', 'mimetypes_blacklist', app.mimetypesBlacklist, true)"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<!--Store & Upload-->
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('user_features') }}
|
||||
</FormLabel>
|
||||
|
||||
<!--Available only when is not metered billing-->
|
||||
<div v-if="config.subscriptionType !== 'metered'">
|
||||
<AppInputSwitch
|
||||
:description="$t('admin_settings.others.storage_limit_help')"
|
||||
:title="$t('admin_settings.others.storage_limit')"
|
||||
>
|
||||
<SwitchInput
|
||||
v-model="app.storageLimitation"
|
||||
:state="app.storageLimitation"
|
||||
class="switch"
|
||||
@input="$updateText('/admin/settings', 'storage_limitation', app.storageLimitation)"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputText v-if="app.storageLimitation" :title="$t('admin_settings.others.default_storage')">
|
||||
<input
|
||||
v-model="app.defaultStorage"
|
||||
:placeholder="$t('admin_settings.others.default_storage_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
max="999999999"
|
||||
min="1"
|
||||
type="number"
|
||||
@input="$updateText('/admin/settings', 'default_max_storage_amount', app.defaultStorage)"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<AppInputText :description="$t('zero_for_unlimited_members')" :is-last="true" :title="$t('max_team_members')">
|
||||
<input
|
||||
v-model="app.teamsDefaultMembers"
|
||||
:placeholder="$t('admin_settings.others.default_storage_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
max="999999999"
|
||||
min="1"
|
||||
type="number"
|
||||
@input="$updateText('/admin/settings', 'default_max_team_member', app.teamsDefaultMembers)"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<!-- ReCaptcha -->
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel icon="shield">
|
||||
{{ $t('reCaptcha') }}
|
||||
</FormLabel>
|
||||
|
||||
<AppInputSwitch
|
||||
:description="$t('allow_recaptcha_note')"
|
||||
:is-last="!recaptcha.allowedService"
|
||||
:title="$t('allow_recaptcha')"
|
||||
>
|
||||
<SwitchInput
|
||||
v-model="recaptcha.allowedService"
|
||||
:state="recaptcha.allowedService"
|
||||
class="switch"
|
||||
@input="$updateText('/admin/settings', 'allowed_recaptcha', recaptcha.allowedService)"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<div
|
||||
v-if="config.isRecaptchaConfigured && recaptcha.allowedService"
|
||||
:class="{ 'mb-4': recaptcha.isVisibleCredentialsForm }"
|
||||
class="flex cursor-pointer items-center"
|
||||
@click="recaptcha.isVisibleCredentialsForm = !recaptcha.isVisibleCredentialsForm"
|
||||
>
|
||||
<edit2-icon class="vue-feather text-theme mr-2" size="12" />
|
||||
<b class="text-xs">{{ $t('update_your_credentials') }}</b>
|
||||
</div>
|
||||
|
||||
<!--Set up recaptcha credentials-->
|
||||
<ValidationObserver
|
||||
v-if="(!config.isRecaptchaConfigured || recaptcha.isVisibleCredentialsForm) && recaptcha.allowedService"
|
||||
ref="credentialsForm"
|
||||
v-slot="{ invalid }"
|
||||
class="rounded-xl p-5 shadow-lg"
|
||||
tag="form"
|
||||
@submit.prevent="storeCredentials('recaptcha')"
|
||||
>
|
||||
<FormLabel v-if="!config.isRecaptchaConfigured" icon="shield">
|
||||
{{ $t('configure_your_credentials') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationProvider v-slot="{ errors }" mode="passive" name="Site Key" rules="required" tag="div">
|
||||
<AppInputText :error="errors[0]" :title="$t('Site Key')">
|
||||
<input
|
||||
v-model="recaptcha.credentials.client_id"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
:placeholder="$t('Paste your Site Key here')"
|
||||
class="focus-border-theme input-dark"
|
||||
type="text"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider v-slot="{ errors }" mode="passive" name="Secret key" rules="required" tag="div">
|
||||
<AppInputText :error="errors[0]" :title="$t('Secret Key')">
|
||||
<input
|
||||
v-model="recaptcha.credentials.client_secret"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
:placeholder="$t('Paste your Secret key here')"
|
||||
class="focus-border-theme input-dark"
|
||||
type="text"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ButtonBase
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
button-style="theme"
|
||||
class="w-full"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('store_credentials') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
|
||||
<!--Other Settings-->
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('application') }}
|
||||
</FormLabel>
|
||||
|
||||
<AppInputButton
|
||||
:description="$t('cache_note')"
|
||||
:title="$t('cache')"
|
||||
>
|
||||
<ButtonBase
|
||||
:disabled="isFlushingCache"
|
||||
:loading="isFlushingCache"
|
||||
button-style="theme"
|
||||
class="w-full sm:w-auto"
|
||||
@click.native="flushCache"
|
||||
>
|
||||
{{ $t('clear_cache') }}
|
||||
</ButtonBase>
|
||||
</AppInputButton>
|
||||
|
||||
<AppInputText :title="$t('admin_settings.others.contact_email')">
|
||||
<input
|
||||
v-model="app.contactMail"
|
||||
:placeholder="$t('admin_settings.others.contact_email_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
type="email"
|
||||
@input="$updateText('/admin/settings', 'contact_email', app.contactMail)"
|
||||
/>
|
||||
</AppInputText>
|
||||
|
||||
<AppInputText :is-last="true" :title="$t('admin_settings.others.google_analytics')">
|
||||
<input
|
||||
v-model="app.googleAnalytics"
|
||||
:placeholder="$t('admin_settings.others.google_analytics_plac')"
|
||||
class="focus-border-theme input-dark"
|
||||
type="text"
|
||||
@input="$updateText('/admin/settings', 'google_analytics', app.googleAnalytics, true)"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
|
||||
<!--Upgrade License-->
|
||||
<div v-if="app && !config.isSaaS" class="card shadow-card">
|
||||
<FormLabel icon="trending-up">
|
||||
{{ $t('Upgrade your License') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationObserver
|
||||
ref="upgradeLicense"
|
||||
v-slot="{ invalid }"
|
||||
class="mt-6"
|
||||
tag="form"
|
||||
@submit.prevent="upgradeLicense"
|
||||
>
|
||||
<ValidationProvider
|
||||
v-slot="{ errors }"
|
||||
mode="passive"
|
||||
name="Purchase Code"
|
||||
rules="required"
|
||||
tag="div"
|
||||
>
|
||||
<AppInputText
|
||||
:error="errors[0]"
|
||||
:is-last="true"
|
||||
>
|
||||
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
|
||||
<input
|
||||
v-model="purchaseCode"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
:placeholder="$t('Paste your Purchase code here...')"
|
||||
class="focus-border-theme input-dark"
|
||||
type="text"
|
||||
/>
|
||||
<ButtonBase :loading="isLoadingUpgradingButton" button-style="theme" class="w-full sm:w-auto" type="submit">
|
||||
{{ $t('Upgrade') }}
|
||||
</ButtonBase>
|
||||
</div>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
|
||||
<!-- Subscription -->
|
||||
<div v-if="app && config.isSaaS" class="card shadow-card">
|
||||
<FormLabel icon="credit-card">
|
||||
{{ $t('subscription') }}
|
||||
</FormLabel>
|
||||
|
||||
<AppInputText :description="$t('subscription_type_note')" :is-last="true" :title="$t('subscription_type')">
|
||||
<SelectInput
|
||||
:default="app.subscriptionType"
|
||||
:options="subscriptionTypes"
|
||||
:placeholder="$t('select_subscription_type')"
|
||||
@change="subscriptionTypeChange"
|
||||
/>
|
||||
</AppInputText>
|
||||
</div>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Edit2Icon} from 'vue-feather-icons'
|
||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
||||
import SwitchInput from '../../../../components/Inputs/SwitchInput'
|
||||
import AppInputButton from '../../../../components/Forms/Layouts/AppInputButton'
|
||||
import AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import {required} from 'vee-validate/dist/rules'
|
||||
import {events} from '../../../../bus'
|
||||
import {mapGetters} from 'vuex'
|
||||
import axios from 'axios'
|
||||
import SelectInput from "../../../../components/Inputs/SelectInput";
|
||||
|
||||
export default {
|
||||
name: 'AppOthers',
|
||||
components: {
|
||||
SelectInput,
|
||||
AppInputButton,
|
||||
ValidationObserver,
|
||||
ValidationProvider,
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
SwitchInput,
|
||||
ButtonBase,
|
||||
Edit2Icon,
|
||||
FormLabel,
|
||||
required,
|
||||
PageTab,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['subscriptionTypes', 'config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
isLoadingUpgradingButton: false,
|
||||
isFlushingCache: false,
|
||||
app: undefined,
|
||||
purchaseCode: undefined,
|
||||
recaptcha: {
|
||||
allowedService: false,
|
||||
isVisibleCredentialsForm: false,
|
||||
credentials: {
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async upgradeLicense() {
|
||||
this.isLoadingUpgradingButton = true
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.upgradeLicense.validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
axios.post('/api/admin/upgrade-license', {
|
||||
purchaseCode: this.purchaseCode
|
||||
})
|
||||
.then((response) => {
|
||||
this.$store.dispatch('getLanguageTranslations', this.config.locale)
|
||||
|
||||
this.$store.commit('REPLACE_CONFIG_VALUE', {
|
||||
key: 'isSaaS',
|
||||
value: true,
|
||||
})
|
||||
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('Your license was successfully upgraded'),
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status === 400) {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('Purchase code is invalid or is not Extended License'),
|
||||
})
|
||||
} else {
|
||||
events.$emit('alert:open', {
|
||||
title: this.$t('popup_error.title'),
|
||||
message: this.$t('popup_error.message'),
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoadingUpgradingButton = false
|
||||
})
|
||||
},
|
||||
subscriptionTypeChange(type) {
|
||||
events.$emit('confirm:open', {
|
||||
title: this.$t('subscription_type_change_warn'),
|
||||
message: this.$t('subscription_type_change_warn_description'),
|
||||
action: {
|
||||
type: type,
|
||||
operation: 'change-subscription-type',
|
||||
},
|
||||
})
|
||||
},
|
||||
async storeCredentials(service) {
|
||||
// Validate fields
|
||||
const isValid = await this.$refs.credentialsForm.validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
// Start loading
|
||||
this.isLoading = true
|
||||
|
||||
// Send request to get verify account
|
||||
axios
|
||||
.post('/api/admin/settings/social-service', {
|
||||
client_id: this[service].credentials.client_id,
|
||||
client_secret: this[service].credentials.client_secret,
|
||||
service: service,
|
||||
})
|
||||
.then(() => {
|
||||
// Commit credentials
|
||||
this.$store.commit('SET_SOCIAL_LOGIN_CONFIGURED', service)
|
||||
|
||||
this[service].allowedService = true
|
||||
this[service].isVisibleCredentialsForm = false
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('toaster.credentials_set', {
|
||||
service: service,
|
||||
}),
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status === 500) {
|
||||
this.isError = true
|
||||
this.errorMessage = error.response.data.message
|
||||
}
|
||||
})
|
||||
.finally(() => (this.isLoading = false))
|
||||
},
|
||||
flushCache() {
|
||||
this.isFlushingCache = true
|
||||
|
||||
axios
|
||||
.get('/api/admin/settings/flush-cache')
|
||||
.then(() => {
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: 'Your cache was successfully deleted.',
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.isFlushingCache = false
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.recaptcha.allowedService = this.config.allowedRecaptcha
|
||||
|
||||
axios
|
||||
.get('/api/admin/settings', {
|
||||
params: {
|
||||
column: 'contact_email|google_analytics|default_max_storage_amount|storage_limitation|mimetypes_blacklist|upload_limit|subscriptionType|chunk_size|default_max_team_member',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
this.isLoading = false
|
||||
|
||||
this.app = {
|
||||
contactMail: response.data.contact_email,
|
||||
googleAnalytics: response.data.google_analytics,
|
||||
defaultStorage: response.data.default_max_storage_amount,
|
||||
storageLimitation: parseInt(response.data.storage_limitation),
|
||||
mimetypesBlacklist: response.data.mimetypes_blacklist,
|
||||
uploadLimit: response.data.upload_limit,
|
||||
subscriptionType: response.data.subscriptionType,
|
||||
chunkSize: response.data.chunk_size,
|
||||
teamsDefaultMembers: response.data.default_max_team_member,
|
||||
}
|
||||
})
|
||||
},
|
||||
created() {
|
||||
events.$on('action:confirmed', (data) => {
|
||||
if (data.operation === 'change-subscription-type') {
|
||||
|
||||
// Update database
|
||||
this.$updateText('/admin/settings', 'subscription_type', data.type)
|
||||
|
||||
// Update config
|
||||
this.$store.commit('REPLACE_CONFIG_VALUE', {
|
||||
key: 'subscriptionType',
|
||||
value: data.type,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
events.$off('action:confirmed')
|
||||
},
|
||||
}
|
||||
</script>
|
||||
274
resources/js/views/Admin/Settings/AppSettingsTabs/Server.vue
Normal file
274
resources/js/views/Admin/Settings/AppSettingsTabs/Server.vue
Normal file
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<PageTab v-if="!isLoading">
|
||||
<!--Cron check-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="info">Cron</FormLabel>
|
||||
|
||||
<div class="lg:flex lg:space-y-0 space-y-3 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 pt-1 block leading-normal">
|
||||
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 pt-1 block leading-normal">
|
||||
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>
|
||||
|
||||
<!--Logs-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="list">Latest Server Logs</FormLabel>
|
||||
|
||||
<InfoBox v-if="!logs.length" class="!mb-0">
|
||||
<p v-html="$t('there_is_not_log')"></p>
|
||||
</InfoBox>
|
||||
|
||||
<div
|
||||
v-if="logs.length"
|
||||
v-for="(log, i) in logs"
|
||||
: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">
|
||||
{{ log }}
|
||||
</b>
|
||||
</div>
|
||||
<div @click="downloadLog(log)" class="flex h-8 w-8 items-center justify-center rounded-md bg-light-background transition-colors hover:bg-green-100 dark:bg-2x-dark-foreground cursor-pointer">
|
||||
<DownloadCloudIcon size="15" class="opacity-75" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--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_database_backup')"></p>
|
||||
</InfoBox>
|
||||
|
||||
<InfoBox v-if="backups.length" class="!mb-3">
|
||||
<p v-html="$t('backup_path')"></p>
|
||||
</InfoBox>
|
||||
|
||||
<div
|
||||
v-if="backups.length"
|
||||
v-for="(filename, i) in backups"
|
||||
:key="i"
|
||||
class="md:flex md:space-y-0 space-y-3 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>
|
||||
|
||||
<!--Writable directories-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="database">Writable Permission</FormLabel>
|
||||
|
||||
<div
|
||||
v-for="(isWritable, file, i) in writable"
|
||||
:key="i"
|
||||
class="flex md:space-y-0 space-y-3 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">/{{ file }}</b>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<check-icon v-if="isWritable" size="16" class="vue-feather text-green-600 dark:text-green-600" />
|
||||
<x-icon v-if="!isWritable" size="16" class="vue-feather text-red-600 dark:text-red-600" />
|
||||
|
||||
<span :class="{'text-green-600 dark:text-green-600': isWritable, 'text-red-600 dark:text-red-600': !isWritable}" class="ml-3 text-sm font-bold ">
|
||||
{{ isWritable ? 'Writable' : 'Unwritable'}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--PHP version and ini check-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="info"> PHP Settings </FormLabel>
|
||||
|
||||
<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 pt-1 block leading-normal">
|
||||
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>
|
||||
|
||||
<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 pt-1 block leading-normal">
|
||||
You must 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>
|
||||
|
||||
<!--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="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' : 'You have to install this module' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CheckIcon, XIcon, DownloadCloudIcon } from 'vue-feather-icons'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import InfoBox from '../../../../components/UI/Others/InfoBox'
|
||||
import { mapGetters } from 'vuex'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Server',
|
||||
components: {
|
||||
FormLabel,
|
||||
InfoBox,
|
||||
PageTab,
|
||||
DownloadCloudIcon,
|
||||
CheckIcon,
|
||||
XIcon,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
isCheckedAPI() {
|
||||
return typeof this.apiRunning !== 'undefined'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
ini: undefined,
|
||||
cron: undefined,
|
||||
modules: undefined,
|
||||
phpVersion: undefined,
|
||||
apiRunning: undefined,
|
||||
backups: undefined,
|
||||
logs: undefined,
|
||||
writable: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downloadLog(log) {
|
||||
|
||||
let anchor = document.createElement('a')
|
||||
|
||||
anchor.href = `/admin/log/${log}`
|
||||
anchor.download = log
|
||||
|
||||
document.body.appendChild(anchor)
|
||||
|
||||
anchor.click()
|
||||
}
|
||||
},
|
||||
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
|
||||
this.logs = response.data.logs
|
||||
this.writable = response.data.writable
|
||||
})
|
||||
|
||||
// Ping API
|
||||
axios
|
||||
.get('/api/ping')
|
||||
.then((response) => {
|
||||
this.apiRunning = response.data === 'pong'
|
||||
})
|
||||
.catch(() => {
|
||||
this.apiRunning = false
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
411
resources/js/views/Admin/Settings/AppSettingsTabs/SignInUp.vue
Normal file
411
resources/js/views/Admin/Settings/AppSettingsTabs/SignInUp.vue
Normal file
@@ -0,0 +1,411 @@
|
||||
<template>
|
||||
<PageTab>
|
||||
<!--User Login/Registration-->
|
||||
<div v-if="app" class="card shadow-card">
|
||||
<FormLabel>
|
||||
{{ $t('User Login/Registration') }}
|
||||
</FormLabel>
|
||||
|
||||
<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"
|
||||
class="switch"
|
||||
:state="app.userRegistration"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputSwitch
|
||||
:title="$t('require_email_verification')"
|
||||
:description="$t('require_email_verification_note')"
|
||||
:is-last="true"
|
||||
>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'user_verification', app.userVerification)"
|
||||
v-model="app.userVerification"
|
||||
class="switch"
|
||||
:state="app.userVerification"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
</div>
|
||||
|
||||
<!--Facebook Social Authentication-->
|
||||
<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"
|
||||
>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'allowed_facebook_login', facebook.allowedService)"
|
||||
v-model="facebook.allowedService"
|
||||
class="switch"
|
||||
:state="facebook.allowedService"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputText
|
||||
v-if="facebook.allowedService"
|
||||
:title="$t('Your Callback URL')"
|
||||
:description="$t('Please copy your url and paste it to the service callback URL.')"
|
||||
>
|
||||
<CopyInput size="small" :str="getCallbackEndpoint('facebook')" />
|
||||
</AppInputText>
|
||||
|
||||
<div
|
||||
v-if="config.isFacebookLoginConfigured && facebook.allowedService"
|
||||
@click="facebook.isVisibleCredentialsForm = !facebook.isVisibleCredentialsForm"
|
||||
class="flex cursor-pointer items-center"
|
||||
:class="{ 'mb-4': facebook.isVisibleCredentialsForm }"
|
||||
>
|
||||
<edit2-icon size="12" class="vue-feather text-theme mr-2" />
|
||||
<b class="text-xs">{{ $t('update_your_credentials') }}</b>
|
||||
</div>
|
||||
|
||||
<!--Set up facebook credentials-->
|
||||
<ValidationObserver
|
||||
v-if="
|
||||
(!config.isFacebookLoginConfigured || facebook.isVisibleCredentialsForm) && facebook.allowedService
|
||||
"
|
||||
@submit.prevent="storeCredentials('facebook')"
|
||||
ref="facebook"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="rounded-xl p-5 shadow-lg"
|
||||
>
|
||||
<FormLabel v-if="!config.isFacebookLoginConfigured" icon="shield">
|
||||
{{ $t('Configure Credentials') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client ID" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client ID')" :error="errors[0]">
|
||||
<input
|
||||
v-model="facebook.credentials.client_id"
|
||||
:placeholder="$t('Paste your Client ID here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client Secret" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client Secret')" :error="errors[0]">
|
||||
<input
|
||||
v-model="facebook.credentials.client_secret"
|
||||
:placeholder="$t('Paste your Client Secret here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ButtonBase
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
button-style="theme"
|
||||
type="submit"
|
||||
class="w-full"
|
||||
>
|
||||
{{ $t('store_credentials') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
|
||||
<!--Google Social Authentication-->
|
||||
<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"
|
||||
>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'allowed_google_login', google.allowedService)"
|
||||
v-model="google.allowedService"
|
||||
class="switch"
|
||||
:state="google.allowedService"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputText
|
||||
v-if="google.allowedService"
|
||||
:title="$t('Your Callback URL')"
|
||||
:description="$t('Please copy your url and paste it to the service callback URL.')"
|
||||
>
|
||||
<CopyInput size="small" :str="getCallbackEndpoint('google')" />
|
||||
</AppInputText>
|
||||
|
||||
<div
|
||||
v-if="config.isGoogleLoginConfigured && google.allowedService"
|
||||
@click="google.isVisibleCredentialsForm = !google.isVisibleCredentialsForm"
|
||||
class="flex cursor-pointer items-center"
|
||||
:class="{ 'mb-4': google.isVisibleCredentialsForm }"
|
||||
>
|
||||
<edit2-icon size="12" class="vue-feather text-theme mr-2" />
|
||||
<b class="text-xs">{{ $t('update_your_credentials') }}</b>
|
||||
</div>
|
||||
|
||||
<!--Set up Google credentials-->
|
||||
<ValidationObserver
|
||||
v-if="(!config.isGoogleLoginConfigured || google.isVisibleCredentialsForm) && google.allowedService"
|
||||
@submit.prevent="storeCredentials('google')"
|
||||
ref="google"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="rounded-xl p-5 shadow-lg"
|
||||
>
|
||||
<FormLabel v-if="!config.isGoogleLoginConfigured" icon="shield">
|
||||
{{ $t('Configure Credentials') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client ID" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client ID')" :error="errors[0]">
|
||||
<input
|
||||
v-model="google.credentials.client_id"
|
||||
:placeholder="$t('Paste your Client ID here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client Secret" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client Secret')" :error="errors[0]">
|
||||
<input
|
||||
v-model="google.credentials.client_secret"
|
||||
:placeholder="$t('Paste your Client Secret here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ButtonBase
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
button-style="theme"
|
||||
type="submit"
|
||||
class="w-full"
|
||||
>
|
||||
{{ $t('store_credentials') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
|
||||
<!--Github Social Authentication-->
|
||||
<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"
|
||||
>
|
||||
<SwitchInput
|
||||
@input="$updateText('/admin/settings', 'allowed_github_login', github.allowedService)"
|
||||
v-model="github.allowedService"
|
||||
class="switch"
|
||||
:state="github.allowedService"
|
||||
/>
|
||||
</AppInputSwitch>
|
||||
|
||||
<AppInputText
|
||||
v-if="github.allowedService"
|
||||
:title="$t('Your Callback URL')"
|
||||
:description="$t('Please copy your url and paste it to the service callback URL.')"
|
||||
>
|
||||
<CopyInput size="small" :str="getCallbackEndpoint('github')" />
|
||||
</AppInputText>
|
||||
|
||||
<div
|
||||
v-if="config.isGithubLoginConfigured && github.allowedService"
|
||||
@click="github.isVisibleCredentialsForm = !github.isVisibleCredentialsForm"
|
||||
class="flex cursor-pointer items-center"
|
||||
:class="{ 'mb-4': github.isVisibleCredentialsForm }"
|
||||
>
|
||||
<edit2-icon size="12" class="vue-feather text-theme mr-2" />
|
||||
<b class="text-xs">{{ $t('update_your_credentials') }}</b>
|
||||
</div>
|
||||
|
||||
<!--Set up github credentials-->
|
||||
<ValidationObserver
|
||||
v-if="(!config.isGithubLoginConfigured || github.isVisibleCredentialsForm) && github.allowedService"
|
||||
@submit.prevent="storeCredentials('github')"
|
||||
ref="github"
|
||||
v-slot="{ invalid }"
|
||||
tag="form"
|
||||
class="rounded-xl p-5 shadow-lg"
|
||||
>
|
||||
<FormLabel v-if="!config.isGithubLoginConfigured" icon="shield">
|
||||
{{ $t('Configure Credentials') }}
|
||||
</FormLabel>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client ID" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client ID')" :error="errors[0]">
|
||||
<input
|
||||
v-model="github.credentials.client_id"
|
||||
:placeholder="$t('Paste your Client ID here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ValidationProvider tag="div" mode="passive" name="Client Secret" rules="required" v-slot="{ errors }">
|
||||
<AppInputText :title="$t('Client Secret')" :error="errors[0]">
|
||||
<input
|
||||
v-model="github.credentials.client_secret"
|
||||
:placeholder="$t('Paste your Client Secret here')"
|
||||
type="text"
|
||||
:class="{ '!border-rose-600': errors[0] }"
|
||||
class="focus-border-theme input-dark"
|
||||
/>
|
||||
</AppInputText>
|
||||
</ValidationProvider>
|
||||
|
||||
<ButtonBase
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
button-style="theme"
|
||||
type="submit"
|
||||
class="w-full"
|
||||
>
|
||||
{{ $t('store_credentials') }}
|
||||
</ButtonBase>
|
||||
</ValidationObserver>
|
||||
</div>
|
||||
</PageTab>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Edit2Icon } from 'vue-feather-icons'
|
||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
||||
import SwitchInput from '../../../../components/Inputs/SwitchInput'
|
||||
import AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
||||
import CopyInput from '../../../../components/Inputs/CopyInput'
|
||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
||||
import PageTab from '../../../../components/Layout/PageTab'
|
||||
import { required } from 'vee-validate/dist/rules'
|
||||
import { events } from '../../../../bus'
|
||||
import { mapGetters } from 'vuex'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'SignInUp',
|
||||
components: {
|
||||
CopyInput,
|
||||
ValidationObserver,
|
||||
ValidationProvider,
|
||||
AppInputSwitch,
|
||||
AppInputText,
|
||||
SwitchInput,
|
||||
ButtonBase,
|
||||
Edit2Icon,
|
||||
FormLabel,
|
||||
required,
|
||||
PageTab,
|
||||
events,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['config']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
app: {
|
||||
userRegistration: undefined,
|
||||
userVerification: undefined,
|
||||
},
|
||||
facebook: {
|
||||
allowedService: false,
|
||||
isVisibleCredentialsForm: false,
|
||||
credentials: {
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
},
|
||||
},
|
||||
google: {
|
||||
allowedService: false,
|
||||
isVisibleCredentialsForm: false,
|
||||
credentials: {
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
},
|
||||
},
|
||||
github: {
|
||||
allowedService: false,
|
||||
isVisibleCredentialsForm: false,
|
||||
credentials: {
|
||||
key: undefined,
|
||||
secret: undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCallbackEndpoint(service) {
|
||||
return `${this.config.host}/socialite/${service}/callback`
|
||||
},
|
||||
async storeCredentials(service) {
|
||||
// Validate fields
|
||||
const isValid = await this.$refs[service].validate()
|
||||
|
||||
if (!isValid) return
|
||||
|
||||
// Start loading
|
||||
this.isLoading = true
|
||||
|
||||
// Send request to get verify account
|
||||
axios
|
||||
.post('/api/admin/settings/social-service', {
|
||||
client_id: this[service].credentials.client_id,
|
||||
client_secret: this[service].credentials.client_secret,
|
||||
service: service,
|
||||
})
|
||||
.then(() => {
|
||||
// Commit credentials
|
||||
this.$store.commit('SET_SOCIAL_LOGIN_CONFIGURED', service)
|
||||
|
||||
this[service].allowedService = true
|
||||
this[service].isVisibleCredentialsForm = false
|
||||
|
||||
// Show toaster
|
||||
events.$emit('toaster', {
|
||||
type: 'success',
|
||||
message: this.$t('toaster.credentials_set', {
|
||||
service: service,
|
||||
}),
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.response.status === 500) {
|
||||
this.isError = true
|
||||
this.errorMessage = error.response.data.message
|
||||
}
|
||||
})
|
||||
.finally(() => (this.isLoading = false))
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.facebook.allowedService = this.config.allowedFacebookLogin
|
||||
this.google.allowedService = this.config.allowedGoogleLogin
|
||||
this.github.allowedService = this.config.allowedGithubLogin
|
||||
|
||||
this.app.userRegistration = this.config.userRegistration
|
||||
this.app.userVerification = this.config.userVerification
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user