mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-29 03:10:51 +00:00
deleted frontend code
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
APP_NAME=Laravel
|
APP_NAME=Laravel
|
||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=base64:yQs3FfCdjY2KGHl1JpLP7L8LLVq8RNOIu/sygWVXUBM=
|
APP_KEY=base64:YrsSyfNE+I3JPF+zZZTddgxb5YZN6xggPFn6dlpkQlI=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
APP_DEMO=false
|
APP_DEMO=false
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'version' => '2.1.0.1',
|
'version' => '1.0.0',
|
||||||
|
|
||||||
'is_demo' => env('APP_DEMO', false),
|
'is_demo' => env('APP_DEMO', false),
|
||||||
|
|
||||||
@@ -63,10 +63,6 @@ return [
|
|||||||
|
|
||||||
// The update versions which need to run upgrade process
|
// The update versions which need to run upgrade process
|
||||||
'updates' => [
|
'updates' => [
|
||||||
'2_0_10',
|
|
||||||
'2_0_13',
|
|
||||||
'2_0_14',
|
|
||||||
'2_0_16',
|
|
||||||
'2_1_1',
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
+70
-70
@@ -1,75 +1,75 @@
|
|||||||
{
|
{
|
||||||
"/js/main.js": "/js/main.js",
|
"/js/main.js": "/js/main.js",
|
||||||
"/chunks/request.js": "/chunks/request.js?id=a5136967a1882fd5",
|
"/chunks/request.js": "/chunks/request.js?id=6b84fefd11208314",
|
||||||
"/chunks/request-upload.js": "/chunks/request-upload.js?id=1310f3005ea0d465",
|
"/chunks/request-upload.js": "/chunks/request-upload.js?id=a57ea65eceba1b87",
|
||||||
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=3c2fc454c3fce8d2",
|
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=19a0784e59d768ec",
|
||||||
"/chunks/status-check.js": "/chunks/status-check.js?id=42f9d84c64fb105c",
|
"/chunks/status-check.js": "/chunks/status-check.js?id=9239a586761b912d",
|
||||||
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=f858e6cd4e9e59f6",
|
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=ba76b9a8adbfdc0b",
|
||||||
"/chunks/database.js": "/chunks/database.js?id=c36d1bfafcf1b15e",
|
"/chunks/database.js": "/chunks/database.js?id=5113b0d4284f764f",
|
||||||
"/chunks/environment.js": "/chunks/environment.js?id=1cf279f28dcb597f",
|
"/chunks/environment.js": "/chunks/environment.js?id=17210c2b24cf3f13",
|
||||||
"/chunks/app-setup.js": "/chunks/app-setup.js?id=2efed338e56fccab",
|
"/chunks/app-setup.js": "/chunks/app-setup.js?id=cbe7bfed06400736",
|
||||||
"/chunks/admin-account.js": "/chunks/admin-account.js?id=e8c8b0f2c83e8736",
|
"/chunks/admin-account.js": "/chunks/admin-account.js?id=78d257775f5fc485",
|
||||||
"/chunks/shared.js": "/chunks/shared.js?id=adb0dccc00e457ff",
|
"/chunks/shared.js": "/chunks/shared.js?id=17463f7ccbd82a29",
|
||||||
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=e712d9ff304ae80f",
|
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=e418615ad9b55450",
|
||||||
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=75925e92aa837216",
|
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=b64f21aef7584446",
|
||||||
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=6f17bfddfaee9d15",
|
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=b5519d193bce2339",
|
||||||
"/chunks/not-found.js": "/chunks/not-found.js?id=bd6f4028c9d5f194",
|
"/chunks/not-found.js": "/chunks/not-found.js?id=d31bd699138cf828",
|
||||||
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=f1cbdc3b62c510de",
|
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=26798085f527d955",
|
||||||
"/chunks/admin.js": "/chunks/admin.js?id=1560aebbd0a1ec39",
|
"/chunks/admin.js": "/chunks/admin.js?id=517fdb275cc1fa5b",
|
||||||
"/chunks/dashboard.js": "/chunks/dashboard.js?id=50f9ca92c1fb1056",
|
"/chunks/dashboard.js": "/chunks/dashboard.js?id=380940bb78feba70",
|
||||||
"/chunks/invoices.js": "/chunks/invoices.js?id=2ad8029efb381c2a",
|
"/chunks/invoices.js": "/chunks/invoices.js?id=799928609f57ca10",
|
||||||
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=e081b6ee62f749d1",
|
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=a0c4f59d0ec4aee0",
|
||||||
"/chunks/pages.js": "/chunks/pages.js?id=e4dffd90dbd041de",
|
"/chunks/pages.js": "/chunks/pages.js?id=d385a3969fd87fcd",
|
||||||
"/chunks/page-edit.js": "/chunks/page-edit.js?id=9b21bfa01a9a4cc2",
|
"/chunks/page-edit.js": "/chunks/page-edit.js?id=0bdc8a5935fd2197",
|
||||||
"/chunks/plans.js": "/chunks/plans.js?id=65482bb311114624",
|
"/chunks/plans.js": "/chunks/plans.js?id=4bfe7fedc1cb720d",
|
||||||
"/chunks/users.js": "/chunks/users.js?id=46520527325c005f",
|
"/chunks/users.js": "/chunks/users.js?id=e1dc04b0e402dd27",
|
||||||
"/chunks/user-create.js": "/chunks/user-create.js?id=4210ecb12e1bc179",
|
"/chunks/user-create.js": "/chunks/user-create.js?id=40254ae98547761e",
|
||||||
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=aa1f1f24b8ed53ec",
|
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=18f9d1ab17996507",
|
||||||
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=28dd455e83a6ad0a",
|
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=40e9f287b5258a40",
|
||||||
"/chunks/user.js": "/chunks/user.js?id=8f1f08244520be73",
|
"/chunks/user.js": "/chunks/user.js?id=052364b014015a4d",
|
||||||
"/chunks/user-detail.js": "/chunks/user-detail.js?id=d22afa05b9a3757f",
|
"/chunks/user-detail.js": "/chunks/user-detail.js?id=fc5475489f0cec6a",
|
||||||
"/chunks/user-storage.js": "/chunks/user-storage.js?id=4e5dba60505fbd72",
|
"/chunks/user-storage.js": "/chunks/user-storage.js?id=a9e1ccc028fc989d",
|
||||||
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=66ae479b7881829a",
|
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=797d77ff2b1c08cc",
|
||||||
"/chunks/user-password.js": "/chunks/user-password.js?id=2f6feb7b2fe85993",
|
"/chunks/user-password.js": "/chunks/user-password.js?id=900ae71c3d4199ea",
|
||||||
"/chunks/user-delete.js": "/chunks/user-delete.js?id=556ee0e95b61526c",
|
"/chunks/user-delete.js": "/chunks/user-delete.js?id=a3091617207684e5",
|
||||||
"/chunks/plan.js": "/chunks/plan.js?id=64c2482191d0264f",
|
"/chunks/plan.js": "/chunks/plan.js?id=3e7b0b34c2247e6c",
|
||||||
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=b171c0d1b134f7b4",
|
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=36d925def6a82cb2",
|
||||||
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=2cd26776c594e78f",
|
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=df990f928a77c355",
|
||||||
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=c70ebcff48b7f1fd",
|
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=630deb1fc4e17ed9",
|
||||||
"/chunks/payments.js": "/chunks/payments.js?id=995c8bd6ac4c5770",
|
"/chunks/payments.js": "/chunks/payments.js?id=d59a2a18b680d65c",
|
||||||
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=03f371c8b1ce81da",
|
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=27d6c1b58dbd1e6c",
|
||||||
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=5f97f1ac47be9927",
|
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=450162f937b7b2fd",
|
||||||
"/chunks/app-settings.js": "/chunks/app-settings.js?id=6fd0fd89ccfdd290",
|
"/chunks/app-settings.js": "/chunks/app-settings.js?id=4ff5c1e5bbb0aed8",
|
||||||
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=0eb829fd80113549",
|
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=8ba3feb2cc81a2c3",
|
||||||
"/chunks/app-index.js": "/chunks/app-index.js?id=22b024b841518628",
|
"/chunks/app-index.js": "/chunks/app-index.js?id=0c50096e8de09288",
|
||||||
"/chunks/app-environment.js": "/chunks/app-environment.js?id=4be35ec974ce1291",
|
"/chunks/app-environment.js": "/chunks/app-environment.js?id=d5fbb0ea9249ce7f",
|
||||||
"/chunks/app-others.js": "/chunks/app-others.js?id=44647e5dacec3146",
|
"/chunks/app-others.js": "/chunks/app-others.js?id=82cec4d0d2fab089",
|
||||||
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=9c3408a70459090e",
|
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=f79027ce1f1f4c4b",
|
||||||
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=abe3fd03fc6aa6b5",
|
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=c7e7dc2975317062",
|
||||||
"/chunks/app-server.js": "/chunks/app-server.js?id=5051f8a08707ed36",
|
"/chunks/app-server.js": "/chunks/app-server.js?id=ff66d34e90ff98a0",
|
||||||
"/chunks/app-language.js": "/chunks/app-language.js?id=0d67a5ffe354681b",
|
"/chunks/app-language.js": "/chunks/app-language.js?id=041070825d222906",
|
||||||
"/chunks/homepage.js": "/chunks/homepage.js?id=14c7ce5244e7ff7c",
|
"/chunks/homepage.js": "/chunks/homepage.js?id=73f93c1932ffc158",
|
||||||
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=8f0e89961cc767ef",
|
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=9553d7a2912cb901",
|
||||||
"/chunks/contact-us.js": "/chunks/contact-us.js?id=e6902071177114a9",
|
"/chunks/contact-us.js": "/chunks/contact-us.js?id=ea99d85aa3500595",
|
||||||
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=5ac8ec655bcb572a",
|
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=c26cb144101e7c79",
|
||||||
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=2086cf5e64520632",
|
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=170d814982e1c475",
|
||||||
"/chunks/sign-in.js": "/chunks/sign-in.js?id=25ccff57d079640f",
|
"/chunks/sign-in.js": "/chunks/sign-in.js?id=f87a4dd837cbe607",
|
||||||
"/chunks/sign-up.js": "/chunks/sign-up.js?id=d19570e7be1a667b",
|
"/chunks/sign-up.js": "/chunks/sign-up.js?id=3d7559511768cd0e",
|
||||||
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=b3286fb8f390bbd4",
|
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=27cda9364b6593d8",
|
||||||
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=ba2e1007acbe3e19",
|
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=2f0401ee2fc148c4",
|
||||||
"/chunks/settings.js": "/chunks/settings.js?id=78234db26addeb1a",
|
"/chunks/settings.js": "/chunks/settings.js?id=e40960367c00597f",
|
||||||
"/chunks/profile.js": "/chunks/profile.js?id=9742ec84ddcbdea6",
|
"/chunks/profile.js": "/chunks/profile.js?id=5f1e6f1817817716",
|
||||||
"/chunks/settings-password.js": "/chunks/settings-password.js?id=3aecc301e7a35dcb",
|
"/chunks/settings-password.js": "/chunks/settings-password.js?id=d00bf503d8126dc4",
|
||||||
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=4e4ff51f12ad9bc3",
|
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=092e324aad54656b",
|
||||||
"/chunks/billing.js": "/chunks/billing.js?id=5bbebe710852bcb5",
|
"/chunks/billing.js": "/chunks/billing.js?id=115c25478cee576d",
|
||||||
"/chunks/platform.js": "/chunks/platform.js?id=649383244cab95d7",
|
"/chunks/platform.js": "/chunks/platform.js?id=2add0f27d00ef117",
|
||||||
"/chunks/files.js": "/chunks/files.js?id=8a50e16ec0baeff0",
|
"/chunks/files.js": "/chunks/files.js?id=bee14c7818d47129",
|
||||||
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=4de7ebe40af1bf04",
|
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=91632ef82ff2959c",
|
||||||
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=ecc811b50dcce19d",
|
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=3bf3fb855fd65a7d",
|
||||||
"/chunks/trash.js": "/chunks/trash.js?id=03f841299c5ef282",
|
"/chunks/trash.js": "/chunks/trash.js?id=55241ed4bb60c8dd",
|
||||||
"/chunks/team-folders.js": "/chunks/team-folders.js?id=a12cb31542faaed0",
|
"/chunks/team-folders.js": "/chunks/team-folders.js?id=8c6e3f91c2bd3bdb",
|
||||||
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=a9679bfb8e294251",
|
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=470178ec3b181fce",
|
||||||
"/chunks/invitation.js": "/chunks/invitation.js?id=26703e583c07a989",
|
"/chunks/invitation.js": "/chunks/invitation.js?id=424b2783d9785a09",
|
||||||
"/css/tailwind.css": "/css/tailwind.css",
|
"/css/tailwind.css": "/css/tailwind.css",
|
||||||
"/css/app.css": "/css/app.css"
|
"/css/app.css": "/css/app.css"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,10 @@
|
|||||||
<Alert />
|
<Alert />
|
||||||
<ToasterWrapper />
|
<ToasterWrapper />
|
||||||
<CookieDisclaimer />
|
<CookieDisclaimer />
|
||||||
<RemoteUploadProgress />
|
|
||||||
|
|
||||||
<!--Show spinner before translations is loaded-->
|
<!--Show spinner before translations is loaded-->
|
||||||
<Spinner v-if="!isLoaded" />
|
<Spinner v-if="!isLoaded" />
|
||||||
|
|
||||||
<!--Show warning bar when user functionality is restricted-->
|
|
||||||
<RestrictionWarningBar />
|
|
||||||
|
|
||||||
<div :class="{'lg:flex': isSidebarNavigation}">
|
<div :class="{'lg:flex': isSidebarNavigation}">
|
||||||
<SidebarNavigation v-if="isSidebarNavigation" />
|
<SidebarNavigation v-if="isSidebarNavigation" />
|
||||||
<router-view v-if="isLoaded" />
|
<router-view v-if="isLoaded" />
|
||||||
@@ -23,8 +19,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import RestrictionWarningBar from './components/Subscription/RestrictionWarningBar'
|
|
||||||
import RemoteUploadProgress from "./components/RemoteUpload/RemoteUploadProgress"
|
|
||||||
import ToasterWrapper from './components/Toaster/ToasterNotifications'
|
import ToasterWrapper from './components/Toaster/ToasterNotifications'
|
||||||
import SidebarNavigation from "./components/Sidebar/SidebarNavigation"
|
import SidebarNavigation from "./components/Sidebar/SidebarNavigation"
|
||||||
import CookieDisclaimer from './components/UI/Others/CookieDisclaimer'
|
import CookieDisclaimer from './components/UI/Others/CookieDisclaimer'
|
||||||
@@ -37,8 +31,6 @@ import { events } from './bus'
|
|||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
components: {
|
components: {
|
||||||
RestrictionWarningBar,
|
|
||||||
RemoteUploadProgress,
|
|
||||||
SidebarNavigation,
|
SidebarNavigation,
|
||||||
CookieDisclaimer,
|
CookieDisclaimer,
|
||||||
ToasterWrapper,
|
ToasterWrapper,
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
<template>
|
|
||||||
<DatatableWrapper api="/api/admin/dashboard/transactions" :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">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.note }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<div v-if="row.data.relationships.user" class="flex items-center">
|
|
||||||
<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"
|
|
||||||
>
|
|
||||||
{{ row.data.relationships.user.data.attributes.name }}
|
|
||||||
</b>
|
|
||||||
<span class="block text-xs text-gray-600 dark:text-gray-500">
|
|
||||||
{{ row.data.relationships.user.data.attributes.email }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span v-if="!row.data.relationships.user" class="text-xs font-bold text-gray-500">
|
|
||||||
{{ $t('user_was_deleted') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<ColorLabel
|
|
||||||
v-if="config.subscriptionType === 'fixed'"
|
|
||||||
:color="$getTransactionStatusColor(row.data.attributes.status)"
|
|
||||||
>
|
|
||||||
{{ $t(row.data.attributes.status) }}
|
|
||||||
</ColorLabel>
|
|
||||||
<ColorLabel
|
|
||||||
v-if="config.subscriptionType === 'metered'"
|
|
||||||
:color="$getTransactionTypeColor(row.data.attributes.type)"
|
|
||||||
>
|
|
||||||
{{ $t(row.data.attributes.type) }}
|
|
||||||
</ColorLabel>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold" :class="$getTransactionTypeTextColor(row.data.attributes.type)">
|
|
||||||
{{ $getTransactionMark(row.data.attributes.type) + row.data.attributes.price }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.created_at }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="pl-3 md:pl-1">
|
|
||||||
<div class="w-28">
|
|
||||||
<img
|
|
||||||
class="inline-block max-h-5"
|
|
||||||
:src="$getPaymentLogo(row.data.attributes.driver)"
|
|
||||||
:alt="row.data.attributes.driver"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--Empty page-->
|
|
||||||
<template v-slot:empty-page>
|
|
||||||
<InfoBox style="margin-bottom: 0">
|
|
||||||
<p>{{ $t("not_any_transactions") }}</p>
|
|
||||||
</InfoBox>
|
|
||||||
</template>
|
|
||||||
</DatatableWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import DatatableCellImage from '../../UI/Table/DatatableCellImage'
|
|
||||||
import DatatableWrapper from '../../UI/Table/DatatableWrapper'
|
|
||||||
import ColorLabel from '../../UI/Labels/ColorLabel'
|
|
||||||
import { Trash2Icon, Edit2Icon } from 'vue-feather-icons'
|
|
||||||
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
|
||||||
import InfoBox from '../../UI/Others/InfoBox'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'WidgetLatestTransactions',
|
|
||||||
props: ['icon', 'title'],
|
|
||||||
components: {
|
|
||||||
DatatableCellImage,
|
|
||||||
DatatableWrapper,
|
|
||||||
MemberAvatar,
|
|
||||||
Trash2Icon,
|
|
||||||
ColorLabel,
|
|
||||||
Edit2Icon,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config']),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
label: this.$t('note'),
|
|
||||||
field: 'note',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('user'),
|
|
||||||
field: 'user_id',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('status'),
|
|
||||||
field: 'status',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('total'),
|
|
||||||
field: 'amount',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('payed_at'),
|
|
||||||
field: 'created_at',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('service'),
|
|
||||||
field: 'driver',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -144,8 +144,6 @@ export default {
|
|||||||
Trash: this.navigation[0].folders,
|
Trash: this.navigation[0].folders,
|
||||||
Public: this.navigation[0].folders,
|
Public: this.navigation[0].folders,
|
||||||
Files: this.navigation[0].folders,
|
Files: this.navigation[0].folders,
|
||||||
TeamFolders: this.navigation[1].folders,
|
|
||||||
SharedWithMe: this.navigation[2].folders,
|
|
||||||
}[this.$route.name]
|
}[this.$route.name]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -180,28 +178,11 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
groupCollapsable: true,
|
|
||||||
groupTitle: this.$t('collaboration'),
|
|
||||||
groupLinks: [
|
|
||||||
{
|
|
||||||
icon: 'users',
|
|
||||||
route: 'TeamFolders',
|
|
||||||
title: this.$t('team_folders'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'user-check',
|
|
||||||
route: 'SharedWithMe',
|
|
||||||
title: this.$t('shared_with_me'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
resetData() {
|
resetData() {
|
||||||
this.$store.commit('SET_CURRENT_TEAM_FOLDER', null)
|
|
||||||
this.$store.commit('CLIPBOARD_CLEAR')
|
this.$store.commit('CLIPBOARD_CLEAR')
|
||||||
},
|
},
|
||||||
goToFolder(folder) {
|
goToFolder(folder) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
@click.native="$shareFileOrFolder(currentFile)"
|
@click.native="$shareFileOrFolder(currentFile)"
|
||||||
:title="sharingTitle"
|
:title="sharingTitle"
|
||||||
icon="share"
|
icon="share"
|
||||||
v-if="!$isThisRoute($route, ['Public', 'RequestUpload', 'SharedWithMe'])"
|
v-if="!$isThisRoute($route, ['Public'])"
|
||||||
/>
|
/>
|
||||||
<Option
|
<Option
|
||||||
@click.native="$deleteFileOrFolder(currentFile)"
|
@click.native="$deleteFileOrFolder(currentFile)"
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
class="menu-option"
|
class="menu-option"
|
||||||
/>
|
/>
|
||||||
</OptionGroup>
|
</OptionGroup>
|
||||||
<OptionGroup v-if="!$isThisRoute($route, ['RequestUpload'])">
|
<OptionGroup>
|
||||||
<Option @click.native="downloadItem" :title="$t('download')" icon="download" />
|
<Option @click.native="downloadItem" :title="$t('download')" icon="download" />
|
||||||
</OptionGroup>
|
</OptionGroup>
|
||||||
</PopoverItem>
|
</PopoverItem>
|
||||||
@@ -79,7 +79,6 @@
|
|||||||
|
|
||||||
<div class="ml-5">
|
<div class="ml-5">
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
v-if="!$isThisRoute($route, ['RequestUpload'])"
|
|
||||||
@click.native="downloadItem"
|
@click.native="downloadItem"
|
||||||
source="download"
|
source="download"
|
||||||
:action="$t('download_item')"
|
:action="$t('download_item')"
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<FormLabel icon="wifi">
|
|
||||||
{{ $te('broadcasting') ? $t('broadcasting') : 'Broadcasting' }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<ValidationProvider
|
|
||||||
tag="div"
|
|
||||||
mode="passive"
|
|
||||||
name="Broadcast Driver"
|
|
||||||
rules="required"
|
|
||||||
v-slot="{ errors }"
|
|
||||||
>
|
|
||||||
<AppInputText
|
|
||||||
title="Broadcast Driver"
|
|
||||||
:error="errors[0]"
|
|
||||||
:is-last="broadcast.driver === 'none' || broadcast.driver === undefined"
|
|
||||||
>
|
|
||||||
<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="TLS" v-slot="{ errors }">
|
|
||||||
<AppInputSwitch
|
|
||||||
title="Required TLS Connection"
|
|
||||||
description="When enabled, you must have installed ssl certificate on your server host"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<SwitchInput v-model="broadcast.tls" :state="broadcast.tls" />
|
|
||||||
</AppInputSwitch>
|
|
||||||
</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]" :is-last="true">
|
|
||||||
<SelectInput
|
|
||||||
v-model="broadcast.cluster"
|
|
||||||
:options="pusherClusters"
|
|
||||||
placeholder="Select your cluster"
|
|
||||||
:isError="errors[0]"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {ValidationObserver, ValidationProvider} from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import SelectInput from '../Inputs/SelectInput'
|
|
||||||
import AppInputText from './Layouts/AppInputText'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import AppInputSwitch from "./Layouts/AppInputSwitch";
|
|
||||||
import SwitchInput from "../Inputs/SwitchInput";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'BroadcastSetup',
|
|
||||||
components: {
|
|
||||||
SwitchInput,
|
|
||||||
AppInputSwitch,
|
|
||||||
ValidationObserver,
|
|
||||||
ValidationProvider,
|
|
||||||
AppInputText,
|
|
||||||
SelectInput,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
broadcast: {
|
|
||||||
handler(newValue, oldValue) {
|
|
||||||
this.$emit('input', newValue)
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
broadcast: {
|
|
||||||
driver: undefined,
|
|
||||||
id: undefined,
|
|
||||||
key: undefined,
|
|
||||||
secret: undefined,
|
|
||||||
cluster: undefined,
|
|
||||||
tls: true,
|
|
||||||
},
|
|
||||||
broadcastDrivers: [
|
|
||||||
{
|
|
||||||
label: 'Pusher',
|
|
||||||
value: 'pusher',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'VueFileManager',
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,19 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<VueFolderIcon v-if="!item.data.attributes.isTeamFolder" />
|
<VueFolderIcon v-if="!item.data.attributes.isTeamFolder" />
|
||||||
<VueFolderTeamIcon v-if="item.data.attributes.isTeamFolder" style="width: 53px; height: 52px" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import VueFolderTeamIcon from './VueFolderTeamIcon'
|
|
||||||
import VueFolderIcon from './VueFolderIcon'
|
import VueFolderIcon from './VueFolderIcon'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FolderIcon',
|
name: 'FolderIcon',
|
||||||
props: ['item'],
|
props: ['item'],
|
||||||
components: {
|
components: {
|
||||||
VueFolderTeamIcon,
|
|
||||||
VueFolderIcon,
|
VueFolderIcon,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
<template>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
class="google-icon"
|
|
||||||
width="22px"
|
|
||||||
height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<path d="M11.0024865,21.9999898 L10.5295935,21.9999898 C4.79941267,21.6719961 0.249801856,17.0571507 0.00497307141,11.324452 C-0.108950196,7.53234629 1.74080914,3.949454 4.89870278,1.84553974 C8.05659642,-0.258374523 12.0763823,-0.586006523 15.5334621,0.978755386 C15.93211,1.16635174 16.2376499,1.50750632 16.3802706,1.9242707 C16.5207552,2.3463989 16.480972,2.80775257 16.2702955,3.19961693 L14.8516162,5.81627558 C14.4628126,6.53476037 13.5910392,6.83955556 12.8390713,6.51991489 C10.9682883,5.78493153 8.83865842,6.25418492 7.45028969,7.70730621 C6.53135645,8.69989447 6.06889516,10.0310827 6.17457812,11.3794238 C6.30701252,12.681964 6.96661172,13.8736694 8.00016536,14.677733 C9.05866753,15.5524314 10.4319771,15.9503782 11.7943075,15.7771694 C12.9539759,15.6214383 13.9992299,14.9976441 14.6866535,14.0510543 L11.4973746,14.0510543 C10.6209566,14.0510751 9.90877945,13.3440121 9.90273519,12.4678659 L9.90273519,9.52137628 C9.90273519,8.64093344 10.6166796,7.92719349 11.4973746,7.92719349 L20.4053605,7.92719349 C21.2793246,7.93309626 21.9880476,8.6367299 22,9.51038192 L22,11.5773224 C21.6954275,17.4249906 16.8597486,22.0079014 11.0024865,21.9999898 Z M11.0024865,2.21012416 C8.62265013,2.2090533 6.34389345,3.17185147 4.68614478,4.87884362 C3.02839611,6.58583578 2.13308042,8.89139591 2.20447576,11.2694802 C2.40041639,15.8515827 6.03742275,19.5398294 10.6175736,19.8011067 C15.4496383,20.0190768 19.5514723,16.2965621 19.8004973,11.4673787 L19.8004973,10.1260663 L12.1022379,10.1260663 L12.1022379,11.8631758 L17.9419175,11.8631758 L17.4910195,13.2924432 C16.7642506,15.7700545 14.6584095,17.5960263 12.1022379,17.9650479 C10.1464891,18.2487094 8.15978033,17.7203963 6.60348115,16.5027975 C5.06921332,15.2995219 4.11012255,13.508076 3.95960166,11.5644046 C3.80908078,9.62073328 4.48093145,7.70305715 5.81166018,6.27803888 C7.69032381,4.25377573 10.5650106,3.48826744 13.2019892,4.3100477 L14.0487978,2.73785364 C13.0730876,2.38128177 12.0413172,2.20254243 11.0024865,2.21012416 Z" id="Shape"></path>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'GoogleIcon',
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.google-icon path{
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<template>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 53 39"
|
|
||||||
version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
>
|
|
||||||
<g id="V2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<g id="team-folder">
|
|
||||||
<path
|
|
||||||
d="M48.03125,6.5 L29.790833,6.5 C28.7431613,6.5 27.7373076,6.08896217 26.9894703,5.35523504 L22.6980297,1.14476496 C21.9501924,0.41103783 20.9443387,-6.36543387e-16 19.896667,0 L4.96875,0 L4.96875,0 C2.22455078,0 0,2.18257812 0,4.875 L0,34.125 C0,36.8174219 2.22455078,39 4.96875,39 L48.03125,39 C50.7754492,39 53,36.8174219 53,34.125 L53,11.375 C53,8.68257813 50.7754492,6.5 48.03125,6.5 Z"
|
|
||||||
class="svg-color-theme"
|
|
||||||
stroke="none"
|
|
||||||
stroke-width="0"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
d="M48.03125,6.5 L29.790833,6.5 C28.7431613,6.5 27.7373076,6.08896217 26.9894703,5.35523504 L22.6980297,1.14476496 C21.9501924,0.41103783 20.9443387,-6.36543387e-16 19.896667,0 L4.96875,0 L4.96875,0 C2.22455078,0 0,2.18257812 0,4.875 L0,34.125 C0,36.8174219 2.22455078,39 4.96875,39 L48.03125,39 C50.7754492,39 53,36.8174219 53,34.125 L53,11.375 C53,8.68257813 50.7754492,6.5 48.03125,6.5 Z"
|
|
||||||
fill="black"
|
|
||||||
fill-opacity="0.2"
|
|
||||||
stroke="none"
|
|
||||||
stroke-width="0"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
d="M48.03125,12.75 C49.0609313,12.75 49.9941504,13.1577174 50.6692739,13.8201027 C51.3356976,14.4739525 51.75,15.3766531 51.75,16.375 L51.75,16.375 L51.75,34.125 C51.75,35.1233469 51.3356976,36.0260475 50.6692739,36.6798973 C49.9941504,37.3422826 49.0609313,37.75 48.03125,37.75 L48.03125,37.75 L4.96875,37.75 C3.93906868,37.75 3.00584961,37.3422826 2.33072613,36.6798973 C1.66430239,36.0260475 1.25,35.1233469 1.25,34.125 L1.25,34.125 L1.25,16.375 C1.25,15.3766531 1.66430239,14.4739525 2.33072613,13.8201027 C3.00584961,13.1577174 3.93906868,12.75 4.96875,12.75 L4.96875,12.75 Z"
|
|
||||||
stroke-width="2"
|
|
||||||
class="svg-color-theme"
|
|
||||||
fill="green"
|
|
||||||
></path>
|
|
||||||
<g
|
|
||||||
id="Icon"
|
|
||||||
transform="translate(8.000000, 20.000000)"
|
|
||||||
class="svg-stroke-theme-darken"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="1.3"
|
|
||||||
stroke="black"
|
|
||||||
stroke-opacity="0.25"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M9.59999943,10.7999994 L9.59999943,9.59999943 C9.59999943,8.27451611 8.52548289,7.19999957 7.19999957,7.19999957 L2.39999986,7.19999957 C1.07451654,7.19999957 0,8.27451611 0,9.59999943 L0,10.7999994"
|
|
||||||
></path>
|
|
||||||
<circle cx="4.79999971" cy="2.39999986" r="2.39999986"></circle>
|
|
||||||
<path
|
|
||||||
d="M13.1999992,10.7999994 L13.1999992,9.59999943 C13.1991834,8.50627014 12.4589985,7.55143166 11.3999993,7.27799957"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
d="M8.99999946,0.0779999954 C10.0619483,0.349901852 10.8047053,1.30679461 10.8047053,2.40299986 C10.8047053,3.4992051 10.0619483,4.45609786 8.99999946,4.72799972"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'VueFolderTeamIcon',
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="page-title left" :class="type">
|
|
||||||
<h1 class="title" v-html="title"></h1>
|
|
||||||
<h2 class="description" v-if="description">
|
|
||||||
{{ description }}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'IndexPageTile',
|
|
||||||
props: ['title', 'description', 'type'],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&.center {
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
max-width: 780px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
max-width: 580px;
|
|
||||||
font-size: 48px;
|
|
||||||
font-weight: 800;
|
|
||||||
line-height: 1.3;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
/deep/ span {
|
|
||||||
font-size: 48px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
max-width: 580px;
|
|
||||||
@include font-size(20);
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.65;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.page-title {
|
|
||||||
.title {
|
|
||||||
max-width: 100%;
|
|
||||||
font-size: 32px;
|
|
||||||
line-height: 1.25;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
/deep/ span {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
max-width: 100%;
|
|
||||||
@include font-size(16);
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="text-center">
|
|
||||||
<PlanPeriodSwitcher v-if="plans && yearlyPlans.length > 0" v-model="isSelectedYearlyPlans" class="inline-block" />
|
|
||||||
<div class="plans-wrapper" v-if="plans">
|
|
||||||
<article class="plan" v-if="plan.data.attributes.interval === intervalPlanType" v-for="plan in plans.data" :key="plan.data.id">
|
|
||||||
<div class="plan-wrapper">
|
|
||||||
<header class="plan-header mb-8">
|
|
||||||
<div class="icon">
|
|
||||||
<hard-drive-icon class="text-theme mx-auto" size="26" />
|
|
||||||
</div>
|
|
||||||
<h1 class="title">{{ plan.data.attributes.name }}</h1>
|
|
||||||
<h2 class="description">
|
|
||||||
{{ plan.data.attributes.description }}
|
|
||||||
</h2>
|
|
||||||
</header>
|
|
||||||
<div class="justify-center flex py-1.5" v-for="(value, key, i) in plan.data.attributes.features" :key="i">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<CheckIcon size="18" class="svg-stroke-theme mr-2" />
|
|
||||||
|
|
||||||
<span class="text-sm font-bold" v-if="value !== -1">
|
|
||||||
{{ $t( key === 'max_team_members' ? 'max_team_members_total' : key, { value: value }) }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="text-sm font-bold" v-if="value === -1">
|
|
||||||
{{ $t(`${key}.unlimited`) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="plan-footer mt-8">
|
|
||||||
<b class="price text-theme">
|
|
||||||
{{ plan.data.attributes.price }} / {{ $t(`interval.${plan.data.attributes.interval}`) }}
|
|
||||||
</b>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { CheckIcon, HardDriveIcon } from 'vue-feather-icons'
|
|
||||||
import axios from 'axios'
|
|
||||||
import PlanPeriodSwitcher from "../../Subscription/PlanPeriodSwitcher";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PricingTables',
|
|
||||||
components: {
|
|
||||||
PlanPeriodSwitcher,
|
|
||||||
HardDriveIcon,
|
|
||||||
CheckIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
intervalPlanType() {
|
|
||||||
return this.isSelectedYearlyPlans ? 'year' : 'month'
|
|
||||||
},
|
|
||||||
yearlyPlans() {
|
|
||||||
return this.plans.data.filter((plan) => plan.data.attributes.interval === 'year')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
plans: undefined,
|
|
||||||
isSelectedYearlyPlans: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
axios.get('api/subscriptions/plans').then((response) => {
|
|
||||||
this.plans = response.data
|
|
||||||
this.$emit('load', response.data)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.plans-wrapper {
|
|
||||||
box-shadow: 0 7px 20px 5px hsla(220, 36%, 16%, 0.05);
|
|
||||||
border-radius: 8px;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan {
|
|
||||||
text-align: center;
|
|
||||||
flex: 0 0 33%;
|
|
||||||
padding: 55px 25px 75px;
|
|
||||||
//border-right: 1px solid #F7F7F7;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-header {
|
|
||||||
.icon {
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
@include font-size(25);
|
|
||||||
font-weight: 800;
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
@include font-size(14);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-features {
|
|
||||||
margin: 55px 0;
|
|
||||||
|
|
||||||
.storage-size {
|
|
||||||
@include font-size(48);
|
|
||||||
font-weight: 900;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.storage-description {
|
|
||||||
display: block;
|
|
||||||
@include font-size(15);
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-footer {
|
|
||||||
.sign-in-button {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.price {
|
|
||||||
@include font-size(18);
|
|
||||||
display: block;
|
|
||||||
padding-top: 5px;
|
|
||||||
|
|
||||||
.vat-disclaimer {
|
|
||||||
@include font-size(11);
|
|
||||||
color: $text;
|
|
||||||
display: block;
|
|
||||||
font-weight: 300;
|
|
||||||
opacity: 0.45;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plans-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.plans-wrapper {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
.plan {
|
|
||||||
padding: 30px 25px;
|
|
||||||
border-bottom: 1px solid #f7f7f7;
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.plans-wrapper {
|
|
||||||
background: $dark_mode_foreground;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan {
|
|
||||||
border-color: $dark_mode_border_color !important;
|
|
||||||
|
|
||||||
.plan-wrapper {
|
|
||||||
background: $dark_mode_foreground;
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-header {
|
|
||||||
.title {
|
|
||||||
color: $dark_mode_text_primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
color: $dark_mode_text_secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-features {
|
|
||||||
.storage-size {
|
|
||||||
color: $dark_mode_text_primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.storage-description {
|
|
||||||
color: $dark_mode_text_primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plan-footer {
|
|
||||||
.sign-in-button {
|
|
||||||
background: rgba($theme, 0.1);
|
|
||||||
|
|
||||||
/deep/ .content {
|
|
||||||
color: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.price {
|
|
||||||
.vat-disclaimer {
|
|
||||||
color: $dark_mode_text_primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,348 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="page-wrapper large get-started" v-if="index.section_get_started === '1'">
|
|
||||||
<PageTitle
|
|
||||||
class="page-title"
|
|
||||||
type="center"
|
|
||||||
:title="index.get_started_title"
|
|
||||||
:description="index.get_started_description"
|
|
||||||
></PageTitle>
|
|
||||||
|
|
||||||
<router-link
|
|
||||||
tag="button"
|
|
||||||
class="get-started-button bg-theme-800 hover-bg-theme shadow-theme"
|
|
||||||
:to="{ name: 'SignUp' }"
|
|
||||||
>
|
|
||||||
<span class="content">{{ $t('sign_up_now') }}</span>
|
|
||||||
<chevron-right-icon size="22"></chevron-right-icon>
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<cloud-icon size="790" class="cloud-bg svg-color-theme" />
|
|
||||||
|
|
||||||
<div class="icons">
|
|
||||||
<hard-drive-icon size="42" class="icon"></hard-drive-icon>
|
|
||||||
<settings-icon size="22" class="icon"></settings-icon>
|
|
||||||
<image-icon size="50" class="icon"></image-icon>
|
|
||||||
<link-icon size="24" class="icon"></link-icon>
|
|
||||||
<trash2-icon size="40" class="icon"></trash2-icon>
|
|
||||||
<search-icon size="18" class="icon"></search-icon>
|
|
||||||
<eye-icon size="36" class="icon"></eye-icon>
|
|
||||||
<star-icon size="34" class="icon"></star-icon>
|
|
||||||
<folder-plus-icon size="20" class="icon"></folder-plus-icon>
|
|
||||||
<grid-icon size="28" class="icon"></grid-icon>
|
|
||||||
<share-icon size="32" class="icon"></share-icon>
|
|
||||||
<folder-plus-icon size="48" class="icon"></folder-plus-icon>
|
|
||||||
<search-icon size="34" class="icon"></search-icon>
|
|
||||||
<star-icon size="22" class="icon"></star-icon>
|
|
||||||
<upload-cloud-icon size="42" class="icon"></upload-cloud-icon>
|
|
||||||
<grid-icon size="18" class="icon"></grid-icon>
|
|
||||||
<settings-icon size="32" class="icon"></settings-icon>
|
|
||||||
<link-icon size="36" class="icon"></link-icon>
|
|
||||||
<hard-drive-icon size="22" class="icon"></hard-drive-icon>
|
|
||||||
<info-icon size="36" class="icon"></info-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PageTitle from './Components/PageTitle'
|
|
||||||
import {
|
|
||||||
ChevronRightIcon,
|
|
||||||
UploadCloudIcon,
|
|
||||||
FolderPlusIcon,
|
|
||||||
HardDriveIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
Trash2Icon,
|
|
||||||
SearchIcon,
|
|
||||||
ShareIcon,
|
|
||||||
CloudIcon,
|
|
||||||
ImageIcon,
|
|
||||||
InfoIcon,
|
|
||||||
GridIcon,
|
|
||||||
LinkIcon,
|
|
||||||
StarIcon,
|
|
||||||
EyeIcon,
|
|
||||||
} from 'vue-feather-icons'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexGetStarted',
|
|
||||||
components: {
|
|
||||||
InfoIcon,
|
|
||||||
UploadCloudIcon,
|
|
||||||
ShareIcon,
|
|
||||||
ChevronRightIcon,
|
|
||||||
FolderPlusIcon,
|
|
||||||
HardDriveIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
Trash2Icon,
|
|
||||||
SearchIcon,
|
|
||||||
CloudIcon,
|
|
||||||
PageTitle,
|
|
||||||
ImageIcon,
|
|
||||||
GridIcon,
|
|
||||||
LinkIcon,
|
|
||||||
StarIcon,
|
|
||||||
EyeIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['index']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.icons {
|
|
||||||
.icon {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
&:nth-child(20) {
|
|
||||||
bottom: -37%;
|
|
||||||
left: 37%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
circle,
|
|
||||||
line {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(19) {
|
|
||||||
bottom: -21%;
|
|
||||||
left: 23.5%;
|
|
||||||
transform: rotate(-20deg);
|
|
||||||
|
|
||||||
path,
|
|
||||||
line {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(18) {
|
|
||||||
bottom: -4%;
|
|
||||||
left: 26.5%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
path {
|
|
||||||
stroke: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(17) {
|
|
||||||
bottom: -5%;
|
|
||||||
left: 8.5%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(16) {
|
|
||||||
top: 86%;
|
|
||||||
left: 17%;
|
|
||||||
transform: rotate(18deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(15) {
|
|
||||||
top: 64%;
|
|
||||||
left: 17%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
polyline,
|
|
||||||
line,
|
|
||||||
path {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(14) {
|
|
||||||
top: 44%;
|
|
||||||
left: 28%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
polygon {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(13) {
|
|
||||||
top: 33%;
|
|
||||||
left: 16%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(12) {
|
|
||||||
top: 23%;
|
|
||||||
left: 32%;
|
|
||||||
transform: rotate(13deg);
|
|
||||||
|
|
||||||
line,
|
|
||||||
path {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
top: 35%;
|
|
||||||
right: 49%;
|
|
||||||
transform: rotate(-11deg);
|
|
||||||
|
|
||||||
line,
|
|
||||||
path {
|
|
||||||
stroke: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
top: 12%;
|
|
||||||
right: 45%;
|
|
||||||
transform: rotate(0);
|
|
||||||
|
|
||||||
circle,
|
|
||||||
path {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
top: 30%;
|
|
||||||
right: 30%;
|
|
||||||
transform: rotate(20deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(4) {
|
|
||||||
top: 14%;
|
|
||||||
right: 14.5%;
|
|
||||||
transform: rotate(-1deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(5) {
|
|
||||||
top: 62%;
|
|
||||||
right: 15.5%;
|
|
||||||
transform: rotate(21deg);
|
|
||||||
|
|
||||||
polyline,
|
|
||||||
path,
|
|
||||||
line {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(6) {
|
|
||||||
top: 66%;
|
|
||||||
right: 26.5%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(7) {
|
|
||||||
bottom: 3%;
|
|
||||||
right: 21.5%;
|
|
||||||
transform: rotate(16deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(8) {
|
|
||||||
bottom: -13%;
|
|
||||||
right: 16.5%;
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
polygon {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(9) {
|
|
||||||
bottom: -32%;
|
|
||||||
right: 27%;
|
|
||||||
transform: rotate(-20deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(10) {
|
|
||||||
bottom: -5%;
|
|
||||||
right: 34%;
|
|
||||||
transform: rotate(16deg);
|
|
||||||
|
|
||||||
rect {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(11) {
|
|
||||||
bottom: -28%;
|
|
||||||
right: 44%;
|
|
||||||
transform: rotate(-12deg);
|
|
||||||
|
|
||||||
polyline,
|
|
||||||
line,
|
|
||||||
path {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cloud-bg {
|
|
||||||
z-index: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 70px;
|
|
||||||
right: 60px;
|
|
||||||
transform: scale(-1, 1) rotate(13deg);
|
|
||||||
opacity: 0.1;
|
|
||||||
|
|
||||||
path {
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
padding-top: 340px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.get-started-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 20px 36px;
|
|
||||||
border-radius: 6px;
|
|
||||||
//box-shadow: 0 5px 10px 2px rgba($theme, 0.34);
|
|
||||||
margin-bottom: 395px;
|
|
||||||
@include transition(150ms);
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.content {
|
|
||||||
@include font-size(19);
|
|
||||||
font-weight: 700;
|
|
||||||
margin-right: 8px;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
polyline {
|
|
||||||
stroke: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1190px) {
|
|
||||||
.get-started-button {
|
|
||||||
margin-bottom: 280px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.page-title {
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.get-started-button {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cloud-bg,
|
|
||||||
.icons {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,227 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="page-wrapper large hero-screenshot">
|
|
||||||
<img class="hero-light" src="/assets/images/vuefilemanager-screenshot-light.png" :alt="config.app_name" />
|
|
||||||
<img class="hero-dark" src="/assets/images/vuefilemanager-screenshot-dark.png" :alt="config.app_name" />
|
|
||||||
|
|
||||||
<div class="icons">
|
|
||||||
<link-icon size="20" class="icon"></link-icon>
|
|
||||||
<image-icon size="38" class="icon"></image-icon>
|
|
||||||
<hard-drive-icon size="34" class="icon"></hard-drive-icon>
|
|
||||||
<folder-plus-icon size="40" class="icon"></folder-plus-icon>
|
|
||||||
<settings-icon size="18" class="icon"></settings-icon>
|
|
||||||
<search-icon size="24" class="icon"></search-icon>
|
|
||||||
<star-icon size="18" class="icon"></star-icon>
|
|
||||||
<trash2-icon size="32" class="icon"></trash2-icon>
|
|
||||||
<search-icon size="18" class="icon"></search-icon>
|
|
||||||
<eye-icon size="30" class="icon"></eye-icon>
|
|
||||||
<star-icon size="30" class="icon"></star-icon>
|
|
||||||
<folder-plus-icon size="16" class="icon"></folder-plus-icon>
|
|
||||||
<grid-icon size="20" class="icon"></grid-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import {
|
|
||||||
FolderPlusIcon,
|
|
||||||
HardDriveIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
Trash2Icon,
|
|
||||||
SearchIcon,
|
|
||||||
ImageIcon,
|
|
||||||
GridIcon,
|
|
||||||
LinkIcon,
|
|
||||||
StarIcon,
|
|
||||||
EyeIcon,
|
|
||||||
} from 'vue-feather-icons'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexHeroScreenshot',
|
|
||||||
components: {
|
|
||||||
FolderPlusIcon,
|
|
||||||
HardDriveIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
Trash2Icon,
|
|
||||||
SearchIcon,
|
|
||||||
ImageIcon,
|
|
||||||
GridIcon,
|
|
||||||
LinkIcon,
|
|
||||||
StarIcon,
|
|
||||||
EyeIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.icons {
|
|
||||||
.icon {
|
|
||||||
z-index: 0;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
top: -14%;
|
|
||||||
right: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
top: -5%;
|
|
||||||
right: 14%;
|
|
||||||
transform: rotate(19deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
top: -6.5%;
|
|
||||||
right: 28.5%;
|
|
||||||
transform: rotate(-12deg);
|
|
||||||
|
|
||||||
line,
|
|
||||||
path {
|
|
||||||
stroke: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(4) {
|
|
||||||
top: -9.5%;
|
|
||||||
right: 41.5%;
|
|
||||||
transform: rotate(13deg);
|
|
||||||
|
|
||||||
path,
|
|
||||||
line {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(5) {
|
|
||||||
top: -16%;
|
|
||||||
right: 26%;
|
|
||||||
|
|
||||||
circle,
|
|
||||||
path {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(6) {
|
|
||||||
top: -13%;
|
|
||||||
right: 49%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(7) {
|
|
||||||
top: 2.5%;
|
|
||||||
right: 46%;
|
|
||||||
|
|
||||||
polygon {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(8) {
|
|
||||||
top: 13%;
|
|
||||||
right: 2.5%;
|
|
||||||
transform: rotate(22deg);
|
|
||||||
|
|
||||||
polyline,
|
|
||||||
path,
|
|
||||||
line {
|
|
||||||
stroke: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(9) {
|
|
||||||
top: 14%;
|
|
||||||
right: 11%;
|
|
||||||
|
|
||||||
circle,
|
|
||||||
line {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(10) {
|
|
||||||
top: 29%;
|
|
||||||
right: 7%;
|
|
||||||
transform: rotate(19deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(11) {
|
|
||||||
top: 38%;
|
|
||||||
right: 3%;
|
|
||||||
|
|
||||||
polygon {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(12) {
|
|
||||||
top: 50%;
|
|
||||||
right: 11.5%;
|
|
||||||
transform: rotate(-22deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(13) {
|
|
||||||
top: 34%;
|
|
||||||
right: 16%;
|
|
||||||
transform: rotate(13deg);
|
|
||||||
|
|
||||||
rect {
|
|
||||||
stroke: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-screenshot {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
padding-top: 75px;
|
|
||||||
padding-bottom: 130px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 80%;
|
|
||||||
box-shadow: 0 7px 255px rgba(#19363c, 0.1);
|
|
||||||
|
|
||||||
&.hero-dark {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 890px) {
|
|
||||||
.icons {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-screenshot {
|
|
||||||
padding-top: 40px;
|
|
||||||
padding-bottom: 90px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.hero-screenshot {
|
|
||||||
img {
|
|
||||||
&.hero-light {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hero-dark {
|
|
||||||
display: block;
|
|
||||||
box-shadow: 0 7px 185px rgba(0, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section class="main-features page-wrapper medium">
|
|
||||||
<PageTitle
|
|
||||||
v-if="index.section_features === '1'"
|
|
||||||
type="center"
|
|
||||||
:title="index.features_title"
|
|
||||||
:description="index.features_description"
|
|
||||||
></PageTitle>
|
|
||||||
<div v-if="index.section_feature_boxes === '1'" class="content">
|
|
||||||
<div class="hero">
|
|
||||||
<img src="/assets/images/hero-Illustration.svg" alt="Hero" />
|
|
||||||
</div>
|
|
||||||
<div class="features">
|
|
||||||
<div class="feature">
|
|
||||||
<div class="icon">
|
|
||||||
<cloud-icon size="24"></cloud-icon>
|
|
||||||
</div>
|
|
||||||
<h3 class="title">
|
|
||||||
{{ index.feature_title_1 }}
|
|
||||||
</h3>
|
|
||||||
<p class="description">
|
|
||||||
{{ index.feature_description_1 }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<div class="icon">
|
|
||||||
<user-icon size="24"></user-icon>
|
|
||||||
</div>
|
|
||||||
<h3 class="title">
|
|
||||||
{{ index.feature_title_2 }}
|
|
||||||
</h3>
|
|
||||||
<p class="description">
|
|
||||||
{{ index.feature_description_2 }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<div class="icon">
|
|
||||||
<hard-drive-icon size="24"></hard-drive-icon>
|
|
||||||
</div>
|
|
||||||
<h3 class="title">
|
|
||||||
{{ index.feature_title_3 }}
|
|
||||||
</h3>
|
|
||||||
<p class="description">
|
|
||||||
{{ index.feature_description_3 }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { UserIcon, CloudIcon, HardDriveIcon } from 'vue-feather-icons'
|
|
||||||
import PageTitle from './Components/PageTitle'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexMainFeatures',
|
|
||||||
components: {
|
|
||||||
PageTitle,
|
|
||||||
HardDriveIcon,
|
|
||||||
CloudIcon,
|
|
||||||
UserIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['index']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.features {
|
|
||||||
padding-left: 75px;
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
@include font-size(26);
|
|
||||||
font-weight: 800;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
line-height: 1.5;
|
|
||||||
color: $text-muted;
|
|
||||||
@include font-size(18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
border-radius: 12px;
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(1) .icon {
|
|
||||||
background: rgba($yellow, 0.1);
|
|
||||||
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) .icon {
|
|
||||||
background: rgba($theme, 0.1);
|
|
||||||
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
stroke: $theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) .icon {
|
|
||||||
background: rgba($purple, 0.1);
|
|
||||||
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
margin-top: 107px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1190px) {
|
|
||||||
.hero {
|
|
||||||
flex: 0 0 60%;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
padding-left: 25px;
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.content {
|
|
||||||
display: block;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
margin-top: 50px;
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
margin-bottom: 35px;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
@include font-size(22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
@include font-size(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.features {
|
|
||||||
.feature {
|
|
||||||
.description {
|
|
||||||
color: $dark_mode_text_secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
<template>
|
|
||||||
<nav class="main-navigation">
|
|
||||||
<router-link :to="{ name: 'Homepage' }" tag="div" class="logo">
|
|
||||||
<img
|
|
||||||
class="max-h-6"
|
|
||||||
v-if="config.app_logo_horizontal"
|
|
||||||
:src="$getImage(logoSrc)"
|
|
||||||
:alt="config.app_name"
|
|
||||||
/>
|
|
||||||
<b v-if="!config.app_logo_horizontal" class="logo-text">{{ config.app_name }}</b>
|
|
||||||
</router-link>
|
|
||||||
<div class="navigation">
|
|
||||||
<ul class="navigation-links">
|
|
||||||
<!--<li v-if="config.stripe_public_key">
|
|
||||||
<a href="/#pricing">
|
|
||||||
{{ $t('pricing') }}
|
|
||||||
</a>
|
|
||||||
</li>-->
|
|
||||||
<li>
|
|
||||||
<router-link :to="{ name: 'ContactUs' }" class="hover-text-theme">
|
|
||||||
{{ $t('contact_us') }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul v-if="!config.isAuthenticated" class="navigation-links">
|
|
||||||
<li>
|
|
||||||
<router-link :to="{ name: 'SignIn' }" class="hover-text-theme">
|
|
||||||
{{ $t('log_in') }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
<li v-if="config.userRegistration">
|
|
||||||
<router-link class="cta-button text-theme bg-theme-100" :to="{ name: 'SignUp' }">
|
|
||||||
{{ $t('page_index.menu.sign_in') }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul v-if="config.isAuthenticated" class="navigation-links">
|
|
||||||
<li>
|
|
||||||
<router-link class="cta-button text-theme bg-theme-100" :to="{ name: 'Files' }">
|
|
||||||
{{ $t('go_to_files') }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<router-link class="cta-button log-in text-theme bg-theme-100" :to="{ name: 'SignIn' }">
|
|
||||||
{{ $t('log_in') }}
|
|
||||||
</router-link>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexNavigation',
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config', 'index', 'isDarkMode']),
|
|
||||||
logoSrc() {
|
|
||||||
return this.isDarkMode && this.config.app_logo_horizontal ? this.config.app_logo_horizontal_dark : this.config.app_logo_horizontal
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.main-navigation {
|
|
||||||
justify-content: space-between;
|
|
||||||
padding-bottom: 25px;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 25px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
img {
|
|
||||||
cursor: pointer;
|
|
||||||
height: 38px;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-text {
|
|
||||||
font-weight: 800;
|
|
||||||
@include font-size(25);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 25px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding: 14px;
|
|
||||||
font-weight: 700;
|
|
||||||
@include font-size(17);
|
|
||||||
@include transition(150ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cta-button {
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 8px 23px;
|
|
||||||
@include font-size(17);
|
|
||||||
font-weight: 700;
|
|
||||||
|
|
||||||
&.log-in {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 690px) {
|
|
||||||
.navigation {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
img {
|
|
||||||
height: auto;
|
|
||||||
width: 190px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cta-button.log-in {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
<template>
|
|
||||||
<footer class="page-wrapper medium">
|
|
||||||
<router-link :to="{ name: 'Homepage' }" tag="div" class="logo">
|
|
||||||
<img
|
|
||||||
v-if="config.app_logo_horizontal"
|
|
||||||
:src="$getImage(logoSrc)"
|
|
||||||
:alt="config.app_name"
|
|
||||||
class="mx-auto max-h-6"
|
|
||||||
/>
|
|
||||||
<b v-if="!config.app_logo_horizontal" class="logo-text">{{ config.app_name }}</b>
|
|
||||||
</router-link>
|
|
||||||
<ul class="navigation-links">
|
|
||||||
<!-- <li>
|
|
||||||
<a href="/#pricing">
|
|
||||||
{{ $t('pricing') }}
|
|
||||||
</a>
|
|
||||||
</li>-->
|
|
||||||
<li>
|
|
||||||
<router-link :to="{ name: 'ContactUs' }" class="hover-text-theme">
|
|
||||||
{{ $t('contact_us') }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul class="navigation-links">
|
|
||||||
<li v-if="legal.visibility" v-for="(legal, index) in config.legal" :key="index">
|
|
||||||
<router-link :to="{ name: 'DynamicPage', params: { slug: legal.slug } }" class="hover-text-theme">
|
|
||||||
{{ legal.title }}
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p class="copyright" v-html="config.app_footer"></p>
|
|
||||||
</footer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexPageFooter',
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config', 'isDarkMode']),
|
|
||||||
logoSrc() {
|
|
||||||
return this.isDarkMode && this.config.app_logo_horizontal ? this.config.app_logo_horizontal_dark : this.config.app_logo_horizontal
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 38px;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-text {
|
|
||||||
font-weight: 800;
|
|
||||||
@include font-size(25);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
padding: 19px;
|
|
||||||
font-weight: 700;
|
|
||||||
@include font-size(17);
|
|
||||||
@include transition(150ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.copyright {
|
|
||||||
@include font-size(17);
|
|
||||||
color: $text-muted;
|
|
||||||
padding-top: 50px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
|
|
||||||
/deep/ a {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.navigation-links {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.copyright {
|
|
||||||
color: $dark_mode_text_secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
<template>
|
|
||||||
<header class="main-header page-wrapper medium">
|
|
||||||
<PageTitle :title="index.header_title" :description="index.header_description" />
|
|
||||||
|
|
||||||
<div v-if="!config.isAuthenticated">
|
|
||||||
<!--User registration button-->
|
|
||||||
<router-link v-if="config.userRegistration" class="sign-up-button" :to="{ name: 'SignUp' }">
|
|
||||||
<AuthButton class="button" icon="chevron-right" :text="$t('page_index.sign_up_button')" />
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<!--User login button-->
|
|
||||||
<router-link v-if="!config.userRegistration" class="sign-up-button" :to="{ name: 'SignIn' }">
|
|
||||||
<AuthButton class="button" icon="chevron-right" :text="$t('log_in')" />
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<div class="features" v-if="config.subscriptionType === 'fixed'">
|
|
||||||
<div class="feature">
|
|
||||||
<credit-card-icon size="19" class="feature-icon"></credit-card-icon>
|
|
||||||
<b class="feature-title">{{ $t('page_index.sign_feature_1') }}</b>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<hard-drive-icon size="19" class="feature-icon"></hard-drive-icon>
|
|
||||||
<b class="feature-title">{{
|
|
||||||
$t('page_index.sign_feature_2', {
|
|
||||||
defaultSpace: config.storageDefaultSpaceFormatted,
|
|
||||||
})
|
|
||||||
}}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import HardDriveIcon from 'vue-feather-icons/icons/HardDriveIcon'
|
|
||||||
import PageTitle from './Components/PageTitle'
|
|
||||||
import AuthButton from '../UI/Buttons/AuthButton'
|
|
||||||
import { CreditCardIcon } from 'vue-feather-icons'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexPageHeader',
|
|
||||||
components: {
|
|
||||||
PageTitle,
|
|
||||||
CreditCardIcon,
|
|
||||||
HardDriveIcon,
|
|
||||||
AuthButton,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['index', 'config']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.features {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 35px;
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
display: flex;
|
|
||||||
margin-right: 35px;
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
stroke: $yellow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
path,
|
|
||||||
line,
|
|
||||||
polyline,
|
|
||||||
rect,
|
|
||||||
circle {
|
|
||||||
stroke: $purple;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-title {
|
|
||||||
@include font-size(14);
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-icon {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-header {
|
|
||||||
padding-top: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sign-up-button {
|
|
||||||
margin-top: 65px;
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.button {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 690px) {
|
|
||||||
.main-header {
|
|
||||||
padding-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sign-up-button {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="page-wrapper medium pricing"
|
|
||||||
v-if="!isEmpty && index.section_pricing_content === '1' && config.stripe_public_key"
|
|
||||||
>
|
|
||||||
<div id="pricing" class="page-title center">
|
|
||||||
<h1 class="title" v-html="index.pricing_title"></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PricingTables class="pricing-tables" @load="pricingLoaded" />
|
|
||||||
|
|
||||||
<div class="page-title center">
|
|
||||||
<h2 class="description">
|
|
||||||
{{ index.pricing_description }}
|
|
||||||
</h2>
|
|
||||||
<router-link class="sign-up-button" :to="{ name: 'SignUp' }">
|
|
||||||
<AuthButton class="button" icon="chevron-right" :text="$t('page_index.sign_up_button')" />
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<cloud-icon size="800" class="cloud-bg"></cloud-icon>
|
|
||||||
<cloud-icon size="560" class="cloud-bg"></cloud-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PricingTables from './Components/PricingTables'
|
|
||||||
import AuthButton from '../UI/Buttons/AuthButton'
|
|
||||||
import { CloudIcon } from 'vue-feather-icons'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'IndexPricingTables',
|
|
||||||
components: {
|
|
||||||
PricingTables,
|
|
||||||
AuthButton,
|
|
||||||
CloudIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['index', 'config']),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isEmpty: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
pricingLoaded(pricing) {
|
|
||||||
if (pricing.length === 0) this.isEmpty = true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../sass/vuefilemanager/landing-page';
|
|
||||||
@import '../../../sass/vuefilemanager/variables';
|
|
||||||
@import '../../../sass/vuefilemanager/mixins';
|
|
||||||
|
|
||||||
.pricing {
|
|
||||||
.cloud-bg {
|
|
||||||
z-index: 0;
|
|
||||||
|
|
||||||
path {
|
|
||||||
stroke: none;
|
|
||||||
fill: rgba($theme, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
position: absolute;
|
|
||||||
top: 30px;
|
|
||||||
right: -130px;
|
|
||||||
transform: scale(-1, 1) rotate(-17deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 160px;
|
|
||||||
left: -230px;
|
|
||||||
transform: rotate(13deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&.center {
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
max-width: 580px;
|
|
||||||
font-size: 48px;
|
|
||||||
font-weight: 800;
|
|
||||||
line-height: 1.25;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
/deep/ span {
|
|
||||||
font-size: 48px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
max-width: 580px;
|
|
||||||
@include font-size(20);
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing {
|
|
||||||
padding-top: 250px;
|
|
||||||
padding-bottom: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-tables {
|
|
||||||
margin-top: 50px;
|
|
||||||
margin-bottom: 60px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sign-up-button {
|
|
||||||
padding-top: 10px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1190px) {
|
|
||||||
.cloud-bg {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing {
|
|
||||||
padding-top: 150px;
|
|
||||||
padding-bottom: 60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
.page-title {
|
|
||||||
.title {
|
|
||||||
font-size: 28px;
|
|
||||||
line-height: 1.25;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
/deep/ span {
|
|
||||||
font-size: 28px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
@include font-size(16);
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing {
|
|
||||||
padding-top: 50px;
|
|
||||||
padding-bottom: 120px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
<ListInfoItem :title="$t('created_at')" :content="singleFile.data.attributes.created_at" />
|
<ListInfoItem :title="$t('created_at')" :content="singleFile.data.attributes.created_at" />
|
||||||
|
|
||||||
<!--Location-->
|
<!--Location-->
|
||||||
<ListInfoItem v-if="$checkPermission(['master']) && !isTeamsHomepage" :title="$t('where')">
|
<ListInfoItem v-if="$checkPermission(['master'])" :title="$t('where')">
|
||||||
<div @click="$moveFileOrFolder(singleFile)" class="flex cursor-pointer items-center">
|
<div @click="$moveFileOrFolder(singleFile)" class="flex cursor-pointer items-center">
|
||||||
<b class="inline-block text-sm font-bold">
|
<b class="inline-block text-sm font-bold">
|
||||||
{{
|
{{
|
||||||
@@ -84,16 +84,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</ListInfoItem>
|
</ListInfoItem>
|
||||||
|
|
||||||
<!--Author-->
|
|
||||||
<ListInfoItem v-if="canShowAuthor" :title="$t('author')">
|
|
||||||
<div class="mt-1.5 flex items-center">
|
|
||||||
<MemberAvatar :size="32" :member="singleFile.data.relationships.creator" />
|
|
||||||
<span class="ml-3 block text-sm font-bold">
|
|
||||||
{{ singleFile.data.relationships.creator.data.attributes.name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</ListInfoItem>
|
|
||||||
|
|
||||||
<!--Metadata-->
|
<!--Metadata-->
|
||||||
<ListInfoItem v-if="canShowMetaData" :title="$t('meta_data')">
|
<ListInfoItem v-if="canShowMetaData" :title="$t('meta_data')">
|
||||||
<ImageMetaData />
|
<ImageMetaData />
|
||||||
@@ -108,7 +98,6 @@ import CopyShareLink from '../../Inputs/CopyShareLink'
|
|||||||
import {Edit2Icon, LockIcon, UnlockIcon, EyeOffIcon} from 'vue-feather-icons'
|
import {Edit2Icon, LockIcon, UnlockIcon, EyeOffIcon} from 'vue-feather-icons'
|
||||||
import ImageMetaData from '../../UI/Others/ImageMetaData'
|
import ImageMetaData from '../../UI/Others/ImageMetaData'
|
||||||
import TitlePreview from '../../UI/Labels/TitlePreview'
|
import TitlePreview from '../../UI/Labels/TitlePreview'
|
||||||
import TeamMembersPreview from '../../Teams/Components/TeamMembersPreview'
|
|
||||||
import ListInfoItem from '../../UI/List/ListInfoItem'
|
import ListInfoItem from '../../UI/List/ListInfoItem'
|
||||||
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
||||||
import {mapGetters} from 'vuex'
|
import {mapGetters} from 'vuex'
|
||||||
@@ -116,7 +105,6 @@ import {mapGetters} from 'vuex'
|
|||||||
export default {
|
export default {
|
||||||
name: 'InfoSidebar',
|
name: 'InfoSidebar',
|
||||||
components: {
|
components: {
|
||||||
TeamMembersPreview,
|
|
||||||
FilePreviewDetail,
|
FilePreviewDetail,
|
||||||
ImageMetaData,
|
ImageMetaData,
|
||||||
CopyShareLink,
|
CopyShareLink,
|
||||||
@@ -156,17 +144,6 @@ export default {
|
|||||||
|
|
||||||
return title ? this.$t(title.label) : this.$t('can_download_file')
|
return title ? this.$t(title.label) : this.$t('can_download_file')
|
||||||
},
|
},
|
||||||
canShowAuthor() {
|
|
||||||
return (
|
|
||||||
this.$isThisRoute(this.$route, ['SharedWithMe', 'TeamFolders'])
|
|
||||||
&& this.clipboard[0].data.type !== 'folder'
|
|
||||||
&& this.clipboard[0].data.relationships.creator
|
|
||||||
&& this.user.data.id !== this.clipboard[0].data.relationships.creator.data.id
|
|
||||||
)
|
|
||||||
},
|
|
||||||
isTeamsHomepage() {
|
|
||||||
return this.$isThisRoute(this.$route, ['TeamFolders', 'SharedWithMe']) && !this.$route.params.id
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="hidden w-[300px] shrink-0 overflow-y-auto overflow-x-hidden px-2.5 pt-2 lg:block xl:w-[320px] 2xl:w-[360px]"
|
|
||||||
>
|
|
||||||
<!--Is empty clipboard-->
|
|
||||||
<div v-if="isEmpty" class="flex h-full items-center justify-center">
|
|
||||||
<div class="text-center">
|
|
||||||
<eye-off-icon size="22" class="vue-feather mb-3 inline-block text-gray-500" />
|
|
||||||
<small class="block text-xs text-gray-500">
|
|
||||||
{{ $t('nothing_to_preview') }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Multiple item selection-->
|
|
||||||
<TitlePreview
|
|
||||||
v-if="!isSingleFile && !isEmpty"
|
|
||||||
class="mb-6"
|
|
||||||
icon="check-square"
|
|
||||||
:title="$t('selected_multiple')"
|
|
||||||
:subtitle="this.clipboard.length + ' ' + $tc('items', this.clipboard.length)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--Single file preview-->
|
|
||||||
<div v-if="isSingleFile && !isEmpty">
|
|
||||||
<FilePreviewDetail />
|
|
||||||
|
|
||||||
<TitlePreview
|
|
||||||
class="mb-6"
|
|
||||||
:icon="clipboard[0].data.type"
|
|
||||||
:title="clipboard[0].data.attributes.name"
|
|
||||||
:subtitle="clipboard[0].data.attributes.mimetype"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--Filesize-->
|
|
||||||
<ListInfoItem
|
|
||||||
v-if="singleFile.data.attributes.filesize"
|
|
||||||
:title="$t('size')"
|
|
||||||
:content="singleFile.data.attributes.filesize"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--Created At-->
|
|
||||||
<ListInfoItem :title="$t('created_at')" :content="singleFile.data.attributes.created_at" />
|
|
||||||
|
|
||||||
<!--Location-->
|
|
||||||
<ListInfoItem :title="$t('where')">
|
|
||||||
<div @click="$moveFileOrFolder(singleFile)" class="flex cursor-pointer items-center">
|
|
||||||
<b class="inline-block text-sm font-bold">
|
|
||||||
{{
|
|
||||||
singleFile.data.relationships.parent
|
|
||||||
? singleFile.data.relationships.parent.data.attributes.name
|
|
||||||
: $getCurrentLocationName()
|
|
||||||
}}
|
|
||||||
</b>
|
|
||||||
<Edit2Icon size="10" class="ml-2" />
|
|
||||||
</div>
|
|
||||||
</ListInfoItem>
|
|
||||||
|
|
||||||
<!--Shared-->
|
|
||||||
<ListInfoItem
|
|
||||||
v-if="$checkPermission('master') && singleFile.data.relationships.shared"
|
|
||||||
:title="$t('shared')"
|
|
||||||
>
|
|
||||||
<div @click="$shareFileOrFolder(singleFile)" class="mb-2 flex cursor-pointer items-center">
|
|
||||||
<span class="inline-block text-sm font-bold">
|
|
||||||
{{ sharedInfo }}
|
|
||||||
</span>
|
|
||||||
<Edit2Icon size="10" class="ml-2" />
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full items-center">
|
|
||||||
<lock-icon
|
|
||||||
v-if="isLocked"
|
|
||||||
@click="$shareFileOrFolder(singleFile)"
|
|
||||||
size="17"
|
|
||||||
class="hover-text-theme vue-feather cursor-pointer"
|
|
||||||
/>
|
|
||||||
<unlock-icon
|
|
||||||
v-if="!isLocked"
|
|
||||||
@click="$shareFileOrFolder(singleFile)"
|
|
||||||
size="17"
|
|
||||||
class="hover-text-theme vue-feather cursor-pointer"
|
|
||||||
/>
|
|
||||||
<CopyShareLink :item="singleFile" size="small" class="w-full pl-2.5" />
|
|
||||||
</div>
|
|
||||||
</ListInfoItem>
|
|
||||||
|
|
||||||
<!--Metadata-->
|
|
||||||
<ListInfoItem v-if="canShowMetaData" :title="$t('meta_data')">
|
|
||||||
<ImageMetaData />
|
|
||||||
</ListInfoItem>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { Edit2Icon, LockIcon, UnlockIcon, EyeOffIcon } from 'vue-feather-icons'
|
|
||||||
import FilePreviewDetail from '../../Others/FilePreviewDetail'
|
|
||||||
import ListInfoItem from '../../UI/List/ListInfoItem'
|
|
||||||
import ImageMetaData from '../../UI/Others/ImageMetaData'
|
|
||||||
import TitlePreview from '../../UI/Labels/TitlePreview'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'InfoSidebarUploadRequest',
|
|
||||||
components: {
|
|
||||||
FilePreviewDetail,
|
|
||||||
ImageMetaData,
|
|
||||||
TitlePreview,
|
|
||||||
ListInfoItem,
|
|
||||||
UnlockIcon,
|
|
||||||
EyeOffIcon,
|
|
||||||
Edit2Icon,
|
|
||||||
LockIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['clipboard']),
|
|
||||||
isEmpty() {
|
|
||||||
return this.clipboard.length === 0
|
|
||||||
},
|
|
||||||
isSingleFile() {
|
|
||||||
return this.clipboard.length === 1
|
|
||||||
},
|
|
||||||
singleFile() {
|
|
||||||
return this.clipboard[0]
|
|
||||||
},
|
|
||||||
canShowMetaData() {
|
|
||||||
return (
|
|
||||||
this.clipboard[0].data.attributes.metadata && this.clipboard[0].data.attributes.metadata.ExifImageWidth
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -13,47 +13,29 @@
|
|||||||
/>
|
/>
|
||||||
<PopoverItem name="desktop-create" side="left">
|
<PopoverItem name="desktop-create" side="left">
|
||||||
<OptionGroup
|
<OptionGroup
|
||||||
:title="$t('frequently_used')"
|
:title="$t('create')"
|
||||||
>
|
>
|
||||||
<OptionUpload
|
<OptionUpload
|
||||||
:title="$t('upload_files')"
|
:title="$t('upload_files')"
|
||||||
type="file"
|
type="file"
|
||||||
:class="{
|
:class="{
|
||||||
'is-inactive': (isSharedWithMe && !canEdit) || canUploadInView || isTeamFolderHomepage || isSharedWithMeHomepage,
|
'is-inactive': canUploadInView,
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<Option
|
|
||||||
@click.native="$createFolder"
|
|
||||||
:class="{
|
|
||||||
'is-inactive': (isSharedWithMe && !canEdit) || canCreateFolder || isTeamFolderHomepage || isSharedWithMeHomepage,
|
|
||||||
}"
|
|
||||||
:title="$t('create_folder')"
|
|
||||||
icon="folder-plus"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
<OptionGroup :title="$t('others')">
|
|
||||||
<OptionUpload
|
<OptionUpload
|
||||||
:class="{
|
:class="{
|
||||||
'is-inactive': (isSharedWithMe && !canEdit) || canUploadFolderInView || isTeamFolderHomepage || isSharedWithMeHomepage,
|
'is-inactive': canUploadFolderInView,
|
||||||
}"
|
}"
|
||||||
:title="$t('upload_folder')"
|
:title="$t('upload_folder')"
|
||||||
type="folder"
|
type="folder"
|
||||||
/>
|
/>
|
||||||
<Option
|
<Option
|
||||||
@click.stop.native="$openRemoteUploadPopup"
|
@click.native="$createFolder"
|
||||||
:title="$t('remote_upload')"
|
:class="{
|
||||||
icon="remote-upload"
|
'is-inactive': canCreateFolder,
|
||||||
/>
|
}"
|
||||||
<Option
|
:title="$t('create_folder')"
|
||||||
@click.stop.native="$createTeamFolder"
|
icon="folder-plus"
|
||||||
:class="{ 'is-inactive': canCreateTeamFolder }"
|
|
||||||
:title="$t('create_team_folder')"
|
|
||||||
icon="users"
|
|
||||||
/>
|
|
||||||
<Option
|
|
||||||
@click.native="$createFileRequest"
|
|
||||||
:title="$t('create_file_request')"
|
|
||||||
icon="upload-cloud"
|
|
||||||
/>
|
/>
|
||||||
</OptionGroup>
|
</OptionGroup>
|
||||||
</PopoverItem>
|
</PopoverItem>
|
||||||
@@ -64,53 +46,11 @@
|
|||||||
|
|
||||||
<!--File Controls-->
|
<!--File Controls-->
|
||||||
<div class="ml-5 flex items-center xl:ml-8">
|
<div class="ml-5 flex items-center xl:ml-8">
|
||||||
<!--Team Heads-->
|
|
||||||
<PopoverWrapper v-if="$isThisRoute($route, ['TeamFolders', 'SharedWithMe'])">
|
|
||||||
<TeamMembersButton
|
|
||||||
@click.stop.native="showTeamFolderMenu"
|
|
||||||
size="32"
|
|
||||||
class="cursor-pointer rounded-lg py-0.5 pl-2 pr-0.5 hover:bg-light-background dark:hover:bg-dark-foreground"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<PopoverItem name="team-folder" side="left">
|
|
||||||
<TeamFolderPreview />
|
|
||||||
|
|
||||||
<OptionGroup v-if="$isThisRoute($route, ['TeamFolders'])" :title="$t('options')">
|
|
||||||
<Option
|
|
||||||
@click.native="$updateTeamFolder(teamFolder)"
|
|
||||||
:title="$t('edit_members')"
|
|
||||||
icon="rename"
|
|
||||||
/>
|
|
||||||
<Option
|
|
||||||
@click.native="$dissolveTeamFolder(teamFolder)"
|
|
||||||
:title="$t('dissolve_team')"
|
|
||||||
icon="trash"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
|
|
||||||
<OptionGroup v-if="$isThisRoute($route, ['SharedWithMe'])" :title="$t('options')">
|
|
||||||
<Option
|
|
||||||
@click.native="$detachMeFromTeamFolder(teamFolder)"
|
|
||||||
:title="$t('leave_team_folder')"
|
|
||||||
icon="user-minus"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
</PopoverItem>
|
|
||||||
</PopoverWrapper>
|
|
||||||
|
|
||||||
<!--Action buttons-->
|
<!--Action buttons-->
|
||||||
<div v-if="!$isMobile()" class="flex items-center">
|
<div v-if="!$isMobile()" class="flex items-center">
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
v-if="canShowConvertToTeamFolder"
|
v-if="!$isThisRoute($route, ['Public'])"
|
||||||
@click.native="$convertAsTeamFolder(clipboard[0])"
|
|
||||||
:class="{
|
|
||||||
'is-inactive': !canCreateTeamFolder,
|
|
||||||
}"
|
|
||||||
source="user-plus"
|
|
||||||
:action="$t('convert_into_team_folder')"
|
|
||||||
/>
|
|
||||||
<ToolbarButton
|
|
||||||
v-if="!$isThisRoute($route, ['SharedWithMe', 'Public'])"
|
|
||||||
@click.native="$shareFileOrFolder(clipboard[0])"
|
@click.native="$shareFileOrFolder(clipboard[0])"
|
||||||
:class="{
|
:class="{
|
||||||
'is-inactive': canShareInView,
|
'is-inactive': canShareInView,
|
||||||
@@ -121,7 +61,7 @@
|
|||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
@click.native="$moveFileOrFolder(clipboard[0])"
|
@click.native="$moveFileOrFolder(clipboard[0])"
|
||||||
:class="{
|
:class="{
|
||||||
'is-inactive': canMoveInView && !canEdit,
|
'is-inactive': canMoveInView,
|
||||||
}"
|
}"
|
||||||
source="move"
|
source="move"
|
||||||
:action="$t('move')"
|
:action="$t('move')"
|
||||||
@@ -129,7 +69,7 @@
|
|||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
@click.native="$deleteFileOrFolder(clipboard[0])"
|
@click.native="$deleteFileOrFolder(clipboard[0])"
|
||||||
:class="{
|
:class="{
|
||||||
'is-inactive': canDeleteInView && !canEdit,
|
'is-inactive': canDeleteInView,
|
||||||
}"
|
}"
|
||||||
source="trash"
|
source="trash"
|
||||||
:action="$t('delete')"
|
:action="$t('delete')"
|
||||||
@@ -163,8 +103,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TeamMembersButton from '../../Teams/Components/TeamMembersButton'
|
|
||||||
import TeamFolderPreview from '../../Teams/Components/TeamFolderPreview'
|
|
||||||
import PopoverWrapper from '../../UI/Popover/PopoverWrapper'
|
import PopoverWrapper from '../../UI/Popover/PopoverWrapper'
|
||||||
import FileSortingOptions from '../../Menus/FileSortingOptions'
|
import FileSortingOptions from '../../Menus/FileSortingOptions'
|
||||||
import PopoverItem from '../../UI/Popover/PopoverItem'
|
import PopoverItem from '../../UI/Popover/PopoverItem'
|
||||||
@@ -182,8 +120,6 @@ export default {
|
|||||||
name: 'DesktopToolbar',
|
name: 'DesktopToolbar',
|
||||||
components: {
|
components: {
|
||||||
FileSortingOptions,
|
FileSortingOptions,
|
||||||
TeamMembersButton,
|
|
||||||
TeamFolderPreview,
|
|
||||||
SearchBarButton,
|
SearchBarButton,
|
||||||
UploadProgress,
|
UploadProgress,
|
||||||
PopoverWrapper,
|
PopoverWrapper,
|
||||||
@@ -197,71 +133,34 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
'isVisibleNavigationBars',
|
'isVisibleNavigationBars',
|
||||||
'currentTeamFolder',
|
|
||||||
'currentFolder',
|
'currentFolder',
|
||||||
'sharedDetail',
|
'sharedDetail',
|
||||||
'clipboard',
|
'clipboard',
|
||||||
'user',
|
'user',
|
||||||
]),
|
]),
|
||||||
canEdit() {
|
|
||||||
if (this.currentTeamFolder && this.user) {
|
|
||||||
let member = this.currentTeamFolder.data.relationships.members.data.find(
|
|
||||||
(member) => member.data.id === this.user.data.id
|
|
||||||
)
|
|
||||||
|
|
||||||
return member.data.attributes.permission === 'can-edit'
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
teamFolder() {
|
|
||||||
return this.currentTeamFolder ? this.currentTeamFolder : this.clipboard[0]
|
|
||||||
},
|
|
||||||
isTeamFolderHomepage() {
|
|
||||||
return this.$isThisRoute(this.$route, ['TeamFolders']) && !this.$route.params.id
|
|
||||||
},
|
|
||||||
isSharedWithMe() {
|
|
||||||
return this.$isThisRoute(this.$route, ['SharedWithMe'])
|
|
||||||
},
|
|
||||||
isSharedWithMeHomepage() {
|
|
||||||
return this.$isThisRoute(this.$route, ['SharedWithMe']) && !this.$route.params.id
|
|
||||||
},
|
|
||||||
canCreateFolder() {
|
canCreateFolder() {
|
||||||
return !this.$isThisRoute(this.$route, ['Files', 'Public', 'TeamFolders', 'SharedWithMe'])
|
return !this.$isThisRoute(this.$route, ['Files', 'Public'])
|
||||||
},
|
|
||||||
canShowConvertToTeamFolder() {
|
|
||||||
return this.$isThisRoute(this.$route, ['Files', 'MySharedItems'])
|
|
||||||
},
|
},
|
||||||
canUploadInView() {
|
canUploadInView() {
|
||||||
return !this.$isThisRoute(this.$route, ['Files', 'RecentUploads', 'Public', 'TeamFolders', 'SharedWithMe'])
|
return !this.$isThisRoute(this.$route, ['Files', 'RecentUploads', 'Public'])
|
||||||
},
|
},
|
||||||
canUploadFolderInView() {
|
canUploadFolderInView() {
|
||||||
return !this.$isThisRoute(this.$route, ['Files', 'Public', 'TeamFolders', 'SharedWithMe'])
|
return !this.$isThisRoute(this.$route, ['Files', 'Public'])
|
||||||
},
|
},
|
||||||
canDeleteInView() {
|
canDeleteInView() {
|
||||||
let routes = ['TeamFolders', 'SharedWithMe', 'RecentUploads', 'MySharedItems', 'Trash', 'Public', 'Files']
|
let routes = ['RecentUploads', 'MySharedItems', 'Trash', 'Public', 'Files']
|
||||||
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length === 0
|
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length === 0
|
||||||
},
|
},
|
||||||
canMoveInView() {
|
canMoveInView() {
|
||||||
let routes = ['SharedWithMe', 'RecentUploads', 'MySharedItems', 'Public', 'Files', 'TeamFolders']
|
let routes = ['RecentUploads', 'MySharedItems', 'Public', 'Files']
|
||||||
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length === 0
|
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length === 0
|
||||||
},
|
},
|
||||||
canShareInView() {
|
canShareInView() {
|
||||||
let routes = ['TeamFolders', 'RecentUploads', 'MySharedItems', 'Public', 'Files']
|
let routes = ['RecentUploads', 'MySharedItems', 'Public', 'Files']
|
||||||
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length > 1 || this.clipboard.length === 0
|
return !this.$isThisRoute(this.$route, routes) || this.clipboard.length > 1 || this.clipboard.length === 0
|
||||||
},
|
},
|
||||||
canCreateTeamFolder() {
|
|
||||||
return (
|
|
||||||
this.$isThisRoute(this.$route, ['MySharedItems', 'Files']) &&
|
|
||||||
this.clipboard.length === 1 &&
|
|
||||||
this.clipboard[0].data.type === 'folder'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showTeamFolderMenu() {
|
|
||||||
if (this.teamFolder) events.$emit('popover:open', 'team-folder')
|
|
||||||
},
|
|
||||||
showCreateMenu() {
|
showCreateMenu() {
|
||||||
events.$emit('popover:open', 'desktop-create')
|
events.$emit('popover:open', 'desktop-create')
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hidden lg:block">
|
|
||||||
<div class="flex items-center justify-between py-3">
|
|
||||||
<NavigationBar />
|
|
||||||
|
|
||||||
<div class="flex items-center">
|
|
||||||
|
|
||||||
<!--I am Done-->
|
|
||||||
<div @click="uploadingDone" class="bg-theme-200 mr-6 flex cursor-pointer items-center rounded-lg py-1 pr-1 pl-4">
|
|
||||||
<b class="text-theme mr-3 text-sm leading-3">
|
|
||||||
{{ $t('tell_you_are_done', {name: uploadRequest.data.relationships.user.data.attributes.name}) }}
|
|
||||||
</b>
|
|
||||||
<MemberAvatar
|
|
||||||
:member="uploadRequest.data.relationships.user"
|
|
||||||
:size="34"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Create button-->
|
|
||||||
<PopoverWrapper>
|
|
||||||
<ToolbarButton
|
|
||||||
@click.stop.native="showCreateMenu"
|
|
||||||
source="cloud-plus"
|
|
||||||
:action="$t('create_something')"
|
|
||||||
/>
|
|
||||||
<PopoverItem name="desktop-create" side="left">
|
|
||||||
<OptionGroup :title="$t('frequently_used')">
|
|
||||||
<OptionUpload :title="$t('upload_files')" type="file" />
|
|
||||||
<Option
|
|
||||||
@click.native="$createFolder"
|
|
||||||
:title="$t('create_folder')"
|
|
||||||
icon="folder-plus"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
<OptionGroup :title="$t('others')">
|
|
||||||
<OptionUpload :title="$t('upload_folder')" type="folder" />
|
|
||||||
<Option
|
|
||||||
@click.stop.native="$openRemoteUploadPopup"
|
|
||||||
:title="$t('remote_upload')"
|
|
||||||
icon="remote-upload"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
</PopoverItem>
|
|
||||||
</PopoverWrapper>
|
|
||||||
|
|
||||||
<!--File Controls-->
|
|
||||||
<div v-if="!$isMobile()" class="ml-5 flex items-center xl:ml-8">
|
|
||||||
<ToolbarButton
|
|
||||||
@click.native="$moveFileOrFolder(clipboard[0])"
|
|
||||||
:class="{
|
|
||||||
'is-inactive': !canManipulate,
|
|
||||||
}"
|
|
||||||
source="move"
|
|
||||||
:action="$t('move')"
|
|
||||||
/>
|
|
||||||
<ToolbarButton
|
|
||||||
@click.native="$deleteFileOrFolder(clipboard[0])"
|
|
||||||
:class="{
|
|
||||||
'is-inactive': !canManipulate,
|
|
||||||
}"
|
|
||||||
source="trash"
|
|
||||||
:action="$t('delete')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--View Controls-->
|
|
||||||
<div class="ml-5 flex items-center xl:ml-8">
|
|
||||||
<PopoverWrapper>
|
|
||||||
<ToolbarButton
|
|
||||||
@click.stop.native="showSortingMenu"
|
|
||||||
source="preview-sorting"
|
|
||||||
:action="$t('sorting_view')"
|
|
||||||
/>
|
|
||||||
<PopoverItem name="desktop-sorting" side="left">
|
|
||||||
<FileSortingOptions />
|
|
||||||
</PopoverItem>
|
|
||||||
</PopoverWrapper>
|
|
||||||
<ToolbarButton
|
|
||||||
@click.native="$store.dispatch('fileInfoToggle')"
|
|
||||||
:action="$t('info_panel')"
|
|
||||||
source="info"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<UploadProgress />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PopoverWrapper from '../../UI/Popover/PopoverWrapper'
|
|
||||||
import FileSortingOptions from '../../Menus/FileSortingOptions'
|
|
||||||
import PopoverItem from '../../UI/Popover/PopoverItem'
|
|
||||||
import UploadProgress from '../../UI/Others/UploadProgress'
|
|
||||||
import NavigationBar from './NavigationBar'
|
|
||||||
import ToolbarButton from '../../UI/Buttons/ToolbarButton'
|
|
||||||
import MemberAvatar from "../../UI/Others/MemberAvatar"
|
|
||||||
import OptionUpload from '../../Menus/Components/OptionUpload'
|
|
||||||
import OptionGroup from '../../Menus/Components/OptionGroup'
|
|
||||||
import { events } from '../../../bus'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import Option from '../../Menus/Components/Option'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'DesktopUploadRequestToolbar',
|
|
||||||
components: {
|
|
||||||
FileSortingOptions,
|
|
||||||
UploadProgress,
|
|
||||||
PopoverWrapper,
|
|
||||||
NavigationBar,
|
|
||||||
ToolbarButton,
|
|
||||||
MemberAvatar,
|
|
||||||
OptionUpload,
|
|
||||||
OptionGroup,
|
|
||||||
PopoverItem,
|
|
||||||
Option,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['isVisibleNavigationBars', 'currentTeamFolder', 'currentFolder', 'sharedDetail', 'clipboard', 'uploadRequest']),
|
|
||||||
canManipulate() {
|
|
||||||
return this.clipboard[0]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
uploadingDone() {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: this.$t('closing_request_for_upload', {name: this.uploadRequest.data.relationships.user.data.attributes.name}),
|
|
||||||
message: this.$t('closing_request_for_upload_warn'),
|
|
||||||
action: {
|
|
||||||
id: this.$router.currentRoute.params.token,
|
|
||||||
operation: 'close-upload-request',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showCreateMenu() {
|
|
||||||
events.$emit('popover:open', 'desktop-create')
|
|
||||||
},
|
|
||||||
showSortingMenu() {
|
|
||||||
events.$emit('popover:open', 'desktop-sorting')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -5,12 +5,6 @@
|
|||||||
<NavigationBar />
|
<NavigationBar />
|
||||||
|
|
||||||
<div class="relative flex items-center">
|
<div class="relative flex items-center">
|
||||||
<TeamMembersButton
|
|
||||||
v-if="$isThisRoute($route, ['TeamFolders', 'SharedWithMe'])"
|
|
||||||
size="28"
|
|
||||||
@click.stop.native="$showMobileMenu('team-menu')"
|
|
||||||
class="absolute right-10"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!--More Actions-->
|
<!--More Actions-->
|
||||||
<div class="flex items-center relative mr-[4px]">
|
<div class="flex items-center relative mr-[4px]">
|
||||||
@@ -24,8 +18,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TeamMembersPreview from '../../Teams/Components/TeamMembersPreview'
|
|
||||||
import TeamMembersButton from '../../Teams/Components/TeamMembersButton'
|
|
||||||
import { MenuIcon } from 'vue-feather-icons'
|
import { MenuIcon } from 'vue-feather-icons'
|
||||||
import NavigationBar from './NavigationBar'
|
import NavigationBar from './NavigationBar'
|
||||||
|
|
||||||
@@ -33,8 +25,6 @@ export default {
|
|||||||
name: 'MobileToolBar',
|
name: 'MobileToolBar',
|
||||||
components: {
|
components: {
|
||||||
NavigationBar,
|
NavigationBar,
|
||||||
TeamMembersPreview,
|
|
||||||
TeamMembersButton,
|
|
||||||
MenuIcon,
|
MenuIcon,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="sticky top-0 z-[19] block flex w-full items-center justify-between bg-white py-5 px-4 text-center dark:bg-dark-background lg:hidden"
|
|
||||||
>
|
|
||||||
<NavigationBar />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import TeamMembersPreview from '../../Teams/Components/TeamMembersPreview'
|
|
||||||
import TeamMembersButton from '../../Teams/Components/TeamMembersButton'
|
|
||||||
import { MenuIcon } from 'vue-feather-icons'
|
|
||||||
import NavigationBar from './NavigationBar'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MobileUploadRequestToolBar',
|
|
||||||
components: {
|
|
||||||
NavigationBar,
|
|
||||||
TeamMembersPreview,
|
|
||||||
TeamMembersButton,
|
|
||||||
MenuIcon,
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showMobileNavigation() {
|
|
||||||
this.$showMobileMenu('user-navigation')
|
|
||||||
this.$store.commit('DISABLE_MULTISELECT_MODE')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<template>
|
|
||||||
<MenuMobile name="team-menu">
|
|
||||||
<TeamFolderPreview />
|
|
||||||
|
|
||||||
<MenuMobileGroup v-if="$slots.default">
|
|
||||||
<slot />
|
|
||||||
</MenuMobileGroup>
|
|
||||||
</MenuMobile>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MenuMobileGroup from '../Mobile/MenuMobileGroup'
|
|
||||||
import TeamFolderPreview from '../Teams/Components/TeamFolderPreview'
|
|
||||||
import MenuMobile from '../Mobile/MenuMobile'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MobileTeamContextMenu',
|
|
||||||
components: {
|
|
||||||
TeamFolderPreview,
|
|
||||||
MenuMobileGroup,
|
|
||||||
MenuMobile,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -3,21 +3,6 @@
|
|||||||
<!--User avatar-->
|
<!--User avatar-->
|
||||||
<UserHeadline v-if="!clickedSubmenu" class="p-5 pb-3" />
|
<UserHeadline v-if="!clickedSubmenu" class="p-5 pb-3" />
|
||||||
|
|
||||||
<!--User estimate-->
|
|
||||||
<div
|
|
||||||
v-if="config.subscriptionType === 'metered' && user && user.data.meta.usages && !clickedSubmenu"
|
|
||||||
class="block px-5 pt-2"
|
|
||||||
>
|
|
||||||
<div class="rounded-lg bg-light-background px-3 py-1.5 dark:bg-4x-dark-foreground">
|
|
||||||
<span class="text-sm font-semibold">
|
|
||||||
{{ $t('current_estimated_usage') }}
|
|
||||||
</span>
|
|
||||||
<span class="text-theme text-sm font-bold">
|
|
||||||
{{ user.data.meta.usages.costEstimate }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Go back button-->
|
<!--Go back button-->
|
||||||
<div v-if="clickedSubmenu" @click.stop="showSubmenu(undefined)" class="flex items-center p-5 pb-4">
|
<div v-if="clickedSubmenu" @click.stop="showSubmenu(undefined)" class="flex items-center p-5 pb-4">
|
||||||
<chevron-left-icon size="19" class="vue-feather text-theme mr-2 -ml-1" />
|
<chevron-left-icon size="19" class="vue-feather text-theme mr-2 -ml-1" />
|
||||||
@@ -76,13 +61,6 @@
|
|||||||
icon="hard-drive"
|
icon="hard-drive"
|
||||||
:is-hover-disabled="true"
|
:is-hover-disabled="true"
|
||||||
/>
|
/>
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('Billing')"
|
|
||||||
v-if="config.subscriptionType !== 'none'"
|
|
||||||
:title="$t('billing')"
|
|
||||||
icon="cloud"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
</OptionGroup>
|
||||||
|
|
||||||
<!--Submenu: Admin settings-->
|
<!--Submenu: Admin settings-->
|
||||||
@@ -105,16 +83,6 @@
|
|||||||
icon="settings"
|
icon="settings"
|
||||||
:is-hover-disabled="true"
|
:is-hover-disabled="true"
|
||||||
/>
|
/>
|
||||||
</OptionGroup>
|
|
||||||
|
|
||||||
<!--Submenu: Content settings-->
|
|
||||||
<OptionGroup v-if="clickedSubmenu === 'admin'">
|
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('Pages')"
|
|
||||||
:title="$t('pages')"
|
|
||||||
icon="monitor"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
<Option
|
<Option
|
||||||
@click.native="goToRoute('Language')"
|
@click.native="goToRoute('Language')"
|
||||||
:title="$t('languages')"
|
:title="$t('languages')"
|
||||||
@@ -122,35 +90,6 @@
|
|||||||
:is-hover-disabled="true"
|
:is-hover-disabled="true"
|
||||||
/>
|
/>
|
||||||
</OptionGroup>
|
</OptionGroup>
|
||||||
|
|
||||||
<!--Submenu: Billing settings-->
|
|
||||||
<OptionGroup v-if="clickedSubmenu === 'admin' && config.subscriptionType !== 'none'">
|
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('AppPayments')"
|
|
||||||
:title="$t('payments')"
|
|
||||||
icon="credit-card"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('Subscriptions')"
|
|
||||||
v-if="config.subscriptionType === 'fixed'"
|
|
||||||
:title="$t('subscriptions')"
|
|
||||||
icon="credit-card"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('Plans')"
|
|
||||||
:title="$t('plans')"
|
|
||||||
icon="database"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
<Option
|
|
||||||
@click.native="goToRoute('Invoices')"
|
|
||||||
:title="$t('transactions')"
|
|
||||||
icon="file-text"
|
|
||||||
:is-hover-disabled="true"
|
|
||||||
/>
|
|
||||||
</OptionGroup>
|
|
||||||
</MenuMobileGroup>
|
</MenuMobileGroup>
|
||||||
</MenuMobile>
|
</MenuMobile>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
<template>
|
|
||||||
<article
|
|
||||||
class="delay-[3000ms] duration-700 transition-all relative z-[11] mb-1.5 flex items-start space-x-4 rounded-xl p-2.5"
|
|
||||||
:class="{'dark:bg-4x-dark-foreground bg-light-background/80': isUnread}"
|
|
||||||
>
|
|
||||||
<gift-icon
|
|
||||||
v-if="notification.data.attributes.category === 'gift'"
|
|
||||||
size="22"
|
|
||||||
class="vue-feather text-theme shrink-0"
|
|
||||||
/>
|
|
||||||
<user-plus-icon
|
|
||||||
v-if="notification.data.attributes.category === 'team-invitation'"
|
|
||||||
size="22"
|
|
||||||
class="vue-feather text-theme shrink-0"
|
|
||||||
/>
|
|
||||||
<trending-up-icon
|
|
||||||
v-if="notification.data.attributes.category === 'subscription-created'"
|
|
||||||
size="22"
|
|
||||||
class="vue-feather text-theme shrink-0"
|
|
||||||
/>
|
|
||||||
<alert-triangle-icon
|
|
||||||
v-if="['billing-alert', 'insufficient-balance'].includes(notification.data.attributes.category)"
|
|
||||||
size="22"
|
|
||||||
class="vue-feather text-theme shrink-0"
|
|
||||||
/>
|
|
||||||
<upload-cloud-icon
|
|
||||||
v-if="['file-request', 'remote-upload-done'].includes(notification.data.attributes.category)"
|
|
||||||
size="22"
|
|
||||||
class="vue-feather text-theme shrink-0"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b class="mb-1.5 block font-extrabold">
|
|
||||||
{{ notification.data.attributes.title }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<p class="mb-1.5 text-sm dark:text-gray-500">
|
|
||||||
{{ notification.data.attributes.description }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="flex items-center">
|
|
||||||
<!--<MemberAvatar class="mr-2" :size="22" :is-border="false" :member="user" />-->
|
|
||||||
<time class="block text-xs text-gray-400 dark:text-gray-400">
|
|
||||||
{{ notification.data.attributes.created_at }}
|
|
||||||
</time>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Accept or decline team invitation-->
|
|
||||||
<div v-if="action && action.type === 'invitation'" class="flex items-center space-x-3 mt-4">
|
|
||||||
<div
|
|
||||||
@click="acceptAction"
|
|
||||||
class="relative flex cursor-pointer items-center rounded-xl py-1.5 px-2 transition-colors bg-green-100 dark:bg-green-900"
|
|
||||||
>
|
|
||||||
<refresh-cw-icon v-if="isAccepting" size="16" class="animate-spin left-0 right-0 mx-auto vue-feather text-green-600 dark:text-green-600 absolute justify-center" />
|
|
||||||
<check-icon size="16" class="vue-feather mr-1 text-green-600 dark:text-green-600" :class="{'opacity-0': isAccepting}" />
|
|
||||||
<span class="text-sm font-bold text-green-600 dark:text-green-600" :class="{'opacity-0': isAccepting}">
|
|
||||||
{{ $t('accept') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
@click="declineAction"
|
|
||||||
class="relative flex cursor-pointer items-center rounded-xl py-1.5 px-2 transition-colors bg-rose-100 dark:bg-rose-900"
|
|
||||||
>
|
|
||||||
<refresh-cw-icon v-if="isDeclining" size="16" class="animate-spin left-0 right-0 mx-auto vue-feather text-rose-600 dark:text-rose-600 absolute justify-center" />
|
|
||||||
<x-icon size="16" class="vue-feather mr-1 text-rose-600 dark:text-rose-600" :class="{'opacity-0': isDeclining}" />
|
|
||||||
<span class="text-sm font-bold text-rose-600 dark:text-rose-600 capitalize" :class="{'opacity-0': isDeclining}">
|
|
||||||
{{ $t('decline') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Go to route-->
|
|
||||||
<router-link
|
|
||||||
@click.native="closeCenter"
|
|
||||||
v-if="action && action.type === 'route'"
|
|
||||||
:to="{ name: action.params.route, params: { id: action.params.id } }"
|
|
||||||
class="mt-4 flex items-center"
|
|
||||||
>
|
|
||||||
<span class="mr-2 whitespace-nowrap text-xs font-bold">
|
|
||||||
{{ action.params.button }}
|
|
||||||
</span>
|
|
||||||
<chevron-right-icon size="16" class="text-theme vue-feather" />
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { RefreshCwIcon, TrendingUpIcon, GiftIcon, CheckIcon, XIcon, MailIcon, UserPlusIcon, UploadCloudIcon, ChevronRightIcon, AlertTriangleIcon } from 'vue-feather-icons'
|
|
||||||
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
|
||||||
import {events} from "../../../bus";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Notification',
|
|
||||||
props: ['notification'],
|
|
||||||
components: {
|
|
||||||
MemberAvatar,
|
|
||||||
AlertTriangleIcon,
|
|
||||||
ChevronRightIcon,
|
|
||||||
UploadCloudIcon,
|
|
||||||
TrendingUpIcon,
|
|
||||||
RefreshCwIcon,
|
|
||||||
UserPlusIcon,
|
|
||||||
CheckIcon,
|
|
||||||
GiftIcon,
|
|
||||||
MailIcon,
|
|
||||||
XIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
action() {
|
|
||||||
return this.notification.data.attributes.action
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isUnread: false,
|
|
||||||
isAccepting: false,
|
|
||||||
isDeclining: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
acceptAction() {
|
|
||||||
this.isAccepting = true
|
|
||||||
|
|
||||||
axios.put(`/api/teams/invitations/${this.notification.data.attributes.action.params.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$store.commit('CLEAR_NOTIFICATION_ACTION_DATA', this.notification.data.id)
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('you_accepted_invitation'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => this.isAccepting = false)
|
|
||||||
},
|
|
||||||
declineAction() {
|
|
||||||
this.isDeclining = true
|
|
||||||
|
|
||||||
axios.delete(`/api/teams/invitations/${this.notification.data.attributes.action.params.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$store.commit('CLEAR_NOTIFICATION_ACTION_DATA', this.notification.data.id)
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('you_decline_invitation'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => this.isDeclining = false)
|
|
||||||
},
|
|
||||||
closeCenter() {
|
|
||||||
this.$store.commit('CLOSE_NOTIFICATION_CENTER')
|
|
||||||
this.$closePopup()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.isUnread = this.notification.data.attributes.read_at === null
|
|
||||||
|
|
||||||
setTimeout(() => this.isUnread = false, 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="relative button-icon inline-block cursor-pointer rounded-xl p-3">
|
|
||||||
<bell-icon size="18" class="vue-feather dark:text-gray-100 transition" :class="{'rotate-[30deg]': notificationCount}" />
|
|
||||||
<span v-if="notificationCount" class="absolute z-[9] right-1.5 bottom-1.5 flex items-center justify-center w-4 h-4 bg-theme text-white rounded-full text-xs font-bold">
|
|
||||||
{{ notificationCount }}
|
|
||||||
</span>
|
|
||||||
<span v-if="notificationCount" class="animate-ping absolute z-[8] right-1.5 bottom-1.5 flex items-center justify-center w-4 h-4 bg-theme text-white rounded-full text-xs font-bold"></span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
import {BellIcon} from "vue-feather-icons"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'NotificationBell',
|
|
||||||
components: {
|
|
||||||
BellIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters([
|
|
||||||
'notificationCount'
|
|
||||||
]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
<template>
|
|
||||||
<transition name="popup">
|
|
||||||
<div class="fixed popup z-20 top-[27px] bottom-[27px] left-20 w-[360px]">
|
|
||||||
|
|
||||||
<!--Triangle-->
|
|
||||||
<div class="z-20 absolute left-0 top-[64px] w-4 translate-x-[-15px] overflow-hidden inline-block" :class="{'!top-[102px]': config.subscriptionType === 'metered'}">
|
|
||||||
<div class="h-12 -rotate-45 transform origin-top-right dark:bg-2x-dark-foreground bg-white bg-opacity-80 backdrop-blur-2xl"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-click-outside="clickOutside" class="dark:bg-2x-dark-foreground bg-white dark:bg-opacity-80 dark:backdrop-blur-2xl bg-opacity-80 backdrop-blur-2xl shadow-xl rounded-xl text-left p-3 overflow-y-auto max-h-full">
|
|
||||||
|
|
||||||
<!--Title-->
|
|
||||||
<b class="dark:text-gray-200 text-xl font-extrabold px-2.5 mb-2.5 block">
|
|
||||||
{{ $t('notification_center') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<div class="px-2.5">
|
|
||||||
<MobileActionButton v-if="readNotifications.length || unreadNotifications.length" @click.native="$store.dispatch('deleteAllNotifications')" icon="check-square" class="mb-2 dark:!bg-4x-dark-foreground">
|
|
||||||
{{ $t('clear_all') }}
|
|
||||||
</MobileActionButton>
|
|
||||||
|
|
||||||
<p v-if="!readNotifications.length && !unreadNotifications.length" class="text-sm mt-8">
|
|
||||||
{{ $t("not_any_notifications") }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<b v-if="unreadNotifications.length" class="dark-text-theme mt-1.5 block px-2.5 mb-2.5 text-xs text-gray-400">
|
|
||||||
{{ $t('unread') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<Notification :notification="notification" v-for="notification in unreadNotifications" :key="notification.id" />
|
|
||||||
|
|
||||||
<b v-if="readNotifications.length" class="dark-text-theme mt-2.5 block px-2.5 mb-2.5 text-xs text-gray-400">
|
|
||||||
{{ $t('read') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<Notification :notification="notification" v-for="notification in readNotifications" :key="notification.id" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MobileActionButton from "../UI/Buttons/MobileActionButton"
|
|
||||||
import Notification from "./Components/Notification"
|
|
||||||
import vClickOutside from 'v-click-outside'
|
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'NotificationCenter',
|
|
||||||
components: {
|
|
||||||
MobileActionButton,
|
|
||||||
Notification
|
|
||||||
},
|
|
||||||
directives: {
|
|
||||||
clickOutside: vClickOutside.directive
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters([
|
|
||||||
'user', 'config', 'isVisibleNotificationCenter',
|
|
||||||
]),
|
|
||||||
readNotifications() {
|
|
||||||
return this.user.data.relationships.readNotifications.data
|
|
||||||
},
|
|
||||||
unreadNotifications() {
|
|
||||||
return this.user.data.relationships.unreadNotifications.data
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
clickOutside() {
|
|
||||||
if (this.isVisibleNotificationCenter)
|
|
||||||
this.$store.commit('CLOSE_NOTIFICATION_CENTER')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.$store.dispatch('readAllNotifications')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.popup-leave-active {
|
|
||||||
animation: popup-slide-in 0.15s ease reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-enter-active {
|
|
||||||
animation: popup-slide-in 0.25s 0.1s ease both;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes popup-slide-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(50px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="notifications-mobile">
|
|
||||||
<!--Title-->
|
|
||||||
<PopupHeader :title="$t('notifications')" icon="bell" />
|
|
||||||
|
|
||||||
<!--Content-->
|
|
||||||
<PopupContent v-if="readNotifications && unreadNotifications">
|
|
||||||
<MobileActionButton
|
|
||||||
v-if="readNotifications.length || unreadNotifications.length"
|
|
||||||
@click.native="$store.dispatch('deleteAllNotifications')"
|
|
||||||
icon="check-square"
|
|
||||||
class="mb-2 dark:!bg-4x-dark-foreground"
|
|
||||||
>
|
|
||||||
{{ $t('clear_all') }}
|
|
||||||
</MobileActionButton>
|
|
||||||
|
|
||||||
<p v-if="!readNotifications.length && !unreadNotifications.length" class="text-sm text-gray-500">
|
|
||||||
{{ $t("not_any_notifications") }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<b
|
|
||||||
v-if="unreadNotifications.length"
|
|
||||||
class="dark-text-theme mt-1.5 mb-2.5 block px-2.5 text-xs text-gray-400"
|
|
||||||
>
|
|
||||||
{{ $t('unread') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<Notification
|
|
||||||
:notification="notification"
|
|
||||||
v-for="notification in unreadNotifications"
|
|
||||||
:key="notification.id"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<b v-if="readNotifications.length" class="dark-text-theme mt-2.5 mb-2.5 block px-2.5 text-xs text-gray-400">
|
|
||||||
{{ $t('read') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<Notification
|
|
||||||
:notification="notification"
|
|
||||||
v-for="notification in readNotifications"
|
|
||||||
:key="notification.id"
|
|
||||||
/>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
|
||||||
{{ $t('close') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MobileActionButton from '../UI/Buttons/MobileActionButton'
|
|
||||||
import Notification from './Components/Notification'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import PopupWrapper from '../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../Popups/Components/PopupHeader'
|
|
||||||
import vClickOutside from 'v-click-outside'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'NotificationsPopup',
|
|
||||||
components: {
|
|
||||||
MobileActionButton,
|
|
||||||
Notification,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
},
|
|
||||||
directives: {
|
|
||||||
clickOutside: vClickOutside.directive,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user', 'config']),
|
|
||||||
readNotifications() {
|
|
||||||
return this.user?.data.relationships.readNotifications.data
|
|
||||||
},
|
|
||||||
unreadNotifications() {
|
|
||||||
return this.user?.data.relationships.unreadNotifications.data
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
clickOutside() {
|
|
||||||
if (this.isVisibleNotificationCenter) this.$store.commit('CLOSE_NOTIFICATION_CENTER')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="remote-upload">
|
|
||||||
<PopupHeader :title="$t('upload_files_remotely')" icon="remote-upload" />
|
|
||||||
|
|
||||||
<PopupContent>
|
|
||||||
<ValidationObserver @submit.prevent ref="createForm" v-slot="{ invalid }" tag="form">
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Remote Links" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText
|
|
||||||
:title="$t('remote_links')"
|
|
||||||
:description="$t('remote_links_help')"
|
|
||||||
:error="errors[0]"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
v-model="links"
|
|
||||||
class="focus-border-theme input-dark whitespace-nowrap"
|
|
||||||
rows="6"
|
|
||||||
:placeholder="$t('paste_remote_links_here')"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
ref="textarea"
|
|
||||||
>
|
|
||||||
</textarea>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
|
||||||
{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase class="w-full" @click.native="upload" button-style="theme" :loading="loading">
|
|
||||||
{{ $t('upload') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import PopupWrapper from '../Popups/Components/PopupWrapper'
|
|
||||||
import PopupContent from '../Popups/Components/PopupContent'
|
|
||||||
import PopupActions from '../Popups/Components/PopupActions'
|
|
||||||
import PopupHeader from '../Popups/Components/PopupHeader'
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import { required } from 'vee-validate/dist/rules'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import i18n from "../../i18n";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'RemoteUploadPopup',
|
|
||||||
components: {
|
|
||||||
ValidationProvider,
|
|
||||||
ValidationObserver,
|
|
||||||
required,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
PopupActions,
|
|
||||||
AppInputText,
|
|
||||||
ButtonBase,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
links: undefined,
|
|
||||||
loading: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async upload() {
|
|
||||||
// Validate fields
|
|
||||||
const isValid = await this.$refs.createForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.loading = true
|
|
||||||
|
|
||||||
this.urls = this.links
|
|
||||||
.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, "")
|
|
||||||
.split(/\r?\n/)
|
|
||||||
|
|
||||||
// If demo, return success message
|
|
||||||
if (this.$store.getters.config.isDemo && this.$store.getters.user.data.attributes.email === 'ho**@hi5ve.digital') {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: i18n.t('remote_download_finished'),
|
|
||||||
})
|
|
||||||
|
|
||||||
events.$emit('popup:close')
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If broadcasting
|
|
||||||
if (this.$store.getters.isBroadcasting) {
|
|
||||||
this.$store.commit('UPDATE_REMOTE_UPLOAD_QUEUE', {
|
|
||||||
progress: {
|
|
||||||
total: this.urls.length,
|
|
||||||
processed: 0,
|
|
||||||
failed: 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get route
|
|
||||||
let route = {
|
|
||||||
RequestUpload: `/api/upload-request/${this.$router.currentRoute.params.token}/upload/remote`,
|
|
||||||
Public: `/api/editor/upload/remote/${this.$router.currentRoute.params.token}`,
|
|
||||||
}[this.$router.currentRoute.name] || '/api/upload/remote'
|
|
||||||
|
|
||||||
let parentId = this.$store.getters.currentFolder
|
|
||||||
? this.$store.getters.currentFolder.data.id
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post(route, {
|
|
||||||
urls: this.urls,
|
|
||||||
parent_id: parentId,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// If broadcasting is not set
|
|
||||||
if (!this.$store.getters.isBroadcasting) {
|
|
||||||
// Reload data
|
|
||||||
this.$getDataByLocation()
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: i18n.t('remote_download_finished'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
events.$emit('popup:close')
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
if (error.response.status === 422) {
|
|
||||||
this.$refs.createForm.setErrors({
|
|
||||||
'Remote Links': error.response.data.message,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
events.$on('popup:open', (args) => {
|
|
||||||
if (args.name !== 'remote-upload') return
|
|
||||||
|
|
||||||
this.links = undefined
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
setTimeout(() => this.$refs.textarea.focus(), 100)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<template>
|
|
||||||
<transition name="popup">
|
|
||||||
<div v-if="remoteUploadQueue" class="fixed left-0 right-0 bottom-8 text-center select-none pointer-events-none z-10">
|
|
||||||
<div class="relative inline-block rounded-lg overflow-hidden bg-theme shadow-lg px-3 py-2">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<RefreshCwIcon size="14" class="vue-feather text-white animate-[spin_2s_linear_infinite] z-10 relative" />
|
|
||||||
<span class="text-xs font-bold text-white z-10 relative ml-2 dark:text-black">
|
|
||||||
{{ this.$t('remote_upload_progress', {processed: remoteUploadQueue.processed, total: remoteUploadQueue.total}) }}{{ remoteUploadQueue.failed > 0 ? ", " + this.$t('remote_upload_failed_count', {count: remoteUploadQueue.failed}) : '' }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span class="absolute w-full h-full top-0 bottom-0 left-0 right-0 block bg-theme brightness-125 animate-[pulse_3s_ease-in-out_infinite] z-[5]"></span>
|
|
||||||
<span class="absolute w-full h-full top-0 bottom-0 left-0 right-0 block bg-theme z-0"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import {RefreshCwIcon} from "vue-feather-icons";
|
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'RemoteUploadProgress',
|
|
||||||
components: {
|
|
||||||
RefreshCwIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters([
|
|
||||||
'remoteUploadQueue'
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.popup-leave-active {
|
|
||||||
animation: popup-slide-in 0.15s ease reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-enter-active {
|
|
||||||
animation: popup-slide-in 0.25s 0.1s ease both;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes popup-slide-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(100px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -7,26 +7,6 @@
|
|||||||
<div v-if="user" class="mb-auto text-center">
|
<div v-if="user" class="mb-auto text-center">
|
||||||
<MemberAvatar class="mx-auto" :size="44" :is-border="false" :member="user" />
|
<MemberAvatar class="mx-auto" :size="44" :is-border="false" :member="user" />
|
||||||
|
|
||||||
<!--Usage-->
|
|
||||||
<div
|
|
||||||
v-if="config.subscriptionType === 'metered' && user.data.meta.usages"
|
|
||||||
class="mt-2.5 text-center leading-3"
|
|
||||||
>
|
|
||||||
<b class="text-theme block text-xs font-bold leading-3">
|
|
||||||
{{ user.data.meta.usages.costEstimate }}
|
|
||||||
</b>
|
|
||||||
<span class="text-xs text-gray-500">
|
|
||||||
{{ $t('usage') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Navigation-->
|
|
||||||
<div class="mt-2 relative">
|
|
||||||
<NotificationBell @click.native="$store.commit('TOGGLE_NOTIFICATION_CENTER')" class="hover:bg-light-300 dark:hover:bg-4x-dark-foreground" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<NotificationCenter v-if="isVisibleNotificationCenter" />
|
|
||||||
|
|
||||||
<!--Navigation-->
|
<!--Navigation-->
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<router-link
|
<router-link
|
||||||
@@ -75,14 +55,10 @@
|
|||||||
import MemberAvatar from '../UI/Others/MemberAvatar'
|
import MemberAvatar from '../UI/Others/MemberAvatar'
|
||||||
import {mapGetters} from 'vuex'
|
import {mapGetters} from 'vuex'
|
||||||
import {HardDriveIcon, MoonIcon, PowerIcon, SettingsIcon, SunIcon, UserIcon,} from 'vue-feather-icons'
|
import {HardDriveIcon, MoonIcon, PowerIcon, SettingsIcon, SunIcon, UserIcon,} from 'vue-feather-icons'
|
||||||
import NotificationCenter from "../Notifications/NotificationCenter"
|
|
||||||
import NotificationBell from "../Notifications/Components/NotificationBell";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SidebarNavigation',
|
name: 'SidebarNavigation',
|
||||||
components: {
|
components: {
|
||||||
NotificationBell,
|
|
||||||
NotificationCenter,
|
|
||||||
HardDriveIcon,
|
HardDriveIcon,
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
MemberAvatar,
|
MemberAvatar,
|
||||||
@@ -92,7 +68,7 @@ export default {
|
|||||||
SunIcon,
|
SunIcon,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['isVisibleNavigationBars', 'isDarkMode', 'config', 'user', 'isVisibleNotificationCenter']),
|
...mapGetters(['isVisibleNavigationBars', 'isDarkMode', 'config', 'user']),
|
||||||
navigation() {
|
navigation() {
|
||||||
if (this.user.data.attributes.role === 'admin') {
|
if (this.user.data.attributes.role === 'admin') {
|
||||||
return [
|
return [
|
||||||
@@ -133,11 +109,6 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isNotificationCenter: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
isSection(section) {
|
isSection(section) {
|
||||||
return this.$route.matched[0].name === section
|
return this.$route.matched[0].name === section
|
||||||
|
|||||||
@@ -99,11 +99,6 @@
|
|||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<credit-card-icon
|
|
||||||
v-if="result.action.value === 'AppPayments'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<home-icon
|
<home-icon
|
||||||
v-if="result.action.value === 'Files'"
|
v-if="result.action.value === 'Files'"
|
||||||
size="18"
|
size="18"
|
||||||
@@ -114,23 +109,13 @@
|
|||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<database-icon
|
|
||||||
v-if="['CreateFixedPlan', 'CreateMeteredPlan'].includes(result.action.value)"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<user-plus-icon
|
<user-plus-icon
|
||||||
v-if="result.action.value === 'UserCreate'"
|
v-if="result.action.value === 'UserCreate'"
|
||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<users-icon
|
<users-icon
|
||||||
v-if="['TeamFolders', 'Users'].includes(result.action.value)"
|
v-if="['Users'].includes(result.action.value)"
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<user-check-icon
|
|
||||||
v-if="result.action.value === 'SharedWithMe'"
|
|
||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
@@ -139,41 +124,16 @@
|
|||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<link2-icon
|
|
||||||
v-if="result.action.value === 'remote-upload'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<upload-cloud-icon
|
<upload-cloud-icon
|
||||||
v-if="result.action.value === 'RecentUploads'"
|
v-if="result.action.value === 'RecentUploads'"
|
||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<file-text-icon
|
|
||||||
v-if="['Invoices', 'Invoice'].includes(result.action.value)"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<database-icon
|
|
||||||
v-if="result.action.value === 'Plans'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<dollar-sign-icon
|
|
||||||
v-if="['Subscriptions', 'Billing'].includes(result.action.value)"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<globe-icon
|
<globe-icon
|
||||||
v-if="result.action.value === 'Language'"
|
v-if="result.action.value === 'Language'"
|
||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<monitor-icon
|
|
||||||
v-if="result.action.value === 'Pages'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<box-icon
|
<box-icon
|
||||||
v-if="result.action.value === 'Dashboard'"
|
v-if="result.action.value === 'Dashboard'"
|
||||||
size="18"
|
size="18"
|
||||||
@@ -214,16 +174,6 @@
|
|||||||
size="18"
|
size="18"
|
||||||
class="vue-feather text-theme"
|
class="vue-feather text-theme"
|
||||||
/>
|
/>
|
||||||
<folder-plus-icon
|
|
||||||
v-if="result.action.value === 'create-team-folder'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
<upload-cloud-icon
|
|
||||||
v-if="result.action.value === 'create-file-request'"
|
|
||||||
size="18"
|
|
||||||
class="vue-feather text-theme"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<b class="ml-3.5 text-sm font-bold">
|
<b class="ml-3.5 text-sm font-bold">
|
||||||
{{ result.title }}
|
{{ result.title }}
|
||||||
@@ -397,20 +347,6 @@ export default {
|
|||||||
value: 'AppOthers',
|
value: 'AppOthers',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('go_to_payments'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'AppPayments',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('go_to_pages'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'Pages',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('go_to_languages'),
|
title: this.$t('go_to_languages'),
|
||||||
action: {
|
action: {
|
||||||
@@ -425,20 +361,6 @@ export default {
|
|||||||
value: 'Users',
|
value: 'Users',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('show_all_plans'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'Plans',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('show_transactions'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'Invoices',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('application_settings'),
|
title: this.$t('application_settings'),
|
||||||
action: {
|
action: {
|
||||||
@@ -446,13 +368,6 @@ export default {
|
|||||||
value: 'AppOthers',
|
value: 'AppOthers',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('login_registration_settings'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'AppSignInUp',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('appearance_settings'),
|
title: this.$t('appearance_settings'),
|
||||||
action: {
|
action: {
|
||||||
@@ -460,20 +375,6 @@ export default {
|
|||||||
value: 'AppAppearance',
|
value: 'AppAppearance',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('adsense_settings'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'AppAdsense',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('homepage_settings'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'AppIndex',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('environment_settings'),
|
title: this.$t('environment_settings'),
|
||||||
action: {
|
action: {
|
||||||
@@ -519,20 +420,6 @@ export default {
|
|||||||
value: 'Trash',
|
value: 'Trash',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('go_to_team_folders'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'TeamFolders',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('go_to_shared_with_me'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'SharedWithMe',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let adminActions = [
|
let adminActions = [
|
||||||
@@ -567,13 +454,6 @@ export default {
|
|||||||
value: 'Storage',
|
value: 'Storage',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: this.$t('show_billing'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'Billing',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('empty_your_trash'),
|
title: this.$t('empty_your_trash'),
|
||||||
action: {
|
action: {
|
||||||
@@ -590,29 +470,7 @@ export default {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
let createList = [
|
let createList = []
|
||||||
{
|
|
||||||
title: this.$t('create_team_folder'),
|
|
||||||
action: {
|
|
||||||
type: 'function',
|
|
||||||
value: 'create-team-folder',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('create_file_request'),
|
|
||||||
action: {
|
|
||||||
type: 'function',
|
|
||||||
value: 'create-file-request',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('remote_upload'),
|
|
||||||
action: {
|
|
||||||
type: 'function',
|
|
||||||
value: 'remote-upload',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
let functionList = [
|
let functionList = [
|
||||||
{
|
{
|
||||||
@@ -656,31 +514,6 @@ export default {
|
|||||||
|
|
||||||
// Return commands for logged admin
|
// Return commands for logged admin
|
||||||
if (this.isAdmin) {
|
if (this.isAdmin) {
|
||||||
// Available only for fixed subscription
|
|
||||||
if (this.config.subscriptionType === 'fixed') {
|
|
||||||
adminLocations.push({
|
|
||||||
title: this.$t('show_all_subscriptions'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: 'Subscriptions',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Available only when is metered billing and plan doesnt exist or when is fixed billing
|
|
||||||
if (
|
|
||||||
(this.config.subscriptionType === 'metered' && !this.config.isCreatedMeteredPlan) ||
|
|
||||||
this.config.subscriptionType === 'fixed'
|
|
||||||
) {
|
|
||||||
adminActions.push({
|
|
||||||
title: this.$t('create_plan'),
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
value: this.config.subscriptionType === 'fixed' ? 'CreateFixedPlan' : 'CreateMeteredPlan',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return [].concat.apply(
|
return [].concat.apply(
|
||||||
[],
|
[],
|
||||||
[functionList, createList, userSettings, fileLocations, adminLocations, adminActions]
|
[functionList, createList, userSettings, fileLocations, adminLocations, adminActions]
|
||||||
@@ -819,18 +652,6 @@ export default {
|
|||||||
if (arg.action.value === 'empty-trash') {
|
if (arg.action.value === 'empty-trash') {
|
||||||
this.$emptyTrashQuietly()
|
this.$emptyTrashQuietly()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.action.value === 'create-team-folder') {
|
|
||||||
this.$createTeamFolder()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.action.value === 'create-file-request') {
|
|
||||||
this.$createFileRequest()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.action.value === 'remote-upload') {
|
|
||||||
this.$openRemoteUploadPopup()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.exitSpotlight()
|
this.exitSpotlight()
|
||||||
@@ -854,15 +675,6 @@ export default {
|
|||||||
id: file.data.id,
|
id: file.data.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else if (file.data.attributes.isTeamFolder) {
|
|
||||||
let route = file.data.relationships.user.data.id === this.user.data.id
|
|
||||||
? 'TeamFolders'
|
|
||||||
: 'SharedWithMe'
|
|
||||||
|
|
||||||
this.$router.push({
|
|
||||||
name: route,
|
|
||||||
params: { id: file.data.id },
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'Files',
|
name: 'Files',
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<tr class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
|
|
||||||
<td class="py-5 pr-3 md:pr-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.note }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td v-if="user" class="whitespace-nowrap px-3 md:px-1">
|
|
||||||
<div v-if="row.data.relationships.user" class="flex items-center">
|
|
||||||
<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"
|
|
||||||
>
|
|
||||||
{{ row.data.relationships.user.data.attributes.name }}
|
|
||||||
</b>
|
|
||||||
<span class="block text-xs text-gray-600 dark:text-gray-500">
|
|
||||||
{{ row.data.relationships.user.data.attributes.email }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span v-if="!row.data.relationships.user" class="text-xs font-bold text-gray-500">
|
|
||||||
{{ $t('user_was_deleted') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<ColorLabel class="capitalize" :color="$getTransactionStatusColor(row.data.attributes.status)">
|
|
||||||
{{ $t(row.data.attributes.status) }}
|
|
||||||
</ColorLabel>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold" :class="$getTransactionTypeTextColor(row.data.attributes.type)">
|
|
||||||
{{ $getTransactionMark(row.data.attributes.type) + row.data.attributes.price }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.created_at }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<div class="w-28">
|
|
||||||
<img
|
|
||||||
class="inline-block max-h-5"
|
|
||||||
:src="$getPaymentLogo(row.data.attributes.driver)"
|
|
||||||
:alt="row.data.attributes.driver"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="pl-3 text-right md:pl-1">
|
|
||||||
<div class="inline-block">
|
|
||||||
<a
|
|
||||||
:href="$getInvoiceLink(row.data.id)"
|
|
||||||
target="_blank"
|
|
||||||
class="inline-block flex h-8 w-8 cursor-pointer items-center justify-center rounded-md bg-light-background transition-colors hover:bg-purple-100 dark:bg-2x-dark-foreground"
|
|
||||||
>
|
|
||||||
<FileTextIcon size="15" class="opacity-75" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import MemberAvatar from '../UI/Others/MemberAvatar'
|
|
||||||
import MeteredTransactionDetailRow from './MeteredTransactionDetailRow'
|
|
||||||
import ColorLabel from '../UI/Labels/ColorLabel'
|
|
||||||
import { EyeIcon, FileTextIcon } from 'vue-feather-icons'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'FixedTransactionRow',
|
|
||||||
components: {
|
|
||||||
MeteredTransactionDetailRow,
|
|
||||||
MemberAvatar,
|
|
||||||
FileTextIcon,
|
|
||||||
ColorLabel,
|
|
||||||
EyeIcon,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
row: {},
|
|
||||||
user: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showedTransactionDetailById: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showTransactionDetail(id) {
|
|
||||||
if (this.showedTransactionDetailById === id) this.showedTransactionDetailById = undefined
|
|
||||||
else this.showedTransactionDetailById = id
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<tr>
|
|
||||||
<td colspan="10" class="overflow-hidden rounded-lg py-2">
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between border-b border-dashed border-light py-2 dark:border-opacity-5"
|
|
||||||
v-for="(usage, i) in row.data.attributes.metadata"
|
|
||||||
:key="i"
|
|
||||||
>
|
|
||||||
<div class="w-2/4 leading-none">
|
|
||||||
<b class="text-sm font-bold leading-none">
|
|
||||||
{{ $t(usage.feature) }}
|
|
||||||
</b>
|
|
||||||
<small class="hidden pt-2 text-xs leading-none text-gray-500 sm:block">
|
|
||||||
{{ $t(`feature_usage_desc_${usage.feature}`) }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-left">
|
|
||||||
<span class="text-gray-560 text-sm font-bold">
|
|
||||||
{{ usage.usage }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-right">
|
|
||||||
<span class="text-theme text-sm font-bold">
|
|
||||||
{{ usage.cost }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'MeteredTransactionDetailRow',
|
|
||||||
props: ['row'],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
<template>
|
|
||||||
<tr class="whitespace-nowrap border-b border-dashed border-light dark:border-opacity-5">
|
|
||||||
<td class="py-5 pr-3 md:pr-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.note }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td v-if="user" class="whitespace-nowrap px-3 md:px-1">
|
|
||||||
<div v-if="row.data.relationships.user" class="flex items-center">
|
|
||||||
<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"
|
|
||||||
>
|
|
||||||
{{ row.data.relationships.user.data.attributes.name }}
|
|
||||||
</b>
|
|
||||||
<span class="block text-xs text-gray-600 dark:text-gray-500">
|
|
||||||
{{ row.data.relationships.user.data.attributes.email }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span v-if="!row.data.relationships.user" class="text-xs font-bold text-gray-500">
|
|
||||||
{{ $t('user_was_deleted') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<ColorLabel class="capitalize" :color="$getTransactionStatusColor(row.data.attributes.status)">
|
|
||||||
{{ $t(row.data.attributes.status) }}
|
|
||||||
</ColorLabel>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold capitalize">
|
|
||||||
{{ $t(row.data.attributes.type) }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold" :class="$getTransactionTypeTextColor(row.data.attributes.type)">
|
|
||||||
{{ $getTransactionMark(row.data.attributes.type) + row.data.attributes.price }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.created_at }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<div class="w-28">
|
|
||||||
<img
|
|
||||||
class="inline-block max-h-5"
|
|
||||||
:src="$getPaymentLogo(row.data.attributes.driver)"
|
|
||||||
:alt="row.data.attributes.driver"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="pl-3 text-right md:pl-1">
|
|
||||||
<div v-if="row.data.attributes.metadata" class="flex w-full justify-end space-x-2">
|
|
||||||
<div
|
|
||||||
@click="$emit('showDetail', row.data.id)"
|
|
||||||
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded-md bg-light-background transition-colors hover:bg-green-100 dark:bg-2x-dark-foreground"
|
|
||||||
>
|
|
||||||
<EyeIcon size="15" class="opacity-75" />
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
:href="$getInvoiceLink(row.data.id)"
|
|
||||||
target="_blank"
|
|
||||||
class="flex h-8 w-8 cursor-pointer items-center justify-center rounded-md bg-light-background transition-colors hover:bg-purple-100 dark:bg-2x-dark-foreground"
|
|
||||||
>
|
|
||||||
<FileTextIcon size="15" class="opacity-75" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div v-else>-</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import MemberAvatar from '../UI/Others/MemberAvatar'
|
|
||||||
import MeteredTransactionDetailRow from './MeteredTransactionDetailRow'
|
|
||||||
import ColorLabel from '../UI/Labels/ColorLabel'
|
|
||||||
import { EyeIcon, FileTextIcon } from 'vue-feather-icons'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MeteredTransactionRow',
|
|
||||||
components: {
|
|
||||||
MeteredTransactionDetailRow,
|
|
||||||
MemberAvatar,
|
|
||||||
FileTextIcon,
|
|
||||||
ColorLabel,
|
|
||||||
EyeIcon,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
row: {},
|
|
||||||
user: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showedTransactionDetailById: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showTransactionDetail(id) {
|
|
||||||
if (this.showedTransactionDetailById === id) this.showedTransactionDetailById = undefined
|
|
||||||
else this.showedTransactionDetailById = id
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between rounded-lg bg-light-background py-3 px-2 dark:bg-2x-dark-foreground md:px-4"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<img :src="`/assets/gateways/${card.data.attributes.brand}.svg`" alt="" class="mr-3 h-5 rounded" />
|
|
||||||
<b class="whitespace-nowrap text-sm font-bold capitalize leading-none">
|
|
||||||
{{ card.data.attributes.brand }} ••••
|
|
||||||
{{ card.data.attributes.last4 }}
|
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
<b class="text-sm font-bold leading-none"> {{ $t('expires') }} {{ card.data.attributes.expiration }} </b>
|
|
||||||
<Trash2Icon @click="deleteCreditCard(card.data.id)" size="15" class="cursor-pointer" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { Trash2Icon } from 'vue-feather-icons'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PaymentCard',
|
|
||||||
components: {
|
|
||||||
Trash2Icon,
|
|
||||||
},
|
|
||||||
props: ['card'],
|
|
||||||
methods: {
|
|
||||||
deleteCreditCard(id) {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: this.$t('want_to_delete_card_title'),
|
|
||||||
message: this.$t('want_to_delete_card_description'),
|
|
||||||
action: {
|
|
||||||
id: id,
|
|
||||||
operation: 'delete-credit-card',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('action:confirmed', (data) => {
|
|
||||||
if (data.operation === 'delete-credit-card')
|
|
||||||
axios
|
|
||||||
.delete(`/api/stripe/credit-cards/${data.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('credit_card_deleted'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => this.$isSomethingWrong())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
events.$off('action:confirmed')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex items-center justify-between border-b border-dashed border-light py-4 dark:border-opacity-5">
|
|
||||||
<div>
|
|
||||||
<img :src="$getPaymentLogo(driver)" :alt="driver" class="h-6" />
|
|
||||||
<small class="block pt-2 text-xs leading-4 dark:text-gray-500 text-gray-500">
|
|
||||||
{{ description }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div v-if="$slots.default" class="bg-theme-200 relative inline-block rounded-lg px-3 py-1">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'PaymentMethod',
|
|
||||||
props: ['description', 'driver'],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="block cursor-pointer select-none rounded-lg py-3 px-4"
|
|
||||||
:class="{
|
|
||||||
'bg-light-background dark:bg-2x-dark-foreground': isSelected,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div class="mb-1.5 flex items-center justify-between">
|
|
||||||
<CheckBox :is-clicked="isSelected" />
|
|
||||||
<b class="flex-1 pl-4 text-left text-lg">
|
|
||||||
{{ plan.data.attributes.name }}
|
|
||||||
</b>
|
|
||||||
<span
|
|
||||||
class="text-theme bg-theme-100 ml-9 inline-block whitespace-nowrap rounded-xl py-1 px-2 text-sm font-extrabold"
|
|
||||||
>
|
|
||||||
{{ plan.data.attributes.price }} /
|
|
||||||
{{ $t(`interval.${plan.data.attributes.interval}`) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<ul class="ml-9 mb-3">
|
|
||||||
<li class="mb-1.5 flex items-center" v-for="(value, key, i) in plan.data.attributes.features" :key="i">
|
|
||||||
<CheckIcon size="12" class="svg-stroke-theme" />
|
|
||||||
<small class="pl-1.5 text-xs font-bold text-gray-600" v-if="value !== -1">
|
|
||||||
{{ $t(key === 'max_team_members' ? 'max_team_members_total' : key, { value: value }) }}
|
|
||||||
</small>
|
|
||||||
<small class="pl-1.5 text-xs font-bold text-gray-600" v-if="value === -1">
|
|
||||||
{{ $t(`${key}.unlimited`) }}
|
|
||||||
</small>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { CheckIcon } from 'vue-feather-icons'
|
|
||||||
import CheckBox from '../Inputs/CheckBox'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PlanDetail',
|
|
||||||
components: {
|
|
||||||
CheckIcon,
|
|
||||||
CheckBox,
|
|
||||||
},
|
|
||||||
props: ['isSelected', 'plan'],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="mb-2 text-right">
|
|
||||||
<label
|
|
||||||
:class="{ 'text-gray-400': !isSelectedYearlyPlans }"
|
|
||||||
class="cursor-pointer text-xs font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('billed_annually') }}
|
|
||||||
</label>
|
|
||||||
<div class="relative inline-block w-12 select-none align-middle">
|
|
||||||
<SwitchInput
|
|
||||||
class="scale-75 transform"
|
|
||||||
v-model="isSelectedYearlyPlans"
|
|
||||||
:state="isSelectedYearlyPlans"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import SwitchInput from '../Inputs/SwitchInput'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PlanPeriodSwitcher',
|
|
||||||
components: {
|
|
||||||
SwitchInput
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'isSelectedYearlyPlans': function () {
|
|
||||||
this.$emit('input', this.isSelectedYearlyPlans)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isSelectedYearlyPlans: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="change-plan-subscription">
|
|
||||||
<PopupHeader :title="$t('change_your_plan')" icon="credit-card" />
|
|
||||||
|
|
||||||
<!--Select Payment Plans-->
|
|
||||||
<PopupContent v-if="plans">
|
|
||||||
<InfoBox v-if="plans.data.length === 0" class="!mb-0">
|
|
||||||
<p>{{ $t("not_any_plan") }}</p>
|
|
||||||
</InfoBox>
|
|
||||||
|
|
||||||
<!--Toggle yearly billing-->
|
|
||||||
<PlanPeriodSwitcher v-if="yearlyPlans.length > 0" v-model="isSelectedYearlyPlans" />
|
|
||||||
|
|
||||||
<!--List available plans-->
|
|
||||||
<div>
|
|
||||||
<PlanDetail
|
|
||||||
v-for="(plan, i) in plans.data"
|
|
||||||
:plan="plan"
|
|
||||||
:key="plan.data.id"
|
|
||||||
v-if="plan.data.attributes.interval === intervalPlanType"
|
|
||||||
:class="{'opacity-50 pointer-events-none': userSubscribedPlanId === plan.data.id}"
|
|
||||||
:is-selected="selectedPlan && selectedPlan.data.id === plan.data.id"
|
|
||||||
@click.native="selectPlan(plan)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
|
||||||
>{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
|
|
||||||
<ButtonBase
|
|
||||||
class="w-full"
|
|
||||||
v-if="plans && plans.data.length !== 0"
|
|
||||||
:button-style="buttonStyle"
|
|
||||||
:loading="isLoading"
|
|
||||||
@click.native="proceedToPayment"
|
|
||||||
>{{ $t('change_plan') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PopupWrapper from '../../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../../Popups/Components/PopupHeader'
|
|
||||||
import ButtonBase from '../../UI/Buttons/ButtonBase'
|
|
||||||
import PlanDetail from '../PlanDetail'
|
|
||||||
import {mapGetters} from 'vuex'
|
|
||||||
import {events} from '../../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
import Spinner from '../../UI/Others/Spinner'
|
|
||||||
import InfoBox from '../../UI/Others/InfoBox'
|
|
||||||
import PlanPeriodSwitcher from "../PlanPeriodSwitcher";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ChangeSubscriptionPopup',
|
|
||||||
components: {
|
|
||||||
PlanPeriodSwitcher,
|
|
||||||
InfoBox,
|
|
||||||
Spinner,
|
|
||||||
PlanDetail,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
isSelectedYearlyPlans() {
|
|
||||||
this.selectedPlan = undefined
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config', 'user']),
|
|
||||||
intervalPlanType() {
|
|
||||||
return this.isSelectedYearlyPlans ? 'year' : 'month'
|
|
||||||
},
|
|
||||||
buttonStyle() {
|
|
||||||
return this.selectedPlan ? 'theme' : 'secondary'
|
|
||||||
},
|
|
||||||
userSubscribedPlanId() {
|
|
||||||
return (
|
|
||||||
this.user &&
|
|
||||||
this.user.data.relationships.subscription &&
|
|
||||||
this.user.data.relationships.subscription.data.relationships.plan.data.id
|
|
||||||
)
|
|
||||||
},
|
|
||||||
yearlyPlans() {
|
|
||||||
return this.plans.data.filter((plan) => plan.data.attributes.interval === 'year')
|
|
||||||
},
|
|
||||||
subscriptionDriver() {
|
|
||||||
return this.user.data.relationships.subscription.data.attributes.driver
|
|
||||||
},
|
|
||||||
subscription() {
|
|
||||||
return this.user.data.relationships.subscription
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isSelectedYearlyPlans: false,
|
|
||||||
isLoading: false,
|
|
||||||
selectedPlan: undefined,
|
|
||||||
plans: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
proceedToPayment() {
|
|
||||||
// Start button spinner
|
|
||||||
this.isLoading = true
|
|
||||||
|
|
||||||
if (this.subscriptionDriver === 'stripe') {
|
|
||||||
this.payByStripe()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.subscriptionDriver === 'paypal') {
|
|
||||||
this.payByPayPal()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.subscriptionDriver === 'paystack') {
|
|
||||||
this.payByPaystack()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
payByPayPal() {
|
|
||||||
axios.post(`/api/subscriptions/swap/${this.selectedPlan.data.id}`)
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.links[0].href
|
|
||||||
})
|
|
||||||
},
|
|
||||||
payByStripe() {
|
|
||||||
// Subscribe to the new plan
|
|
||||||
if (['inactive', 'cancelled', 'completed'].includes(this.subscription.data.attributes.status)) {
|
|
||||||
axios
|
|
||||||
.post('/api/stripe/checkout', {
|
|
||||||
planCode: this.selectedPlan.data.meta.driver_plan_id.stripe,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.url
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
if (error.response.status === 500 && error.response.data.type) {
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: error.response.data.title,
|
|
||||||
message: error.response.data.message,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$isSomethingWrong()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change active subscription
|
|
||||||
if (this.subscription.data.attributes.status === 'active') {
|
|
||||||
axios
|
|
||||||
.post(`/api/subscriptions/swap/${this.selectedPlan.data.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$closePopup()
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('subscription_changed'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
payByPaystack() {
|
|
||||||
axios
|
|
||||||
.post('/api/paystack/checkout', {
|
|
||||||
planCode: this.selectedPlan.data.meta.driver_plan_id.paystack,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.data.authorization_url
|
|
||||||
})
|
|
||||||
},
|
|
||||||
selectPlan(plan) {
|
|
||||||
this.selectedPlan = plan
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// Load available plans
|
|
||||||
axios.get('/api/subscriptions/plans').then((response) => {
|
|
||||||
this.plans = response.data
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reset states on popup close
|
|
||||||
events.$on('popup:close', () => {
|
|
||||||
this.isSelectedYearlyPlans = false
|
|
||||||
this.selectedPlan = undefined
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="select-payment-method">
|
|
||||||
<PopupHeader :title="$t('select_payment_method')" icon="credit-card" />
|
|
||||||
|
|
||||||
<PopupContent style="padding: 0 20px">
|
|
||||||
<InfoBox v-if="!config.isPayPal && !config.isPaystack" class="!mb-0">
|
|
||||||
<p>{{ $t("not_any_payment_method") }}</p>
|
|
||||||
</InfoBox>
|
|
||||||
|
|
||||||
<!--PayPal implementation-->
|
|
||||||
<div
|
|
||||||
v-if="config.isPayPal"
|
|
||||||
:class="{
|
|
||||||
'mb-2 rounded-xl bg-light-background px-4 dark:bg-2x-dark-foreground': paypal.isMethodsLoaded,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<PaymentMethod
|
|
||||||
@click.native="payByPayPal"
|
|
||||||
driver="paypal"
|
|
||||||
:description="config.paypal_payment_description"
|
|
||||||
>
|
|
||||||
<div v-if="paypal.isMethodLoading" class="translate-y-3 scale-50 transform">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
v-if="!paypal.isMethodsLoaded"
|
|
||||||
:class="{ 'opacity-0': paypal.isMethodLoading }"
|
|
||||||
class="text-theme cursor-pointer text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('select') }}
|
|
||||||
</span>
|
|
||||||
</PaymentMethod>
|
|
||||||
|
|
||||||
<!--PayPal Buttons-->
|
|
||||||
<div id="paypal-button-container"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Paystack implementation-->
|
|
||||||
<PaymentMethod
|
|
||||||
v-if="config.isPaystack"
|
|
||||||
driver="paystack"
|
|
||||||
:description="$t(config.paystack_payment_description)"
|
|
||||||
>
|
|
||||||
<div v-if="paystack.isGettingCheckoutLink" class="translate-y-3 scale-50 transform">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
@click="payByPaystack()"
|
|
||||||
:class="{ 'opacity-0': paystack.isGettingCheckoutLink }"
|
|
||||||
class="text-theme cursor-pointer text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('select') }}
|
|
||||||
</span>
|
|
||||||
</PaymentMethod>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
|
||||||
{{ $t('cancel_payment') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PopupWrapper from '../../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../../Popups/Components/PopupHeader'
|
|
||||||
import ButtonBase from '../../UI/Buttons/ButtonBase'
|
|
||||||
import { loadScript } from '@paypal/paypal-js'
|
|
||||||
import PaymentMethod from '../PaymentMethod'
|
|
||||||
import Spinner from '../../UI/Others/Spinner'
|
|
||||||
import InfoBox from "../../UI/Others/InfoBox"
|
|
||||||
import { events } from '../../../bus'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ChargePaymentPopup',
|
|
||||||
components: {
|
|
||||||
PaymentMethod,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
Spinner,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
paypal: {
|
|
||||||
isMethodsLoaded: false,
|
|
||||||
isMethodLoading: false,
|
|
||||||
},
|
|
||||||
paystack: {
|
|
||||||
isGettingCheckoutLink: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['singleChargeAmount', 'config', 'user']),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
payByPaystack() {
|
|
||||||
this.paystack.isGettingCheckoutLink = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post('/api/paystack/checkout', {
|
|
||||||
amount: this.singleChargeAmount * 100,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.data.authorization_url
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async payByPayPal() {
|
|
||||||
if (this.paypal.isMethodLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.paypal.isMethodLoading = true
|
|
||||||
|
|
||||||
let paypal
|
|
||||||
|
|
||||||
try {
|
|
||||||
paypal = await loadScript({
|
|
||||||
'client-id': this.config.paypal_client_id,
|
|
||||||
vault: true,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('failed_to_load_paypal'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const userId = this.user.data.id
|
|
||||||
const amount = this.singleChargeAmount
|
|
||||||
|
|
||||||
this.paypal.isMethodsLoaded = true
|
|
||||||
this.paypal.isMethodLoading = false
|
|
||||||
const app = this
|
|
||||||
|
|
||||||
// Initialize paypal buttons for single charge
|
|
||||||
await paypal
|
|
||||||
.Buttons({
|
|
||||||
createOrder: function (data, actions) {
|
|
||||||
return actions.order.create({
|
|
||||||
purchase_units: [
|
|
||||||
{
|
|
||||||
amount: {
|
|
||||||
value: amount,
|
|
||||||
},
|
|
||||||
custom_id: userId,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onApprove: function () {
|
|
||||||
app.paymentSuccessful()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.render('#paypal-button-container')
|
|
||||||
},
|
|
||||||
paymentSuccessful() {
|
|
||||||
this.$closePopup()
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('payment_was_successfully_received'),
|
|
||||||
})
|
|
||||||
|
|
||||||
// todo: temporary reload function
|
|
||||||
setTimeout(() => document.location.reload(), 500)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('popup:close', () => (this.paypal.isMethodsLoaded = false))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,312 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="select-plan-subscription">
|
|
||||||
<PopupHeader :title="$t('upgrade_your_account')" icon="credit-card" />
|
|
||||||
|
|
||||||
<!--Payment Options-->
|
|
||||||
<div v-if="isPaymentOptionPage">
|
|
||||||
<PopupContent>
|
|
||||||
<!--Stripe implementation-->
|
|
||||||
<PaymentMethod
|
|
||||||
v-if="config.isStripe"
|
|
||||||
driver="stripe"
|
|
||||||
:description="$t(config.stripe_payment_description)"
|
|
||||||
>
|
|
||||||
<div v-if="stripe.isGettingCheckoutLink" class="translate-y-3 scale-50 transform">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
@click="payByStripe"
|
|
||||||
:class="{ 'opacity-0': stripe.isGettingCheckoutLink }"
|
|
||||||
class="text-theme cursor-pointer text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('select') }}
|
|
||||||
</span>
|
|
||||||
</PaymentMethod>
|
|
||||||
|
|
||||||
<!--PayPal implementation-->
|
|
||||||
<div
|
|
||||||
v-if="config.isPayPal"
|
|
||||||
:class="{
|
|
||||||
'mb-2 rounded-xl bg-light-background px-4 dark:bg-2x-dark-foreground': paypal.isMethodsLoaded,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<PaymentMethod
|
|
||||||
@click.native="payByPayPal"
|
|
||||||
driver="paypal"
|
|
||||||
:description="$t(config.paypal_payment_description)"
|
|
||||||
>
|
|
||||||
<div v-if="paypal.isMethodLoading" class="translate-y-3 scale-50 transform">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
v-if="!paypal.isMethodsLoaded"
|
|
||||||
:class="{ 'opacity-0': paypal.isMethodLoading }"
|
|
||||||
class="text-theme cursor-pointer text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('select') }}
|
|
||||||
</span>
|
|
||||||
</PaymentMethod>
|
|
||||||
|
|
||||||
<!--PayPal Buttons-->
|
|
||||||
<div id="paypal-button-container"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Paystack implementation-->
|
|
||||||
<PaymentMethod
|
|
||||||
v-if="config.isPaystack"
|
|
||||||
driver="paystack"
|
|
||||||
:description="$t(config.paystack_payment_description)"
|
|
||||||
>
|
|
||||||
<div v-if="paystack.isGettingCheckoutLink" class="translate-y-3 scale-50 transform">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
@click="payByPaystack()"
|
|
||||||
:class="{ 'opacity-0': paystack.isGettingCheckoutLink }"
|
|
||||||
class="text-theme cursor-pointer text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('select') }}
|
|
||||||
</span>
|
|
||||||
</PaymentMethod>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary">
|
|
||||||
{{ $t('cancel_payment') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Select Payment Plans-->
|
|
||||||
<div v-if="!isPaymentOptionPage">
|
|
||||||
<PopupContent v-if="plans">
|
|
||||||
<InfoBox v-if="plans.data.length === 0" class="!mb-0">
|
|
||||||
<p>There isn't any plan yet.</p>
|
|
||||||
</InfoBox>
|
|
||||||
|
|
||||||
<PlanPeriodSwitcher v-if="yearlyPlans.length > 0" v-model="isSelectedYearlyPlans" />
|
|
||||||
|
|
||||||
<!--List available plans-->
|
|
||||||
<div>
|
|
||||||
<PlanDetail
|
|
||||||
v-for="(plan, i) in plans.data"
|
|
||||||
:plan="plan"
|
|
||||||
:key="plan.data.id"
|
|
||||||
v-if="plan.data.attributes.interval === intervalPlanType"
|
|
||||||
:class="{ 'pointer-events-none opacity-50': userSubscribedPlanId === plan.data.id }"
|
|
||||||
:is-selected="selectedPlan && selectedPlan.data.id === plan.data.id"
|
|
||||||
@click.native="selectPlan(plan)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
|
||||||
>{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase
|
|
||||||
class="w-full"
|
|
||||||
v-if="plans && plans.data.length !== 0"
|
|
||||||
:button-style="buttonStyle"
|
|
||||||
@click.native="isPaymentOptionPage = true"
|
|
||||||
>{{ $t('upgrade_account') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</div>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PaymentMethod from '../PaymentMethod'
|
|
||||||
import { loadScript } from '@paypal/paypal-js'
|
|
||||||
import SwitchInput from '../../Inputs/SwitchInput'
|
|
||||||
import PopupWrapper from '../../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../../Popups/Components/PopupHeader'
|
|
||||||
import ButtonBase from '../../UI/Buttons/ButtonBase'
|
|
||||||
import PlanDetail from '../PlanDetail'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import { events } from '../../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
import Spinner from '../../UI/Others/Spinner'
|
|
||||||
import InfoBox from '../../UI/Others/InfoBox'
|
|
||||||
import PlanPeriodSwitcher from '../PlanPeriodSwitcher'
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SubscribeAccountPopup',
|
|
||||||
components: {
|
|
||||||
PlanPeriodSwitcher,
|
|
||||||
InfoBox,
|
|
||||||
Spinner,
|
|
||||||
PaymentMethod,
|
|
||||||
PlanDetail,
|
|
||||||
SwitchInput,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
isSelectedYearlyPlans() {
|
|
||||||
this.selectedPlan = undefined
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config', 'user']),
|
|
||||||
intervalPlanType() {
|
|
||||||
return this.isSelectedYearlyPlans ? 'year' : 'month'
|
|
||||||
},
|
|
||||||
buttonStyle() {
|
|
||||||
return this.selectedPlan ? 'theme' : 'secondary'
|
|
||||||
},
|
|
||||||
userSubscribedPlanId() {
|
|
||||||
return (
|
|
||||||
this.user &&
|
|
||||||
this.user.data.relationships.subscription &&
|
|
||||||
this.user.data.relationships.subscription.data.relationships.plan.data.id
|
|
||||||
)
|
|
||||||
},
|
|
||||||
yearlyPlans() {
|
|
||||||
return this.plans.data.filter((plan) => plan.data.attributes.interval === 'year')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
paystack: {
|
|
||||||
isGettingCheckoutLink: false,
|
|
||||||
},
|
|
||||||
stripe: {
|
|
||||||
isGettingCheckoutLink: false,
|
|
||||||
},
|
|
||||||
paypal: {
|
|
||||||
isMethodsLoaded: false,
|
|
||||||
isMethodLoading: false,
|
|
||||||
},
|
|
||||||
isPaymentOptionPage: false,
|
|
||||||
isSelectedYearlyPlans: false,
|
|
||||||
isLoading: false,
|
|
||||||
selectedPlan: undefined,
|
|
||||||
plans: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
payByPaystack() {
|
|
||||||
this.paystack.isGettingCheckoutLink = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post('/api/paystack/checkout', {
|
|
||||||
planCode: this.selectedPlan.data.meta.driver_plan_id.paystack,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.data.authorization_url
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async payByPayPal() {
|
|
||||||
if (this.paypal.isMethodLoading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.paypal.isMethodLoading = true
|
|
||||||
|
|
||||||
let paypal
|
|
||||||
|
|
||||||
try {
|
|
||||||
paypal = await loadScript({
|
|
||||||
'client-id': this.config.paypal_client_id,
|
|
||||||
vault: true,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('failed_to_load_paypal'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const planId = this.selectedPlan.data.meta.driver_plan_id.paypal
|
|
||||||
const userId = this.user.data.id
|
|
||||||
const app = this
|
|
||||||
|
|
||||||
this.paypal.isMethodsLoaded = true
|
|
||||||
this.paypal.isMethodLoading = false
|
|
||||||
|
|
||||||
// Initialize paypal buttons for single charge
|
|
||||||
await paypal
|
|
||||||
.Buttons({
|
|
||||||
createSubscription: function (data, actions) {
|
|
||||||
return actions.subscription.create({
|
|
||||||
plan_id: planId,
|
|
||||||
custom_id: userId,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onApprove: function () {
|
|
||||||
app.paymentSuccessful()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.render('#paypal-button-container')
|
|
||||||
},
|
|
||||||
payByStripe() {
|
|
||||||
this.stripe.isGettingCheckoutLink = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post('/api/stripe/checkout', {
|
|
||||||
planCode: this.selectedPlan.data.meta.driver_plan_id.stripe,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.url
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.$closePopup()
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (error.response.status === 500 && error.response.data.type) {
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: error.response.data.title,
|
|
||||||
message: error.response.data.message,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: this.$t('popup_error.title'),
|
|
||||||
message: this.$t('popup_error.message'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.stripe.isGettingCheckoutLink = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
selectPlan(plan) {
|
|
||||||
this.selectedPlan = plan
|
|
||||||
},
|
|
||||||
paymentSuccessful() {
|
|
||||||
this.$closePopup()
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('payment_was_successfully_received'),
|
|
||||||
})
|
|
||||||
|
|
||||||
// todo: temporary reload function
|
|
||||||
setTimeout(() => document.location.reload(), 1000)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// Load available plans
|
|
||||||
axios.get('/api/subscriptions/plans').then((response) => {
|
|
||||||
this.plans = response.data
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reset states on popup close
|
|
||||||
events.$on('popup:close', () => {
|
|
||||||
this.isSelectedYearlyPlans = false
|
|
||||||
this.isPaymentOptionPage = false
|
|
||||||
this.selectedPlan = undefined
|
|
||||||
this.paypal.isMethodsLoaded = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="$store.getters.isLimitedUser" class="bg-red-500 py-1 text-center">
|
|
||||||
<router-link :to="{ name: 'Billing' }" class="text-xs font-bold text-white">
|
|
||||||
{{ $t('restricted_account_warning') }}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'RestrictionWarningBar',
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="!hasPaymentMethod" class="card shadow-card">
|
|
||||||
<FormLabel icon="dollar">
|
|
||||||
{{ $t('balance') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-2xl font-extrabold sm:text-3xl">
|
|
||||||
{{ user.data.relationships.balance.data.attributes.formatted }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<!-- Make payment form -->
|
|
||||||
<ValidationObserver
|
|
||||||
ref="fundAccount"
|
|
||||||
@submit.prevent="makePayment"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="mt-6"
|
|
||||||
>
|
|
||||||
<ValidationProvider
|
|
||||||
tag="div"
|
|
||||||
v-slot="{ errors }"
|
|
||||||
mode="passive"
|
|
||||||
name="Amount"
|
|
||||||
:rules="`required|min_value:${user.data.meta.totalDebt.amount}`"
|
|
||||||
>
|
|
||||||
<AppInputText
|
|
||||||
:description="
|
|
||||||
$t('amount_increase_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="chargeAmount"
|
|
||||||
:placeholder="$t('fund_account_balance')"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="999999999"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
/>
|
|
||||||
<ButtonBase type="submit" button-style="theme" class="w-full sm:w-auto">
|
|
||||||
{{ $t('make_payment') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</div>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { ValidationObserver, ValidationProvider } from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserBalance',
|
|
||||||
components: {
|
|
||||||
ValidationObserver,
|
|
||||||
ValidationProvider,
|
|
||||||
AppInputText,
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
hasPaymentMethod() {
|
|
||||||
return this.user.data.relationships.creditCards && this.user.data.relationships.creditCards.data.length > 0
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
chargeAmount: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async makePayment() {
|
|
||||||
// Validate fields
|
|
||||||
const isValid = await this.$refs.fundAccount.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
// Show payment methods popup
|
|
||||||
this.$store.dispatch('callSingleChargeProcess', this.chargeAmount)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<FormLabel icon="bell">
|
|
||||||
{{ $t('billing_alert') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<div v-if="user.data.relationships.alert">
|
|
||||||
<b class="-mt-3 mb-0.5 block flex items-center text-2xl font-extrabold sm:text-3xl">
|
|
||||||
{{ user.data.relationships.alert.data.attributes.formatted }}
|
|
||||||
<edit2-icon
|
|
||||||
v-if="!showUpdateBillingAlertForm"
|
|
||||||
@click="showUpdateBillingAlertForm = !showUpdateBillingAlertForm"
|
|
||||||
size="12"
|
|
||||||
class="vue-feather ml-2 -translate-y-0.5 transform cursor-pointer"
|
|
||||||
/>
|
|
||||||
<trash2-icon
|
|
||||||
v-if="showUpdateBillingAlertForm"
|
|
||||||
@click="deleteBillingAlert"
|
|
||||||
size="12"
|
|
||||||
class="vue-feather ml-2 -translate-y-0.5 transform cursor-pointer"
|
|
||||||
/>
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b class="block text-sm dark:text-gray-500 text-gray-400">
|
|
||||||
{{ $t('billing_alert_description') }}
|
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="showUpdateBillingAlertForm"
|
|
||||||
ref="updatebillingAlertForm"
|
|
||||||
@submit.prevent="updateBillingAlert"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="mt-6"
|
|
||||||
>
|
|
||||||
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Billing Alert" rules="required">
|
|
||||||
<AppInputText
|
|
||||||
:description="
|
|
||||||
$t(
|
|
||||||
'billing_alert_notes'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:error="errors[0]"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
|
|
||||||
<input
|
|
||||||
v-model="billingAlertAmount"
|
|
||||||
:placeholder="$t('alert_amount_')"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="999999999"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
/>
|
|
||||||
<ButtonBase
|
|
||||||
:loadint="isSendingBillingAlert"
|
|
||||||
:disabled="isSendingBillingAlert"
|
|
||||||
type="submit"
|
|
||||||
button-style="theme"
|
|
||||||
class="w-full sm:w-auto"
|
|
||||||
>
|
|
||||||
{{ $t('update_alert') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</div>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="!user.data.relationships.alert"
|
|
||||||
ref="billingAlertForm"
|
|
||||||
@submit.prevent="setBillingAlert"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="mt-6"
|
|
||||||
>
|
|
||||||
<ValidationProvider tag="div" v-slot="{ errors }" mode="passive" name="Billing Alert" rules="required">
|
|
||||||
<AppInputText
|
|
||||||
:description="
|
|
||||||
$t(
|
|
||||||
'billing_alert_notes'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:error="errors[0]"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
|
|
||||||
<input
|
|
||||||
v-model="billingAlertAmount"
|
|
||||||
:placeholder="$t('alert_amount_')"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max="999999999"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
/>
|
|
||||||
<ButtonBase
|
|
||||||
:loadint="isSendingBillingAlert"
|
|
||||||
:disabled="isSendingBillingAlert"
|
|
||||||
type="submit"
|
|
||||||
button-style="theme"
|
|
||||||
class="w-full sm:w-auto"
|
|
||||||
>
|
|
||||||
{{ $t('set_alert') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</div>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { ValidationObserver, ValidationProvider } from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import { Edit2Icon, Trash2Icon } from 'vue-feather-icons'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserBillingAlerts',
|
|
||||||
components: {
|
|
||||||
ValidationObserver,
|
|
||||||
ValidationProvider,
|
|
||||||
AppInputText,
|
|
||||||
ButtonBase,
|
|
||||||
Trash2Icon,
|
|
||||||
Edit2Icon,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
billingAlertAmount: undefined,
|
|
||||||
isSendingBillingAlert: false,
|
|
||||||
showUpdateBillingAlertForm: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async updateBillingAlert() {
|
|
||||||
// Validate fields
|
|
||||||
const isValid = await this.$refs.updatebillingAlertForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.isSendingBillingAlert = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.patch(`/api/subscriptions/billing-alerts/${this.user.data.relationships.alert.data.id}`, {
|
|
||||||
amount: this.billingAlertAmount,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
|
|
||||||
this.showUpdateBillingAlertForm = false
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('alert_updated'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.isSendingBillingAlert = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async setBillingAlert() {
|
|
||||||
// Validate fields
|
|
||||||
const isValid = await this.$refs.billingAlertForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.isSendingBillingAlert = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post('/api/subscriptions/billing-alerts', {
|
|
||||||
amount: this.billingAlertAmount,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('alert_set_successfully'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.isSendingBillingAlert = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteBillingAlert() {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: this.$t('want_to_delete_alert'),
|
|
||||||
message: this.$t(
|
|
||||||
'want_to_delete_alert_description'
|
|
||||||
),
|
|
||||||
action: {
|
|
||||||
id: this.user.data.relationships.alert.data.id,
|
|
||||||
operation: 'delete-billing-alert',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('action:confirmed', (data) => {
|
|
||||||
if (data.operation === 'delete-billing-alert')
|
|
||||||
axios
|
|
||||||
.delete(`/api/subscriptions/billing-alerts/${this.user.data.relationships.alert.data.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
|
|
||||||
this.showUpdateBillingAlertForm = false
|
|
||||||
this.billingAlertAmount = undefined
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('deleted_alert'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => this.$isSomethingWrong())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
events.$off('action:confirmed')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="hasSubscription" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('edit_your_subscription') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputButton
|
|
||||||
v-if="subscription.attributes.status !== 'cancelled'"
|
|
||||||
:title="$t('cancel_subscription')"
|
|
||||||
:description="
|
|
||||||
$t(
|
|
||||||
'cancel_subscription_description'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<ButtonBase
|
|
||||||
@click.native="cancelSubscriptionConfirmation"
|
|
||||||
:loading="isCancelling"
|
|
||||||
class="w-full sm:w-auto"
|
|
||||||
button-style="secondary"
|
|
||||||
>
|
|
||||||
{{ $t('cancel_now') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</AppInputButton>
|
|
||||||
|
|
||||||
<AppInputButton
|
|
||||||
:title="$t('upgrade_downgrade_plan')"
|
|
||||||
:description="$t('upgrade_downgrade_plan_description')"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<ButtonBase @click.native="$changeSubscriptionOptions" class="w-full sm:w-auto" button-style="secondary">
|
|
||||||
{{ $t('change_plan') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</AppInputButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import AppInputButton from '../Forms/Layouts/AppInputButton'
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import AppInputSwitch from '../Forms/Layouts/AppInputSwitch'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserEditSubscription',
|
|
||||||
components: {
|
|
||||||
AppInputButton,
|
|
||||||
AppInputSwitch,
|
|
||||||
AppInputText,
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
subscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription.data
|
|
||||||
},
|
|
||||||
hasSubscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isCancelling: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cancelSubscriptionConfirmation() {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: this.$t('want_cancel_subscription'),
|
|
||||||
message: this.$t(
|
|
||||||
"popup_subscription_cancel.message"
|
|
||||||
),
|
|
||||||
action: {
|
|
||||||
operation: 'cancel-subscription',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('action:confirmed', (data) => {
|
|
||||||
if (data.operation === 'cancel-subscription') {
|
|
||||||
// Start deleting spinner button
|
|
||||||
this.isCancelling = true
|
|
||||||
|
|
||||||
// Send post request
|
|
||||||
axios
|
|
||||||
.post('/api/subscriptions/cancel')
|
|
||||||
.then(() => {
|
|
||||||
// Update user data
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('popup_subscription_cancel.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.isCancelling = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
events.$off('action:confirmed')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="!hasSubscription" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('subscription') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-2xl font-extrabold sm:text-3xl">
|
|
||||||
{{ $t('free_plan') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b v-if="$store.getters.config.allowed_payments" class="mb-3 mb-8 block text-sm text-gray-400">
|
|
||||||
{{ $t('upgrade_to_get_more') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<ButtonBase
|
|
||||||
v-if="$store.getters.config.allowed_payments"
|
|
||||||
@click.native="$openSubscribeOptions"
|
|
||||||
type="submit"
|
|
||||||
button-style="theme"
|
|
||||||
class="mt-4 w-full"
|
|
||||||
>
|
|
||||||
{{ $t('upgrade_your_account') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserEmptySubscription',
|
|
||||||
components: {
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
hasSubscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
v-if="user.data.relationships.failedPayments && user.data.relationships.failedPayments.data.length > 0"
|
|
||||||
class="card shadow-card"
|
|
||||||
>
|
|
||||||
<FormLabel icon="frown">
|
|
||||||
{{ $t('failed_payments') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-2xl font-extrabold sm:text-3xl">
|
|
||||||
-{{ user.data.meta.totalDebt.formatted }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b class="mb-3 mb-5 block text-sm text-gray-400">
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
"unable_to_charge"
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<!--Failed Payments-->
|
|
||||||
<div
|
|
||||||
v-for="payment in user.data.relationships.failedPayments.data"
|
|
||||||
:key="payment.data.id"
|
|
||||||
class="flex items-center justify-between border-b border-dashed border-light py-2 dark:border-opacity-5"
|
|
||||||
>
|
|
||||||
<div class="w-2/4 leading-none">
|
|
||||||
<b class="text-sm font-bold leading-none">
|
|
||||||
{{ payment.data.attributes.note }}
|
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-left">
|
|
||||||
<span class="text-gray-560 text-sm font-bold capitalize">
|
|
||||||
{{ $t(payment.data.attributes.source) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-right">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ payment.data.attributes.created_at }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-right">
|
|
||||||
<span class="text-red text-sm font-bold">
|
|
||||||
{{ payment.data.attributes.amount }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserFailedPayments',
|
|
||||||
components: {
|
|
||||||
FormLabel,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="hasSubscription" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('subscription') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-xl font-extrabold sm:text-3xl">
|
|
||||||
{{ status }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b class="mb-3 mb-8 block text-sm dark:text-gray-500 text-gray-400">
|
|
||||||
{{ subscription.data.relationships.plan.data.attributes.name }} /
|
|
||||||
{{ price }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<div v-for="(limit, i) in limitations" :key="i" :class="{ 'mb-6': Object.keys(limitations).length - 1 !== i }">
|
|
||||||
<b class="mb-3 block text-sm dark:text-gray-500 text-gray-400">
|
|
||||||
{{ limit.message }}
|
|
||||||
</b>
|
|
||||||
<ProgressLine v-if="limit.isVisibleBar" :data="limit.distribution" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import ProgressLine from '../UI/ProgressChart/ProgressLine'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserFixedSubscriptionDetail',
|
|
||||||
components: {
|
|
||||||
ProgressLine,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
subscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription
|
|
||||||
},
|
|
||||||
hasSubscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription
|
|
||||||
},
|
|
||||||
limitations() {
|
|
||||||
let limitations = []
|
|
||||||
|
|
||||||
Object.entries(this.user.data.meta.limitations).map(([key, item]) => {
|
|
||||||
let payload = {
|
|
||||||
color: {
|
|
||||||
max_storage_amount: 'warning',
|
|
||||||
max_team_members: 'purple',
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
max_storage_amount: this.$t('total_x_of_x_used', {use: item.use, total:item.total }),
|
|
||||||
max_team_members: item.total === -1
|
|
||||||
? this.$t('max_team_members.unlimited')
|
|
||||||
: this.$t('total_x_of_x_members', {use: item.use, total:item.total }),
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
max_storage_amount: this.$t('storage'),
|
|
||||||
max_team_members: this.$t('team_members'),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
limitations.push({
|
|
||||||
message: payload.message[key],
|
|
||||||
isVisibleBar: item.total !== -1,
|
|
||||||
distribution: [
|
|
||||||
{
|
|
||||||
progress: item.percentage,
|
|
||||||
color: payload.color[key],
|
|
||||||
title: payload.title[key],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return limitations
|
|
||||||
},
|
|
||||||
status() {
|
|
||||||
return {
|
|
||||||
active: this.$t('active_until', {date: this.subscription.data.attributes.renews_at}),
|
|
||||||
cancelled: this.$t('ends_at_date', {date: this.subscription.data.attributes.ends_at}),
|
|
||||||
}[this.subscription.data.attributes.status]
|
|
||||||
},
|
|
||||||
price() {
|
|
||||||
return {
|
|
||||||
month: this.$t('price_per_month', {price: this.subscription.data.relationships.plan.data.attributes.price}),
|
|
||||||
year: this.$t('price_per_year', {price: this.subscription.data.relationships.plan.data.attributes.price}),
|
|
||||||
}[this.subscription.data.relationships.plan.data.attributes.interval]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="canShowForMeteredBilling || canShowForFixedBilling" class="card shadow-card">
|
|
||||||
<FormLabel icon="credit-card">
|
|
||||||
{{ $t('payment_method') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<!-- User has registered payment method -->
|
|
||||||
<div v-if="hasPaymentMethod">
|
|
||||||
<b
|
|
||||||
v-if="
|
|
||||||
config.subscriptionType === 'metered' && user.data.relationships.balance.data.attributes.balance > 0
|
|
||||||
"
|
|
||||||
class="mb-3 mb-5 block text-sm"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
$t('credit_to_auto_withdraw', {
|
|
||||||
credit: user.data.relationships.balance.data.attributes.formatted,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<!-- Card -->
|
|
||||||
<PaymentCard v-for="card in user.data.relationships.creditCards.data" :key="card.data.id" :card="card" />
|
|
||||||
|
|
||||||
<small class="hidden pt-3 text-xs leading-none dark:text-gray-500 text-gray-500 sm:block">
|
|
||||||
{{ $t('auto_settled_credit_card') }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- User doesn't have registered payment method -->
|
|
||||||
<div v-if="!hasPaymentMethod">
|
|
||||||
<!-- Show credit card form -->
|
|
||||||
<ButtonBase
|
|
||||||
@click.native="showStoreCreditCardForm"
|
|
||||||
v-if="!isCreditCardForm"
|
|
||||||
:loading="stripe.storingStripePaymentMethod"
|
|
||||||
type="submit"
|
|
||||||
button-style="theme"
|
|
||||||
class="mt-4 w-full"
|
|
||||||
>
|
|
||||||
{{ $t('add_payment_method') }}
|
|
||||||
</ButtonBase>
|
|
||||||
|
|
||||||
<!-- Store credit card form -->
|
|
||||||
<form v-if="isCreditCardForm" @submit.prevent="storeStripePaymentMethod" id="payment-form" class="mt-6">
|
|
||||||
<div v-if="stripe.isInitialization" class="relative mb-6 h-10">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
<InfoBox v-if="config.isDemo && !stripe.isInitialization">
|
|
||||||
<p>For adding test credit card please use <b class="text-theme">4242 4242 4242 4242</b> as a card number, <b class="text-theme">11/22</b>
|
|
||||||
as the expiration date and <b class="text-theme">123</b> as CVC number and ZIP <b class="text-theme">12345</b> if required.</p>
|
|
||||||
</InfoBox>
|
|
||||||
<div id="payment-element">
|
|
||||||
<!-- Elements will create form elements here -->
|
|
||||||
</div>
|
|
||||||
<ButtonBase
|
|
||||||
:loading="stripe.storingStripePaymentMethod"
|
|
||||||
type="submit"
|
|
||||||
button-style="theme"
|
|
||||||
class="mt-4 w-full"
|
|
||||||
>
|
|
||||||
{{ $t('store_my_credit_card') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<div id="error-message" class="pt-2 text-xs text-rose-600">
|
|
||||||
<!-- Display error message to your customers here -->
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import PaymentCard from './PaymentCard'
|
|
||||||
import Spinner from '../UI/Others/Spinner'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import { loadStripe } from '@stripe/stripe-js'
|
|
||||||
import axios from 'axios'
|
|
||||||
import InfoBox from "../UI/Others/InfoBox";
|
|
||||||
|
|
||||||
// Define stripe variables
|
|
||||||
let stripe,
|
|
||||||
elements = undefined
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserStoredPaymentMethods',
|
|
||||||
components: {
|
|
||||||
InfoBox,
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
PaymentCard,
|
|
||||||
Spinner,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['isDarkMode', 'config', 'user']),
|
|
||||||
canShowForMeteredBilling() {
|
|
||||||
return this.config.isStripe && this.config.subscriptionType === 'metered'
|
|
||||||
},
|
|
||||||
canShowForFixedBilling() {
|
|
||||||
return (
|
|
||||||
this.config.isStripe &&
|
|
||||||
this.config.subscriptionType === 'fixed' &&
|
|
||||||
this.$store.getters.user.data.relationships.subscription &&
|
|
||||||
this.$store.getters.user.data.relationships.subscription.data.attributes.driver === 'stripe'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
hasPaymentMethod() {
|
|
||||||
return this.user.data.relationships.creditCards && this.user.data.relationships.creditCards.data.length > 0
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isLoading: false,
|
|
||||||
isCreditCardForm: false,
|
|
||||||
stripe: {
|
|
||||||
isInitialization: true,
|
|
||||||
storingStripePaymentMethod: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async storeStripePaymentMethod() {
|
|
||||||
if (this.config.isDemo && this.user.data.attributes.email === 'ho**@hi5ve.digital') {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('credit_card_stored'),
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.stripe.storingStripePaymentMethod = true
|
|
||||||
|
|
||||||
const { error } = await stripe.confirmSetup({
|
|
||||||
//`Elements` instance that was used to create the Payment Element
|
|
||||||
elements,
|
|
||||||
redirect: 'if_required',
|
|
||||||
confirmParams: {
|
|
||||||
return_url: window.location.href,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
// This point will only be reached if there is an immediate error when
|
|
||||||
// confirming the payment. Show error to your customer (e.g., payment
|
|
||||||
// details incomplete)
|
|
||||||
const messageContainer = document.querySelector('#error-message')
|
|
||||||
messageContainer.textContent = error.message
|
|
||||||
} else {
|
|
||||||
// Your customer will be redirected to your `return_url`. For some payment
|
|
||||||
// methods like iDEAL, your customer will be redirected to an intermediate
|
|
||||||
// site first to authorize the payment, then redirected to the `return_url`.
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('credit_card_stored'),
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: L9 - load credit card after was stored in database
|
|
||||||
setTimeout(() => document.location.reload(), 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.stripe.storingStripePaymentMethod = false
|
|
||||||
},
|
|
||||||
async stripeInit() {
|
|
||||||
// Init stripe js
|
|
||||||
stripe = await loadStripe(this.config.stripe_public_key)
|
|
||||||
|
|
||||||
await axios
|
|
||||||
.get('/api/stripe/setup-intent')
|
|
||||||
.then((response) => {
|
|
||||||
// Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 2
|
|
||||||
elements = stripe.elements({
|
|
||||||
clientSecret: response.data.client_secret,
|
|
||||||
appearance: {
|
|
||||||
theme: 'stripe',
|
|
||||||
variables: {
|
|
||||||
colorPrimary: this.config.app_color,
|
|
||||||
fontFamily: 'Nunito',
|
|
||||||
borderRadius: '8px',
|
|
||||||
colorText: this.isDarkMode ? '#bec6cf' : '#1B2539',
|
|
||||||
colorBackground: this.isDarkMode ? '#191b1e' : '#fff',
|
|
||||||
fontWeightNormal: '700',
|
|
||||||
fontSizeSm: '0.875rem',
|
|
||||||
colorSuccessText: '#0ABB87',
|
|
||||||
colorSuccess: '#0ABB87',
|
|
||||||
colorWarning: '#fd397a',
|
|
||||||
colorWarningText: '#fd397a',
|
|
||||||
colorDangerText: '#fd397a',
|
|
||||||
colorTextSecondary: '#6b7280',
|
|
||||||
spacingGridRow: '20px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create and mount the Payment Element
|
|
||||||
const paymentElement = elements.create('payment')
|
|
||||||
|
|
||||||
paymentElement.mount('#payment-element')
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
this.stripe.isInitialization = false
|
|
||||||
},
|
|
||||||
showStoreCreditCardForm() {
|
|
||||||
this.isCreditCardForm = !this.isCreditCardForm
|
|
||||||
this.stripeInit()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<FormLabel icon="file-text">
|
|
||||||
{{ $t('transactions') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<DatatableWrapper
|
|
||||||
class="overflow-x-auto"
|
|
||||||
api="/api/subscriptions/transactions"
|
|
||||||
:paginator="true"
|
|
||||||
:columns="columns"
|
|
||||||
>
|
|
||||||
<template slot-scope="{ row }">
|
|
||||||
<FixedTransactionRow :row="row" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--Empty page-->
|
|
||||||
<template v-slot:empty-page>
|
|
||||||
<InfoBox style="margin-bottom: 0">
|
|
||||||
<p>{{ $t('user_invoices.empty') }}</p>
|
|
||||||
</InfoBox>
|
|
||||||
</template>
|
|
||||||
</DatatableWrapper>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import DatatableWrapper from '../UI/Table/DatatableWrapper'
|
|
||||||
import FixedTransactionRow from './FixedTransactionRow'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import ColorLabel from '../UI/Labels/ColorLabel'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserTransactionsForFixedBilling',
|
|
||||||
components: {
|
|
||||||
FixedTransactionRow,
|
|
||||||
DatatableWrapper,
|
|
||||||
ColorLabel,
|
|
||||||
FormLabel,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
columns() {
|
|
||||||
return this.$store.getters.transactionColumns.filter(
|
|
||||||
(column) => !['type', 'user_id'].includes(column.field)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<FormLabel icon="file-text">
|
|
||||||
{{ $t('transactions') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<DatatableWrapper class="overflow-x-auto" api="/api/user/transactions" :paginator="true" :columns="columns">
|
|
||||||
<template slot-scope="{ row }">
|
|
||||||
<!--Transaction rows-->
|
|
||||||
<MeteredTransactionRow :row="row" @showDetail="showTransactionDetail" />
|
|
||||||
|
|
||||||
<!--Transaction detail-->
|
|
||||||
<MeteredTransactionDetailRow
|
|
||||||
v-if="row.data.attributes.metadata && showedTransactionDetailById === row.data.id"
|
|
||||||
:row="row"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--Empty page-->
|
|
||||||
<template v-slot:empty-page>
|
|
||||||
<InfoBox style="margin-bottom: 0">
|
|
||||||
<p>{{ $t('user_invoices.empty') }}</p>
|
|
||||||
</InfoBox>
|
|
||||||
</template>
|
|
||||||
</DatatableWrapper>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { EyeIcon, FileTextIcon } from 'vue-feather-icons'
|
|
||||||
import ColorLabel from '../UI/Labels/ColorLabel'
|
|
||||||
import DatatableWrapper from '../UI/Table/DatatableWrapper'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import MeteredTransactionDetailRow from './MeteredTransactionDetailRow'
|
|
||||||
import MeteredTransactionRow from './MeteredTransactionRow'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserTransactionsForMeteredBilling',
|
|
||||||
components: {
|
|
||||||
MeteredTransactionDetailRow,
|
|
||||||
MeteredTransactionRow,
|
|
||||||
DatatableWrapper,
|
|
||||||
ColorLabel,
|
|
||||||
FormLabel,
|
|
||||||
InfoBox,
|
|
||||||
FileTextIcon,
|
|
||||||
EyeIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
columns() {
|
|
||||||
return this.$store.getters.transactionColumns.filter((column) => column.field !== 'user_id')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showedTransactionDetailById: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showTransactionDetail(id) {
|
|
||||||
if (this.showedTransactionDetailById === id) this.showedTransactionDetailById = undefined
|
|
||||||
else this.showedTransactionDetailById = id
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="canShowForSubscription" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('update_payments') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputButton
|
|
||||||
:title="$t('update_payment_method')"
|
|
||||||
:description="$t('payment_method_update_redirect_description')"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<ButtonBase
|
|
||||||
@click.native="updatePaymentMethod"
|
|
||||||
:loading="isGeneratedUpdateLink"
|
|
||||||
class="w-full sm:w-auto"
|
|
||||||
button-style="theme"
|
|
||||||
>
|
|
||||||
{{ $t('update_payments') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</AppInputButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import AppInputSwitch from '../Forms/Layouts/AppInputSwitch'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import AppInputButton from '../Forms/Layouts/AppInputButton'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserUpdatePaymentMethodsExternally',
|
|
||||||
components: {
|
|
||||||
AppInputButton,
|
|
||||||
AppInputSwitch,
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
canShowForSubscription() {
|
|
||||||
return (
|
|
||||||
this.hasSubscription &&
|
|
||||||
!this.subscription.attributes.is_cancelled &&
|
|
||||||
['paystack', 'paypal'].includes(this.subscription.attributes.driver)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
subscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription.data
|
|
||||||
},
|
|
||||||
hasSubscription() {
|
|
||||||
return this.$store.getters.user.data.relationships.subscription
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isGeneratedUpdateLink: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updatePaymentMethod() {
|
|
||||||
this.isGeneratedUpdateLink = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post(`/api/subscriptions/edit/${this.subscription.id}`)
|
|
||||||
.then((response) => {
|
|
||||||
window.location = response.data.url
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
|
|
||||||
this.isGeneratedUpdateLink = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<FormLabel icon="bar-chart">
|
|
||||||
{{ $t('usage_estimates') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-2xl font-extrabold sm:text-3xl">
|
|
||||||
{{ user.data.meta.usages.costEstimate }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b class="mb-3 mb-5 block text-sm dark:text-gray-500 text-gray-400">
|
|
||||||
{{ user.data.relationships.subscription.data.attributes.updated_at }}
|
|
||||||
{{ $t('till_now') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between border-b border-dashed border-light py-2 dark:border-opacity-5"
|
|
||||||
v-for="(usage, i) in user.data.meta.usages.featureEstimates"
|
|
||||||
:key="i"
|
|
||||||
>
|
|
||||||
<div class="w-2/4 leading-none">
|
|
||||||
<b class="text-sm font-bold leading-none">
|
|
||||||
{{ $t(usage.feature) }}
|
|
||||||
</b>
|
|
||||||
<small class="hidden pt-2 text-xs leading-none dark:text-gray-500 text-gray-500 sm:block">
|
|
||||||
{{ $t(`feature_usage_desc_${usage.feature}`) }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-left">
|
|
||||||
<span class="text-gray-560 text-sm font-bold">
|
|
||||||
{{ usage.usage }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="w-1/4 text-right">
|
|
||||||
<span class="text-theme text-sm font-bold">
|
|
||||||
{{ usage.cost }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<small class="mt-6 block font-bold">
|
|
||||||
{{ $t('records_updated_daily_bases') }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import FormLabel from '../UI/Labels/FormLabel'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'UserUsageEstimates',
|
|
||||||
components: {
|
|
||||||
FormLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div @click="togglePermission" class="permission-toggle">
|
|
||||||
<b class="privilege">{{ $t(teamPermissions[permission]) }}</b>
|
|
||||||
<refresh-cw-icon size="14" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { RefreshCwIcon } from 'vue-feather-icons'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PermissionToggleButton',
|
|
||||||
props: ['item'],
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['teamPermissions']),
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
RefreshCwIcon,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
permission: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
togglePermission() {
|
|
||||||
let index = Object.keys(this.teamPermissions)
|
|
||||||
.map((i) => i)
|
|
||||||
.indexOf(this.permission)
|
|
||||||
|
|
||||||
if (index === Object.keys(this.teamPermissions).length - 1) {
|
|
||||||
this.permission = Object.keys(this.teamPermissions)[0]
|
|
||||||
} else {
|
|
||||||
this.permission = Object.keys(this.teamPermissions)[index + 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$emit('input', this.permission)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.permission = this.item.permission
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import '../../../../sass/vuefilemanager/inapp-forms';
|
|
||||||
@import '../../../../sass/vuefilemanager/forms';
|
|
||||||
|
|
||||||
.permission-toggle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
.privilege {
|
|
||||||
white-space: nowrap;
|
|
||||||
@include font-size(13);
|
|
||||||
color: $text-muted;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
polyline,
|
|
||||||
path {
|
|
||||||
color: $light_text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.permission-toggle .privilege {
|
|
||||||
color: $dark_mode_text_secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="py-3 px-5 text-left">
|
|
||||||
<div class="info">
|
|
||||||
<b class="title text-sm">
|
|
||||||
{{ teamFolder.data.attributes.name }}
|
|
||||||
</b>
|
|
||||||
<span class="subtitle mb-2 block text-tiny text-gray-600 dark:text-gray-500">
|
|
||||||
{{ $t('created_at') }} {{ teamFolder.data.attributes.created_at }}
|
|
||||||
</span>
|
|
||||||
<TeamMembersPreview :folder="teamFolder" :avatar-size="32" class="members" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import TeamMembersPreview from './TeamMembersPreview'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TeamFolderPreview',
|
|
||||||
components: {
|
|
||||||
TeamMembersPreview,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['currentTeamFolder', 'clipboard']),
|
|
||||||
teamFolder() {
|
|
||||||
return this.currentTeamFolder ? this.currentTeamFolder : this.clipboard[0]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<template>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-if="Object.values(members).length > 0 && entry.id !== user.data.id"
|
|
||||||
v-for="(entry, i) in members"
|
|
||||||
:key="i"
|
|
||||||
class="flex items-center py-2"
|
|
||||||
>
|
|
||||||
<!--Remove Member-->
|
|
||||||
<div @click="deleteMember(entry)" class="-ml-1.5 cursor-pointer py-2 px-1 leading-none">
|
|
||||||
<x-icon size="14" class="vue-feather dark:text-gray-600" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Member Preview-->
|
|
||||||
<div class="flex items-center">
|
|
||||||
<!--Avatar-->
|
|
||||||
<MemberAvatar class="mr-3 ml-2" :is-border="false" :size="44" :member="$mapIntoMemberResource(entry)" />
|
|
||||||
|
|
||||||
<!--Member-->
|
|
||||||
<div v-if="entry.type === 'member'" class="info">
|
|
||||||
<b
|
|
||||||
class="max-w-1 block overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
|
|
||||||
style="max-width: 155px"
|
|
||||||
>
|
|
||||||
{{ entry.name }}
|
|
||||||
</b>
|
|
||||||
<span class="block text-xs text-gray-600 dark:text-gray-500">
|
|
||||||
{{ entry.email }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Invitation-->
|
|
||||||
<div v-if="entry.type === 'invitation'" class="info">
|
|
||||||
<b
|
|
||||||
class="block max-w-xs overflow-hidden text-ellipsis whitespace-nowrap text-sm font-bold"
|
|
||||||
style="max-width: 155px"
|
|
||||||
>
|
|
||||||
{{ entry.email }}
|
|
||||||
</b>
|
|
||||||
<span v-if="entry.id" class="block text-xs text-gray-600 dark:text-gray-500">
|
|
||||||
{{ $t('waiting_for_accept_invitation') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Set member permission-->
|
|
||||||
<div class="ml-auto">
|
|
||||||
<PermissionToggleButton @input="updateMemberPermission(entry, $event)" :item="entry" />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PermissionToggleButton from './PermissionToggleButton'
|
|
||||||
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
|
||||||
import { XIcon } from 'vue-feather-icons'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TeamList',
|
|
||||||
props: ['value'],
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
PermissionToggleButton,
|
|
||||||
MemberAvatar,
|
|
||||||
XIcon,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
members: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateMemberPermission(member, value) {
|
|
||||||
this.members.map((e) => (e === member ? (e.permission = value) : e))
|
|
||||||
|
|
||||||
this.emitMembers()
|
|
||||||
},
|
|
||||||
deleteMember(member) {
|
|
||||||
this.members = this.members.filter((m) => m !== member)
|
|
||||||
|
|
||||||
this.emitMembers()
|
|
||||||
},
|
|
||||||
emitMembers() {
|
|
||||||
this.$emit('input', this.members)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.members = this.value
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="w-28">
|
|
||||||
<div v-if="!teamFolder" class="text-right md:text-center">
|
|
||||||
<span class="mr-3 align-middle text-tiny text-gray-600 dark:text-gray-500 md:mr-0.5">
|
|
||||||
{{ $t('not_selected') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<TeamMembersPreview
|
|
||||||
v-else
|
|
||||||
:folder="teamFolder"
|
|
||||||
:limit="true"
|
|
||||||
:avatar-size="size"
|
|
||||||
class="justify-end md:justify-center"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import TeamMembersPreview from './TeamMembersPreview'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TeamMembersButton',
|
|
||||||
components: {
|
|
||||||
TeamMembersPreview,
|
|
||||||
},
|
|
||||||
props: ['size'],
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['currentTeamFolder', 'clipboard']),
|
|
||||||
teamFolder() {
|
|
||||||
return this.currentTeamFolder ? this.currentTeamFolder : this.clipboard[0]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="team-folder">
|
|
||||||
<span v-if="limit && membersCount > 3" class="member-count"> +{{ membersCount - 3 }} </span>
|
|
||||||
<div class="members">
|
|
||||||
<div
|
|
||||||
v-for="member in members"
|
|
||||||
:key="member.data.id"
|
|
||||||
:title="member.data.attributes.email"
|
|
||||||
class="member-preview z-10"
|
|
||||||
>
|
|
||||||
<MemberAvatar :is-border="true" :size="34" :member="member" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import MemberAvatar from '../../UI/Others/MemberAvatar'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TeamMembersPreview',
|
|
||||||
props: ['folder', 'limit', 'avatarSize'],
|
|
||||||
components: {
|
|
||||||
MemberAvatar,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
membersCount() {
|
|
||||||
return (
|
|
||||||
this.folder.data.relationships.members.data.length +
|
|
||||||
this.folder.data.relationships.invitations.data.length
|
|
||||||
)
|
|
||||||
},
|
|
||||||
members() {
|
|
||||||
let allMembers = this.folder.data.relationships.members.data.concat(
|
|
||||||
this.folder.data.relationships.invitations.data
|
|
||||||
)
|
|
||||||
|
|
||||||
if (this.limit) {
|
|
||||||
return allMembers.slice(0, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
return allMembers
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import 'resources/sass/vuefilemanager/_variables';
|
|
||||||
@import 'resources/sass/vuefilemanager/_mixins';
|
|
||||||
|
|
||||||
.team-folder {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.member-count {
|
|
||||||
@include font-size(12);
|
|
||||||
color: $text-muted;
|
|
||||||
margin-right: 3px;
|
|
||||||
opacity: 0.7;
|
|
||||||
min-width: 14px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.members {
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
.member-preview {
|
|
||||||
margin-left: -10px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.member {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 2px solid white;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
.team-folder {
|
|
||||||
.member-count {
|
|
||||||
color: $dark_mode_text_secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.members .member {
|
|
||||||
border-color: $dark_mode_foreground;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="create-team-folder">
|
|
||||||
<!--Title-->
|
|
||||||
<PopupHeader :title="popupTitle" icon="user-plus" />
|
|
||||||
|
|
||||||
<!--Content-->
|
|
||||||
<PopupContent>
|
|
||||||
<!--Item Thumbnail-->
|
|
||||||
<ThumbnailItem v-if="!isNewFolderTeamCreation" class="mb-5" :item="item" />
|
|
||||||
|
|
||||||
<!--Form to set team folder-->
|
|
||||||
<ValidationObserver @submit.prevent="createTeamFolder" ref="teamFolderForm" v-slot="{ invalid }" tag="form">
|
|
||||||
<!--Set folder name-->
|
|
||||||
<ValidationProvider
|
|
||||||
v-if="isNewFolderTeamCreation"
|
|
||||||
tag="div"
|
|
||||||
mode="passive"
|
|
||||||
name="Name"
|
|
||||||
rules="required"
|
|
||||||
v-slot="{ errors }"
|
|
||||||
>
|
|
||||||
<AppInputText :title="$t('popup_create_folder.label')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="name"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="text"
|
|
||||||
ref="name"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:placeholder="$t('popup_create_folder.placeholder')"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<!--Add Member-->
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Email" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('add_member')" :error="errors[0]">
|
|
||||||
<div class="relative">
|
|
||||||
<span
|
|
||||||
v-if="email"
|
|
||||||
@click="addMember"
|
|
||||||
class="button-base theme absolute right-2 top-1/2 -translate-y-1/2 transform cursor-pointer rounded-lg px-3 py-2 text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('add') }}
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
@keypress.enter.stop.prevent="addMember"
|
|
||||||
ref="email"
|
|
||||||
v-model="email"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="email"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:placeholder="$t('type_member_email_')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<!--Member list-->
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Members" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('your_members')" :error="errors[0]" :is-last="true">
|
|
||||||
<span v-if="errors[0]" class="error-message" style="margin-top: -5px">
|
|
||||||
{{ $t('add_at_least_one_member') }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<TeamList v-model="invitations" />
|
|
||||||
|
|
||||||
<p v-if="Object.values(invitations).length === 0" class="text-xs dark:text-gray-500">
|
|
||||||
{{ $t('add_at_least_one_member_into_team_folder') }}
|
|
||||||
</p>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<InfoBox v-if="!isNewFolderTeamCreation" class="mt-2.5 !mb-0">
|
|
||||||
<p v-html="$t('popup.move_into_team_disclaimer')"></p>
|
|
||||||
</InfoBox>
|
|
||||||
</ValidationObserver>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
|
||||||
>{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase
|
|
||||||
class="w-full"
|
|
||||||
@click.native="createTeamFolder"
|
|
||||||
button-style="theme"
|
|
||||||
:loading="isLoading"
|
|
||||||
:disabled="isLoading"
|
|
||||||
>{{ popupSubmit }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import PopupWrapper from '../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../Popups/Components/PopupHeader'
|
|
||||||
import ThumbnailItem from '../UI/Entries/ThumbnailItem'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import TeamList from './Components/TeamList'
|
|
||||||
import { required } from 'vee-validate/dist/rules'
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'CreateTeamFolderPopup',
|
|
||||||
components: {
|
|
||||||
ValidationProvider,
|
|
||||||
ValidationObserver,
|
|
||||||
AppInputText,
|
|
||||||
TeamList,
|
|
||||||
ThumbnailItem,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
required,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
popupTitle() {
|
|
||||||
return this.item ? this.$t('convert_as_team_folder') : this.$t('create_team_folder')
|
|
||||||
},
|
|
||||||
popupSubmit() {
|
|
||||||
return this.item ? this.$t('move_and_invite_members') : this.$t('create_team_folder')
|
|
||||||
},
|
|
||||||
isNewFolderTeamCreation() {
|
|
||||||
return !this.item
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
invitations: [],
|
|
||||||
item: undefined,
|
|
||||||
name: undefined,
|
|
||||||
email: undefined,
|
|
||||||
isLoading: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async createTeamFolder() {
|
|
||||||
const isValid = await this.$refs.teamFolderForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.isLoading = true
|
|
||||||
|
|
||||||
let route = this.name ? `/api/teams/folders` : `/api/teams/folders/${this.item.data.id}/convert`
|
|
||||||
|
|
||||||
let payload = this.name
|
|
||||||
? {
|
|
||||||
name: this.name,
|
|
||||||
invitations: this.invitations,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
invitations: this.invitations,
|
|
||||||
}
|
|
||||||
|
|
||||||
axios
|
|
||||||
.post(route, payload)
|
|
||||||
.then((response) => {
|
|
||||||
let isTeamFoldersLocation = this.$isThisRoute(this.$route, ['TeamFolders'])
|
|
||||||
|
|
||||||
// Redirect into newly created team folder
|
|
||||||
if (isTeamFoldersLocation && this.$route.params.id) {
|
|
||||||
this.$router.push({
|
|
||||||
name: 'TeamFolders',
|
|
||||||
params: { id: response.data.data.id },
|
|
||||||
})
|
|
||||||
|
|
||||||
// Add created team folder into Team Folder homepage view
|
|
||||||
} else if (isTeamFoldersLocation && !this.$route.params.id) {
|
|
||||||
this.$store.commit('ADD_NEW_FOLDER', response.data)
|
|
||||||
|
|
||||||
// Redirect to Team Folders after converting simple folder
|
|
||||||
} else if (!isTeamFoldersLocation) {
|
|
||||||
this.$router.push({ name: 'TeamFolders' })
|
|
||||||
}
|
|
||||||
|
|
||||||
let toasterMessage = this.isNewFolderTeamCreation
|
|
||||||
? this.$t('team_was_invited')
|
|
||||||
: this.$t('team_was_invited_and_folder_moved')
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: toasterMessage,
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$store.dispatch('getAppData')
|
|
||||||
})
|
|
||||||
.catch(() => this.$isSomethingWrong())
|
|
||||||
.finally(() => {
|
|
||||||
this.isLoading = false
|
|
||||||
this.name = undefined
|
|
||||||
this.invitations = undefined
|
|
||||||
|
|
||||||
this.$closePopup()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addMember() {
|
|
||||||
if (!this.$isValidEmail(this.email)) {
|
|
||||||
this.$refs.teamFolderForm.setErrors({
|
|
||||||
Email: this.$t('type_valid_email'),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.$cantInviteMember(this.email, this.invitations)) {
|
|
||||||
this.$refs.teamFolderForm.setErrors({
|
|
||||||
Email: this.$t('upgrade_to_invite_members'),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$refs.teamFolderForm.reset()
|
|
||||||
|
|
||||||
this.invitations.unshift({
|
|
||||||
type: 'invitation',
|
|
||||||
email: this.email,
|
|
||||||
permission: 'can-edit',
|
|
||||||
})
|
|
||||||
|
|
||||||
this.email = undefined
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('popup:open', (args) => {
|
|
||||||
if (args.name !== 'create-team-folder') return
|
|
||||||
|
|
||||||
this.item = args.item
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$isMobile()) return
|
|
||||||
|
|
||||||
if (this.item) this.$refs.email.focus()
|
|
||||||
|
|
||||||
if (!this.item && this.$refs.name) this.$refs.name.focus()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
events.$on('popup:close', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.email = undefined
|
|
||||||
this.name = undefined
|
|
||||||
this.item = undefined
|
|
||||||
this.invitations = []
|
|
||||||
}, 150)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="update-team-folder">
|
|
||||||
<!--Title-->
|
|
||||||
<PopupHeader :title="$t('edit_team_folder')" icon="user-plus" />
|
|
||||||
|
|
||||||
<!--Content-->
|
|
||||||
<PopupContent>
|
|
||||||
<!--Item Thumbnail-->
|
|
||||||
<ThumbnailItem class="mb-5" :item="item" />
|
|
||||||
|
|
||||||
<!--Form to set team folder-->
|
|
||||||
<ValidationObserver @submit.prevent="updateTeamFolder" ref="teamFolderForm" v-slot="{ invalid }" tag="form">
|
|
||||||
<!--Add Member-->
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Email" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('add_member')" :error="errors[0]">
|
|
||||||
<div class="relative">
|
|
||||||
<span
|
|
||||||
v-if="email"
|
|
||||||
@click="addMember"
|
|
||||||
class="button-base theme absolute right-2 top-1/2 -translate-y-1/2 transform cursor-pointer rounded-lg px-3 py-2 text-sm font-bold"
|
|
||||||
>
|
|
||||||
{{ $t('add') }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!--TODO: Fix !pr-20 after JIT official release-->
|
|
||||||
<input
|
|
||||||
@keypress.enter.stop.prevent="addMember"
|
|
||||||
ref="email"
|
|
||||||
v-model="email"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="email"
|
|
||||||
class="focus-border-theme input-dark !pr-20"
|
|
||||||
:placeholder="$t('type_member_email_')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<!--Member list-->
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Members" v-slot="{ errors }">
|
|
||||||
<label class="input-label">{{ $t('your_members') }}:</label>
|
|
||||||
<span v-if="errors[0]" class="error-message" style="margin-top: -5px">{{
|
|
||||||
$t('add_at_least_one_member')
|
|
||||||
}}</span>
|
|
||||||
<TeamList v-model="members" />
|
|
||||||
<TeamList v-model="invitations" />
|
|
||||||
|
|
||||||
<p
|
|
||||||
v-if="Object.values(members).length === 0 && Object.values(invitations).length === 0"
|
|
||||||
class="text-xs dark:text-gray-500"
|
|
||||||
>
|
|
||||||
{{ $t('add_at_least_one_member_into_team_folder') }}
|
|
||||||
</p>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions>
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
|
||||||
>{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase
|
|
||||||
class="w-full"
|
|
||||||
@click.native="updateTeamFolder"
|
|
||||||
:button-style="isDisabledSubmit ? 'secondary' : 'theme'"
|
|
||||||
:loading="isLoading"
|
|
||||||
:disabled="isLoading || isDisabledSubmit"
|
|
||||||
>{{ $t('update_team_folder') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import PopupWrapper from '../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../Popups/Components/PopupHeader'
|
|
||||||
import ThumbnailItem from '../UI/Entries/ThumbnailItem'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import TeamList from './Components/TeamList'
|
|
||||||
import { required } from 'vee-validate/dist/rules'
|
|
||||||
import InfoBox from '../UI/Others/InfoBox'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'EditTeamFolderPopup',
|
|
||||||
components: {
|
|
||||||
ValidationProvider,
|
|
||||||
ValidationObserver,
|
|
||||||
AppInputText,
|
|
||||||
TeamList,
|
|
||||||
ThumbnailItem,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
required,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['user']),
|
|
||||||
isDisabledSubmit() {
|
|
||||||
return Object.values(this.members).length === 0 && Object.values(this.invitations).length === 0
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
invitations: [],
|
|
||||||
members: [],
|
|
||||||
item: undefined,
|
|
||||||
name: undefined,
|
|
||||||
email: undefined,
|
|
||||||
isLoading: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async updateTeamFolder() {
|
|
||||||
const isValid = await this.$refs.teamFolderForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.isLoading = true
|
|
||||||
|
|
||||||
axios
|
|
||||||
.patch(`/api/teams/folders/${this.item.data.id}`, {
|
|
||||||
members: this.members,
|
|
||||||
invitations: this.invitations,
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
this.$store.commit('UPDATE_ITEM', response.data)
|
|
||||||
this.$store.commit('SET_CURRENT_TEAM_FOLDER', response.data)
|
|
||||||
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: this.$t('team_folder_updated'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'danger',
|
|
||||||
message: this.$t('popup_error.title'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.isLoading = false
|
|
||||||
this.name = undefined
|
|
||||||
this.invitations = undefined
|
|
||||||
this.members = undefined
|
|
||||||
|
|
||||||
this.$closePopup()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addMember() {
|
|
||||||
if (!this.$isValidEmail(this.email)) {
|
|
||||||
this.$refs.teamFolderForm.setErrors({
|
|
||||||
Email: this.$t('type_valid_email'),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.$cantInviteMember(this.email, this.invitations)) {
|
|
||||||
this.$refs.teamFolderForm.setErrors({
|
|
||||||
Email: this.$t('upgrade_to_invite_members'),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$refs.teamFolderForm.reset()
|
|
||||||
|
|
||||||
this.invitations.unshift({
|
|
||||||
type: 'invitation',
|
|
||||||
email: this.email,
|
|
||||||
permission: 'can-edit',
|
|
||||||
})
|
|
||||||
|
|
||||||
this.email = undefined
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
events.$on('popup:open', (args) => {
|
|
||||||
if (args.name !== 'update-team-folder') return
|
|
||||||
|
|
||||||
this.item = args.item
|
|
||||||
|
|
||||||
this.members = args.item.data.relationships.members.data.map((member) => {
|
|
||||||
return {
|
|
||||||
type: 'member',
|
|
||||||
id: member.data.id,
|
|
||||||
email: member.data.attributes.email,
|
|
||||||
name: member.data.attributes.name,
|
|
||||||
avatar: member.data.attributes.avatar,
|
|
||||||
color: member.data.attributes.color,
|
|
||||||
permission: member.data.attributes.permission,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.invitations = args.item.data.relationships.invitations.data.map((member) => {
|
|
||||||
return {
|
|
||||||
id: member.data.id,
|
|
||||||
type: 'invitation',
|
|
||||||
email: member.data.attributes.email,
|
|
||||||
color: member.data.attributes.color,
|
|
||||||
permission: member.data.attributes.permission,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.email && !this.$isMobile()) this.$refs.email.focus()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
events.$on('popup:close', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.email = undefined
|
|
||||||
this.name = undefined
|
|
||||||
this.item = undefined
|
|
||||||
this.invitations = []
|
|
||||||
this.members = []
|
|
||||||
}, 150)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
@import '../../../sass/vuefilemanager/inapp-forms';
|
|
||||||
@import '../../../sass/vuefilemanager/forms';
|
|
||||||
|
|
||||||
.item-thumbnail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,17 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="toasters.length || notifications.length"
|
v-if="toasters.length"
|
||||||
class="fixed bottom-4 right-4 left-4 z-[55] sm:w-[360px] sm:left-auto lg:bottom-8 lg:right-8"
|
class="fixed bottom-4 right-4 left-4 z-[55] sm:w-[360px] sm:left-auto lg:bottom-8 lg:right-8"
|
||||||
>
|
>
|
||||||
<ToasterWrapper
|
|
||||||
v-for="notification in notifications"
|
|
||||||
:key="notification.data.id"
|
|
||||||
class="mt-4 overflow-hidden rounded-xl dark:bg-2x-dark-foreground bg-white/80 backdrop-blur-2xl shadow-xl"
|
|
||||||
bar-color="bg-theme"
|
|
||||||
>
|
|
||||||
<Notification :notification="notification" class="z-10 !mb-0 !px-4 !pt-4 !pb-5" />
|
|
||||||
</ToasterWrapper>
|
|
||||||
|
|
||||||
<ToasterWrapper
|
<ToasterWrapper
|
||||||
v-for="(toaster, i) in toasters"
|
v-for="(toaster, i) in toasters"
|
||||||
:key="i"
|
:key="i"
|
||||||
@@ -24,7 +15,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Notification from '../Notifications/Components/Notification'
|
|
||||||
import ToasterWrapper from './ToasterWrapper'
|
import ToasterWrapper from './ToasterWrapper'
|
||||||
import {events} from '../../bus'
|
import {events} from '../../bus'
|
||||||
import Toaster from './Toaster'
|
import Toaster from './Toaster'
|
||||||
@@ -32,12 +22,10 @@ import Toaster from './Toaster'
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ToasterWrapper,
|
ToasterWrapper,
|
||||||
Notification,
|
|
||||||
Toaster,
|
Toaster,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
notifications: [],
|
|
||||||
toasters: [],
|
toasters: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -51,29 +39,6 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
events.$on('toaster', (toaster) => this.toasters.push(toaster))
|
events.$on('toaster', (toaster) => this.toasters.push(toaster))
|
||||||
events.$on('notification', (notification) => this.notifications.push(notification))
|
|
||||||
|
|
||||||
/*events.$emit('notification', {
|
|
||||||
data: {
|
|
||||||
type: 'file-request',
|
|
||||||
id: 'df954d23-f9d4-4677-85c8-abfd48aaa090',
|
|
||||||
attributes: {
|
|
||||||
action: {
|
|
||||||
type: 'route',
|
|
||||||
params: {
|
|
||||||
route: 'Files',
|
|
||||||
button: 'Show Files',
|
|
||||||
id: 'ae37b1d8-c147-489a-83ab-2a3c7cb86263',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created_at: '',
|
|
||||||
description: "Your file request for 'Multi Level Folder' folder was filled successfully.",
|
|
||||||
read_at: '',
|
|
||||||
title: 'File Request Filled',
|
|
||||||
category: 'file-request',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})*/
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
v-if="config.allowedFacebookLogin || config.allowedGoogleLogin || config.allowedGithubLogin"
|
|
||||||
class="mb-10 flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<div v-if="config.allowedFacebookLogin" class="mx-5 cursor-pointer">
|
|
||||||
<facebook-icon @click="socialiteRedirect('facebook')" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="config.allowedGithubLogin" class="mx-5 cursor-pointer">
|
|
||||||
<github-icon @click="socialiteRedirect('github')" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="config.allowedGoogleLogin" class="mx-5 cursor-pointer">
|
|
||||||
<google-icon @click.native="socialiteRedirect('google')" class="vue-feather"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { FacebookIcon, GithubIcon } from 'vue-feather-icons'
|
|
||||||
import GoogleIcon from "../../Icons/GoogleIcon"
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SocialLoginButtons',
|
|
||||||
components: {
|
|
||||||
FacebookIcon,
|
|
||||||
GoogleIcon,
|
|
||||||
GithubIcon,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config']),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
socialiteRedirect(provider) {
|
|
||||||
this.$store.dispatch('socialiteRedirect', provider)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -11,29 +11,20 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<NotificationBell @click.native="openNotificationPopup" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MemberAvatar from './MemberAvatar'
|
import MemberAvatar from './MemberAvatar'
|
||||||
import NotificationBell from '../../Notifications/Components/NotificationBell'
|
|
||||||
import { events } from '../../../bus'
|
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UserHeadline',
|
name: 'UserHeadline',
|
||||||
components: {
|
components: {
|
||||||
NotificationBell,
|
|
||||||
MemberAvatar,
|
MemberAvatar,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['user']),
|
...mapGetters(['user']),
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
openNotificationPopup() {
|
|
||||||
events.$emit('popup:open', { name: 'notifications-mobile' })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,210 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PopupWrapper name="create-file-request">
|
|
||||||
<!--Title-->
|
|
||||||
<PopupHeader :title="$t('create_file_request')" icon="upload" />
|
|
||||||
|
|
||||||
<!--Content-->
|
|
||||||
<PopupContent>
|
|
||||||
<!--Item Thumbnail-->
|
|
||||||
<ThumbnailItem v-if="pickedItem" class="mb-5" :item="pickedItem" />
|
|
||||||
|
|
||||||
<!--Form to set upload request-->
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="!generatedUploadRequest"
|
|
||||||
@submit.prevent="createUploadRequest"
|
|
||||||
ref="createForm"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
>
|
|
||||||
<!--Set name-->
|
|
||||||
<ValidationProvider
|
|
||||||
tag="div"
|
|
||||||
mode="passive"
|
|
||||||
name="Name"
|
|
||||||
v-slot="{ errors }"
|
|
||||||
>
|
|
||||||
<AppInputText :title="$t('folder_name_optional')" :description="$t('folder_name_optional_description')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="form.name"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="text"
|
|
||||||
ref="input"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:placeholder="$t('type_name_')"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<!--Set note-->
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Note" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('message_optional')" :description="$t('message_optional_description')" :error="errors[0]">
|
|
||||||
<textarea
|
|
||||||
v-model="form.notes"
|
|
||||||
rows="2"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="text"
|
|
||||||
ref="input"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:placeholder="$t('message_for_recipient')"
|
|
||||||
></textarea>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<!--Send Request by Email-->
|
|
||||||
<AppInputSwitch
|
|
||||||
:title="$t('send_request_by_email')"
|
|
||||||
:description="$t('send_request_by_email_description')"
|
|
||||||
:is-last="! shareViaEmail"
|
|
||||||
>
|
|
||||||
<SwitchInput v-model="shareViaEmail" :state="shareViaEmail" />
|
|
||||||
</AppInputSwitch>
|
|
||||||
|
|
||||||
<!--Set email-->
|
|
||||||
<ValidationProvider
|
|
||||||
v-if="shareViaEmail"
|
|
||||||
tag="div"
|
|
||||||
mode="passive"
|
|
||||||
name="Email"
|
|
||||||
rules="required"
|
|
||||||
v-slot="{ errors }"
|
|
||||||
>
|
|
||||||
<AppInputText :error="errors[0]" class="-mt-2" :is-last="true">
|
|
||||||
<input
|
|
||||||
v-model="form.email"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
type="text"
|
|
||||||
ref="input"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
:placeholder="$t('type_email_')"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
</ValidationObserver>
|
|
||||||
|
|
||||||
<!--Copy generated link-->
|
|
||||||
<AppInputText v-if="generatedUploadRequest" :title="$t('copy_upload_request_link')" :is-last="true">
|
|
||||||
<CopyInput :str="generatedUploadRequest.data.attributes.url" />
|
|
||||||
</AppInputText>
|
|
||||||
</PopupContent>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions v-if="!generatedUploadRequest">
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="secondary"
|
|
||||||
>{{ $t('cancel') }}
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase class="w-full" @click.native="createUploadRequest" :loading="isLoading" button-style="theme"
|
|
||||||
>{{ $t('create_request') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
|
|
||||||
<!--Actions-->
|
|
||||||
<PopupActions v-if="generatedUploadRequest">
|
|
||||||
<ButtonBase class="w-full" @click.native="$closePopup()" button-style="theme"
|
|
||||||
>{{ $t('awesome_iam_done') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</PopupActions>
|
|
||||||
</PopupWrapper>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
|
|
||||||
import AppInputSwitch from '../Forms/Layouts/AppInputSwitch'
|
|
||||||
import {required} from 'vee-validate/dist/rules'
|
|
||||||
import ButtonBase from '../UI/Buttons/ButtonBase'
|
|
||||||
import AppInputText from '../Forms/Layouts/AppInputText'
|
|
||||||
import PopupWrapper from '../Popups/Components/PopupWrapper'
|
|
||||||
import PopupActions from '../Popups/Components/PopupActions'
|
|
||||||
import PopupContent from '../Popups/Components/PopupContent'
|
|
||||||
import PopupHeader from '../Popups/Components/PopupHeader'
|
|
||||||
import SwitchInput from '../Inputs/SwitchInput'
|
|
||||||
import ThumbnailItem from '../UI/Entries/ThumbnailItem'
|
|
||||||
import CopyInput from '../Inputs/CopyInput'
|
|
||||||
import {events} from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'CreateUploadRequestPopup',
|
|
||||||
components: {
|
|
||||||
ValidationProvider,
|
|
||||||
ValidationObserver,
|
|
||||||
AppInputSwitch,
|
|
||||||
ThumbnailItem,
|
|
||||||
AppInputText,
|
|
||||||
PopupWrapper,
|
|
||||||
PopupActions,
|
|
||||||
PopupContent,
|
|
||||||
SwitchInput,
|
|
||||||
PopupHeader,
|
|
||||||
ButtonBase,
|
|
||||||
CopyInput,
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
form: {
|
|
||||||
email: undefined,
|
|
||||||
notes: undefined,
|
|
||||||
folder_id: undefined,
|
|
||||||
name: undefined,
|
|
||||||
},
|
|
||||||
generatedUploadRequest: undefined,
|
|
||||||
shareViaEmail: false,
|
|
||||||
pickedItem: undefined,
|
|
||||||
isLoading: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async createUploadRequest() {
|
|
||||||
// Validate fields
|
|
||||||
const isValid = await this.$refs.createForm.validate()
|
|
||||||
|
|
||||||
if (!isValid) return
|
|
||||||
|
|
||||||
this.isLoading = true
|
|
||||||
|
|
||||||
// Send request to get share link
|
|
||||||
axios
|
|
||||||
.post(`/api/upload-request`, this.form)
|
|
||||||
.then((response) => {
|
|
||||||
this.generatedUploadRequest = response.data
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: this.$t('popup_error.title'),
|
|
||||||
message: this.$t('popup_error.message'),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.isLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
events.$on('popup:open', (args) => {
|
|
||||||
if (args.name === 'create-file-request') {
|
|
||||||
this.pickedItem = args.item
|
|
||||||
this.form.folder_id = args.item?.data.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Close popup
|
|
||||||
events.$on('popup:close', () => {
|
|
||||||
|
|
||||||
// Restore data
|
|
||||||
setTimeout(() => {
|
|
||||||
this.generatedUploadRequest = undefined
|
|
||||||
this.pickedItem = undefined
|
|
||||||
|
|
||||||
this.shareViaEmail = false
|
|
||||||
|
|
||||||
this.form = {
|
|
||||||
name: undefined,
|
|
||||||
email: undefined,
|
|
||||||
notes: undefined,
|
|
||||||
folder_id: undefined,
|
|
||||||
}
|
|
||||||
}, 150)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
const ValidatorHelpers = {
|
|
||||||
install(Vue) {
|
|
||||||
Vue.prototype.$generatePaystackReference = function () {
|
|
||||||
let text = ''
|
|
||||||
|
|
||||||
let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) text += possible.charAt(Math.floor(Math.random() * possible.length))
|
|
||||||
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ValidatorHelpers
|
|
||||||
-26
@@ -1,31 +1,5 @@
|
|||||||
import store from '../store/index'
|
|
||||||
|
|
||||||
const ValidatorHelpers = {
|
const ValidatorHelpers = {
|
||||||
install(Vue) {
|
install(Vue) {
|
||||||
Vue.prototype.$cantInviteMember = function (email, invitations) {
|
|
||||||
if (['metered', 'none'].includes(store.getters.config.subscriptionType)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get max team members limitations
|
|
||||||
let limit = store.getters.user.data.meta.limitations.max_team_members
|
|
||||||
|
|
||||||
// Unlimited option
|
|
||||||
if (limit.total === -1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get emails from invitations and currently active members
|
|
||||||
let newInvitationEmails = invitations.map((item) => item['email'])
|
|
||||||
let allowedMemberEmails = limit.meta.allowed_emails
|
|
||||||
|
|
||||||
// Get unique list of member emails
|
|
||||||
let totalUniqueEmails = [...new Set(newInvitationEmails.concat(Object.values(allowedMemberEmails)))]
|
|
||||||
|
|
||||||
// If there is more unique emails than can be in limit, disable ability to add member
|
|
||||||
return totalUniqueEmails.length >= limit.total && !totalUniqueEmails.includes(email)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$isValidEmail = function (email) {
|
Vue.prototype.$isValidEmail = function (email) {
|
||||||
return email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/) !== null
|
return email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/) !== null
|
||||||
}
|
}
|
||||||
|
|||||||
-125
@@ -141,14 +141,6 @@ const FunctionHelpers = {
|
|||||||
return source ? store.getters.config.host + '/' + source : ''
|
return source ? store.getters.config.host + '/' + source : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$getCreditCardBrand = function (brand) {
|
|
||||||
return `/assets/icons/${brand}.svg`
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getInvoiceLink = function (id) {
|
|
||||||
return '/invoices/' + id
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$uploadFiles = async function (files) {
|
Vue.prototype.$uploadFiles = async function (files) {
|
||||||
// Show alert message when upload is disabled
|
// Show alert message when upload is disabled
|
||||||
if (store.getters.user && !store.getters.user.data.meta.restrictions.canUpload) {
|
if (store.getters.user && !store.getters.user.data.meta.restrictions.canUpload) {
|
||||||
@@ -289,14 +281,11 @@ const FunctionHelpers = {
|
|||||||
return store.getters.currentFolder.data.attributes.name
|
return store.getters.currentFolder.data.attributes.name
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
RequestUpload: this.$t('home'),
|
|
||||||
RecentUploads: this.$t('menu.latest'),
|
RecentUploads: this.$t('menu.latest'),
|
||||||
MySharedItems: this.$t('publicly_shared'),
|
MySharedItems: this.$t('publicly_shared'),
|
||||||
Trash: this.$t('trash'),
|
Trash: this.$t('trash'),
|
||||||
Public: this.$t('menu.files'),
|
Public: this.$t('menu.files'),
|
||||||
Files: this.$t('sidebar.home'),
|
Files: this.$t('sidebar.home'),
|
||||||
TeamFolders: this.$t('team_folders'),
|
|
||||||
SharedWithMe: this.$t('shared_with_me'),
|
|
||||||
}[this.$route.name]
|
}[this.$route.name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,8 +297,6 @@ const FunctionHelpers = {
|
|||||||
Trash: this.$t('trash'),
|
Trash: this.$t('trash'),
|
||||||
Public: this.$t('menu.files'),
|
Public: this.$t('menu.files'),
|
||||||
Files: this.$t('sidebar.home'),
|
Files: this.$t('sidebar.home'),
|
||||||
TeamFolders: this.$t('team_folders'),
|
|
||||||
SharedWithMe: this.$t('shared_with_me'),
|
|
||||||
}[this.$route.name]
|
}[this.$route.name]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,89 +307,21 @@ const FunctionHelpers = {
|
|||||||
Trash: 'trash2',
|
Trash: 'trash2',
|
||||||
Public: 'hard-drive',
|
Public: 'hard-drive',
|
||||||
Files: 'hard-drive',
|
Files: 'hard-drive',
|
||||||
TeamFolders: 'users',
|
|
||||||
SharedWithMe: 'user-check',
|
|
||||||
}[this.$router.currentRoute.name]
|
}[this.$router.currentRoute.name]
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$getDataByLocation = function () {
|
Vue.prototype.$getDataByLocation = function () {
|
||||||
let routes = {
|
let routes = {
|
||||||
RequestUpload: ['getUploadRequestFolder', router.currentRoute.params.id || undefined ],
|
|
||||||
Public: ['getSharedFolder', router.currentRoute.params.id || undefined],
|
Public: ['getSharedFolder', router.currentRoute.params.id || undefined],
|
||||||
Files: ['getFolder', router.currentRoute.params.id || undefined],
|
Files: ['getFolder', router.currentRoute.params.id || undefined],
|
||||||
RecentUploads: ['getRecentUploads'],
|
RecentUploads: ['getRecentUploads'],
|
||||||
MySharedItems: ['getMySharedItems'],
|
MySharedItems: ['getMySharedItems'],
|
||||||
Trash: ['getTrash', router.currentRoute.params.id || undefined],
|
Trash: ['getTrash', router.currentRoute.params.id || undefined],
|
||||||
TeamFolders: ['getTeamFolder', router.currentRoute.params.id || undefined],
|
|
||||||
SharedWithMe: ['getSharedWithMeFolder', router.currentRoute.params.id || undefined],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch(...routes[router.currentRoute.name])
|
store.dispatch(...routes[router.currentRoute.name])
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$getPaymentLogo = function (driver) {
|
|
||||||
return (
|
|
||||||
{
|
|
||||||
paypal: store.getters.isDarkMode
|
|
||||||
? '/assets/payments/paypal-dark.svg'
|
|
||||||
: '/assets/payments/paypal.svg',
|
|
||||||
paystack: store.getters.isDarkMode
|
|
||||||
? '/assets/payments/paystack-dark.svg'
|
|
||||||
: '/assets/payments/paystack.svg',
|
|
||||||
stripe: '/assets/payments/stripe.svg',
|
|
||||||
system: store.getters.isDarkMode
|
|
||||||
? this.$getImage(store.getters.config.app_logo_horizontal_dark)
|
|
||||||
: this.$getImage(store.getters.config.app_logo_horizontal),
|
|
||||||
}[driver] || this.$getImage(store.getters.config.app_logo_horizontal)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getSocialLogo = function (driver) {
|
|
||||||
return {
|
|
||||||
google: '/assets/socials/google.svg',
|
|
||||||
facebook: '/assets/socials/facebook.svg',
|
|
||||||
github: store.getters.isDarkMode ? '/assets/socials/github-dark.svg' : '/assets/socials/github.svg',
|
|
||||||
}[driver]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getSubscriptionStatusColor = function (status) {
|
|
||||||
return {
|
|
||||||
active: 'green',
|
|
||||||
cancelled: 'yellow',
|
|
||||||
completed: 'purple',
|
|
||||||
}[status]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getTransactionStatusColor = function (status) {
|
|
||||||
return {
|
|
||||||
completed: 'green',
|
|
||||||
cancelled: 'yellow',
|
|
||||||
error: 'red',
|
|
||||||
}[status]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getTransactionTypeColor = function (type) {
|
|
||||||
return {
|
|
||||||
credit: 'green',
|
|
||||||
charge: 'purple',
|
|
||||||
withdrawal: 'red',
|
|
||||||
}[type]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getTransactionStatusColor = function (type) {
|
|
||||||
return {
|
|
||||||
completed: 'green',
|
|
||||||
error: 'red',
|
|
||||||
}[type]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getPlanStatusColor = function (type) {
|
|
||||||
return {
|
|
||||||
active: 'green',
|
|
||||||
archived: 'red',
|
|
||||||
}[type]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getUserRoleColor = function (role) {
|
Vue.prototype.$getUserRoleColor = function (role) {
|
||||||
return {
|
return {
|
||||||
admin: 'purple',
|
admin: 'purple',
|
||||||
@@ -410,28 +329,9 @@ const FunctionHelpers = {
|
|||||||
}[role]
|
}[role]
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$getTransactionTypeTextColor = function (type) {
|
|
||||||
return {
|
|
||||||
withdrawal: 'text-red',
|
|
||||||
credit: 'text-green',
|
|
||||||
charge: '',
|
|
||||||
}[type]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$getTransactionMark = function (type) {
|
|
||||||
return {
|
|
||||||
withdrawal: '-',
|
|
||||||
credit: '+',
|
|
||||||
charge: '',
|
|
||||||
}[type]
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$goToFileView = function (id) {
|
Vue.prototype.$goToFileView = function (id) {
|
||||||
let locations = {
|
let locations = {
|
||||||
RequestUpload: {name: 'RequestUpload', params: { token: this.$route.params.token, id: id }},
|
|
||||||
Public: {name: 'Public', params: { token: this.$route.params.token, id: id }},
|
Public: {name: 'Public', params: { token: this.$route.params.token, id: id }},
|
||||||
TeamFolders: { name: 'TeamFolders', params: { id: id } },
|
|
||||||
SharedWithMe: { name: 'SharedWithMe', params: { id: id } },
|
|
||||||
MySharedItems: { name: 'Files', params: { id: id } },
|
MySharedItems: { name: 'Files', params: { id: id } },
|
||||||
Trash: { name: 'Trash', params: { id: id } },
|
Trash: { name: 'Trash', params: { id: id } },
|
||||||
Files: { name: 'Files', params: { id: id } },
|
Files: { name: 'Files', params: { id: id } },
|
||||||
@@ -524,19 +424,6 @@ const FunctionHelpers = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$mapIntoMemberResource = function (entry) {
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
attributes: {
|
|
||||||
avatar: entry.avatar,
|
|
||||||
name: entry.name,
|
|
||||||
email: entry.email,
|
|
||||||
color: entry.color,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$closePopup = function () {
|
Vue.prototype.$closePopup = function () {
|
||||||
events.$emit('popup:close')
|
events.$emit('popup:close')
|
||||||
}
|
}
|
||||||
@@ -561,18 +448,6 @@ const FunctionHelpers = {
|
|||||||
Vue.prototype.$showMobileMenu = function (name) {
|
Vue.prototype.$showMobileMenu = function (name) {
|
||||||
events.$emit('mobile-menu:show', name)
|
events.$emit('mobile-menu:show', name)
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$openSubscribeOptions = function () {
|
|
||||||
events.$emit('popup:open', { name: 'select-plan-subscription' })
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$changeSubscriptionOptions = function () {
|
|
||||||
events.$emit('popup:open', { name: 'change-plan-subscription' })
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$openRemoteUploadPopup = function () {
|
|
||||||
events.$emit('popup:open', {name: 'remote-upload'})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
-58
@@ -103,64 +103,6 @@ const itemHelpers = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.prototype.$dissolveTeamFolder = function (folder) {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: i18n.t('really_dissolve_team'),
|
|
||||||
message: i18n.t(
|
|
||||||
'really_dissolve_team_desc'
|
|
||||||
),
|
|
||||||
action: {
|
|
||||||
id: folder.data.id,
|
|
||||||
operation: 'dissolve-team-folder',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$detachMeFromTeamFolder = function (folder) {
|
|
||||||
events.$emit('confirm:open', {
|
|
||||||
title: i18n.t('really_leave_team'),
|
|
||||||
message: i18n.t(
|
|
||||||
"really_leave_team_desc"
|
|
||||||
),
|
|
||||||
action: {
|
|
||||||
id: folder.data.id,
|
|
||||||
operation: 'leave-team-folder',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$createTeamFolder = function () {
|
|
||||||
// Show alert message when create folder is disabled
|
|
||||||
if (!store.getters.user.data.meta.restrictions.canCreateTeamFolder) {
|
|
||||||
Vue.prototype.$temporarilyDisabledFolderCreate()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
events.$emit('popup:open', { name: 'create-team-folder' })
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$convertAsTeamFolder = function (entry) {
|
|
||||||
events.$emit('popup:open', {
|
|
||||||
name: 'create-team-folder',
|
|
||||||
item: entry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$createFileRequest = function (entry = undefined) {
|
|
||||||
events.$emit('popup:open', {
|
|
||||||
name: 'create-file-request',
|
|
||||||
item: entry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$updateTeamFolder = function (entry) {
|
|
||||||
events.$emit('popup:open', {
|
|
||||||
name: 'update-team-folder',
|
|
||||||
item: entry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.prototype.$removeFavourite = function (folder) {
|
Vue.prototype.$removeFavourite = function (folder) {
|
||||||
store.dispatch('removeFromFavourites', folder)
|
store.dispatch('removeFromFavourites', folder)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-2
@@ -7,7 +7,6 @@ import App from './App.vue'
|
|||||||
import store from './store'
|
import store from './store'
|
||||||
import { events } from './bus'
|
import { events } from './bus'
|
||||||
|
|
||||||
import SubscriptionHelpers from './helpers/SubscriptionHelpers'
|
|
||||||
import ValidatorHelpers from './helpers/ValidatorHelpers'
|
import ValidatorHelpers from './helpers/ValidatorHelpers'
|
||||||
import functionHelpers from './helpers/functionHelpers'
|
import functionHelpers from './helpers/functionHelpers'
|
||||||
import AlertHelpers from './helpers/AlertHelpers'
|
import AlertHelpers from './helpers/AlertHelpers'
|
||||||
@@ -15,7 +14,6 @@ import itemHelpers from './helpers/itemHelpers'
|
|||||||
import { VueReCaptcha } from 'vue-recaptcha-v3'
|
import { VueReCaptcha } from 'vue-recaptcha-v3'
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
Vue.use(SubscriptionHelpers)
|
|
||||||
Vue.use(ValidatorHelpers)
|
Vue.use(ValidatorHelpers)
|
||||||
Vue.use(functionHelpers)
|
Vue.use(functionHelpers)
|
||||||
Vue.use(AlertHelpers)
|
Vue.use(AlertHelpers)
|
||||||
|
|||||||
Vendored
-6
@@ -1,13 +1,10 @@
|
|||||||
import routesUploadRequest from './routes/routesUploadRequest'
|
|
||||||
import routesMaintenance from './routes/routesMaintenance'
|
import routesMaintenance from './routes/routesMaintenance'
|
||||||
import routesShared from './routes/routesShared'
|
import routesShared from './routes/routesShared'
|
||||||
import routesOthers from './routes/routesOthers'
|
import routesOthers from './routes/routesOthers'
|
||||||
import routesAdmin from './routes/routesAdmin'
|
import routesAdmin from './routes/routesAdmin'
|
||||||
import routesIndex from './routes/routesIndex'
|
|
||||||
import routesAuth from './routes/routesAuth'
|
import routesAuth from './routes/routesAuth'
|
||||||
import routesUser from './routes/routesUser'
|
import routesUser from './routes/routesUser'
|
||||||
import routesFile from './routes/routesFile'
|
import routesFile from './routes/routesFile'
|
||||||
import routesTeam from './routes/routesTeam'
|
|
||||||
import store from './store/index'
|
import store from './store/index'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
@@ -17,16 +14,13 @@ Vue.use(Router)
|
|||||||
const router = new Router({
|
const router = new Router({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
routes: [
|
routes: [
|
||||||
...routesUploadRequest,
|
|
||||||
...routesMaintenance,
|
...routesMaintenance,
|
||||||
...routesShared,
|
...routesShared,
|
||||||
...routesOthers,
|
...routesOthers,
|
||||||
...routesAdmin,
|
...routesAdmin,
|
||||||
...routesIndex,
|
|
||||||
...routesAuth,
|
...routesAuth,
|
||||||
...routesUser,
|
...routesUser,
|
||||||
...routesFile,
|
...routesFile,
|
||||||
...routesTeam,
|
|
||||||
],
|
],
|
||||||
scrollBehavior(to, from, savedPosition) {
|
scrollBehavior(to, from, savedPosition) {
|
||||||
if (savedPosition) {
|
if (savedPosition) {
|
||||||
|
|||||||
Vendored
-243
@@ -17,51 +17,6 @@ const routesAdmin = [
|
|||||||
title: 'dashboard',
|
title: 'dashboard',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'Invoices',
|
|
||||||
path: '/admin/invoices',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/invoices" */ '../views/Admin/Invoices'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'transactions',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Subscriptions',
|
|
||||||
path: '/admin/subscriptions',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/subscriptions" */ '../views/Admin/Subscriptions'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'subscriptions',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Pages',
|
|
||||||
path: '/admin/pages',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/pages" */ '../views/Admin/Pages'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'pages',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PageEdit',
|
|
||||||
path: '/admin/pages/:slug',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/page-edit" */ '../views/Admin/Pages/PageEdit'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'edit_page',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Plans',
|
|
||||||
path: '/admin/plans',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/plans" */ '../views/Admin/Plans'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'pricing_plans',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
path: '/admin/users',
|
path: '/admin/users',
|
||||||
@@ -80,30 +35,6 @@ const routesAdmin = [
|
|||||||
title: 'create_user',
|
title: 'create_user',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'CreateFixedPlan',
|
|
||||||
path: '/admin/plan/create/fixed',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-create/fixed" */ '../views/Admin/Plans/Create/CreateFixedPlan'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'create_plan',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'CreateMeteredPlan',
|
|
||||||
path: '/admin/plan/create/metered',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-create/metered" */ '../views/Admin/Plans/Create/CreateMeteredPlan'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'create_plan',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin/user/:id',
|
path: '/admin/user/:id',
|
||||||
component: () => import(/* webpackChunkName: "chunks/user" */ '../views/Admin/Users/User'),
|
component: () => import(/* webpackChunkName: "chunks/user" */ '../views/Admin/Users/User'),
|
||||||
@@ -136,18 +67,6 @@ const routesAdmin = [
|
|||||||
title: 'routes_title.users_storage_usage',
|
title: 'routes_title.users_storage_usage',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'UserSubscription',
|
|
||||||
path: '/admin/user/:id/subscription',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/user-subscription" */ '../views/Admin/Users/UserTabs/UserSubscription'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'subscription',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'UserPassword',
|
name: 'UserPassword',
|
||||||
path: '/admin/user/:id/password',
|
path: '/admin/user/:id/password',
|
||||||
@@ -174,132 +93,6 @@ const routesAdmin = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'PlanFixed',
|
|
||||||
path: '/admin/plan/:id',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/plan" */ '../views/Admin/Plans/FixedPlan'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'PlanFixedSubscribers',
|
|
||||||
path: '/admin/plan/:id/fixed/subscribers',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-subscribers" */ '../views/Admin/Plans/Tabs/PlanSubscribers'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'subscribers',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PlanFixedSettings',
|
|
||||||
path: '/admin/plan/:id/fixed/settings',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-settings" */ '../views/Admin/Plans/Tabs/PlanFixedSettings'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan_settings',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PlanFixedDelete',
|
|
||||||
path: '/admin/plan/:id/fixed/delete',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/plan-delete" */ '../views/Admin/Plans/Tabs/PlanDelete'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan_delete',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PlanMetered',
|
|
||||||
path: '/admin/plan/:id',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/plan" */ '../views/Admin/Plans/MeteredPlan'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'PlanMeteredSubscribers',
|
|
||||||
path: '/admin/plan/:id/metered/subscribers',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-subscribers" */ '../views/Admin/Plans/Tabs/PlanSubscribers'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'subscribers',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PlanMeteredSettings',
|
|
||||||
path: '/admin/plan/:id/metered/settings',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/plan-settings" */ '../views/Admin/Plans/Tabs/PlanMeteredSettings'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan_settings',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PlanMeteredDelete',
|
|
||||||
path: '/admin/plan/:id/metered/delete',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/plan-delete" */ '../views/Admin/Plans/Tabs/PlanDelete'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'plan_delete',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PaymentSettings',
|
|
||||||
path: '/admin/payments',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/payments" */ '../views/Admin/PaymentSettings/PaymentSettings'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'Payment Settings',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'AppBillings',
|
|
||||||
path: '/admin/payments/billings',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/payments/billings" */ '../views/Admin/PaymentSettings/PaymentSettingsTab/Billings'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'billings',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'AppPayments',
|
|
||||||
path: '/admin/payments/payments',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/payments/settings" */ '../views/Admin/PaymentSettings/PaymentSettingsTab/Payments'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'payments',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'AppSettings',
|
name: 'AppSettings',
|
||||||
path: '/admin/settings',
|
path: '/admin/settings',
|
||||||
@@ -322,18 +115,6 @@ const routesAdmin = [
|
|||||||
title: 'appearance',
|
title: 'appearance',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'AppIndex',
|
|
||||||
path: '/admin/settings/index',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/app-index" */ '../views/Admin/Settings/AppSettingsTabs/Index'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'Index',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'AppEnvironment',
|
name: 'AppEnvironment',
|
||||||
path: '/admin/settings/environment',
|
path: '/admin/settings/environment',
|
||||||
@@ -358,30 +139,6 @@ const routesAdmin = [
|
|||||||
title: 'others',
|
title: 'others',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'AppSignInUp',
|
|
||||||
path: '/admin/settings/sign-in',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/app-sign-in-out" */ '../views/Admin/Settings/AppSettingsTabs/SignInUp'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'Sign In/Up',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'AppAdsense',
|
|
||||||
path: '/admin/settings/adsense',
|
|
||||||
component: () =>
|
|
||||||
import(
|
|
||||||
/* webpackChunkName: "chunks/app-adsense" */ '../views/Admin/Settings/AppSettingsTabs/Adsense'
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'Adsense',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'AppServer',
|
name: 'AppServer',
|
||||||
path: '/admin/settings/server',
|
path: '/admin/settings/server',
|
||||||
|
|||||||
Vendored
-17
@@ -1,13 +1,4 @@
|
|||||||
const routesAuth = [
|
const routesAuth = [
|
||||||
{
|
|
||||||
name: 'SuccessfullyVerified',
|
|
||||||
path: '/successfully-verified',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/successfully-email-verified" */ '../views/Auth/SuccessfullyEmailVerified'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'SuccessfullySend',
|
name: 'SuccessfullySend',
|
||||||
path: '/successfully-send',
|
path: '/successfully-send',
|
||||||
@@ -24,14 +15,6 @@ const routesAuth = [
|
|||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'SignUp',
|
|
||||||
path: '/sign-up',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/sign-up" */ '../views/Auth/SignUp'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'ForgottenPassword',
|
name: 'ForgottenPassword',
|
||||||
path: '/forgotten-password',
|
path: '/forgotten-password',
|
||||||
|
|||||||
Vendored
-17
@@ -38,23 +38,6 @@ const routesFile = [
|
|||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'TeamFolders',
|
|
||||||
path: '/platform/team-folders/:id?',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/team-folders" */ '../views/FileView/TeamFolders'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'SharedWithMe',
|
|
||||||
path: '/platform/shared-with-me/:id?',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/shared-with-me" */ '../views/FileView/SharedWithMe'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
-28
@@ -1,28 +0,0 @@
|
|||||||
const routesIndex = [
|
|
||||||
{
|
|
||||||
name: 'Homepage',
|
|
||||||
path: '/',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/homepage" */ '../views/Frontpage/Homepage'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'DynamicPage',
|
|
||||||
path: '/page/:slug',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/dynamic-page" */ '../views/Frontpage/DynamicPage'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ContactUs',
|
|
||||||
path: '/contact-us',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/contact-us" */ '../views/Frontpage/ContactUs'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export default routesIndex
|
|
||||||
Vendored
-12
@@ -1,12 +0,0 @@
|
|||||||
const routesTeam = [
|
|
||||||
{
|
|
||||||
name: 'Invitation',
|
|
||||||
path: '/team-folder-invitation/:id',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/invitation" */ '../views/Teams/Invitation'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export default routesTeam
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
const routesShared = [
|
|
||||||
{
|
|
||||||
name: 'Request',
|
|
||||||
path: '/request',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/request" */ '../views/UploadRequest'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'RequestUpload',
|
|
||||||
path: '/request/:token/upload/:id?',
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "chunks/request-upload" */ '../views/FileView/UploadRequestFiles'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export default routesShared
|
|
||||||
Vendored
-9
@@ -34,15 +34,6 @@ const routesUser = [
|
|||||||
title: 'storage',
|
title: 'storage',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'Billing',
|
|
||||||
path: '/user/settings/billing',
|
|
||||||
component: () => import(/* webpackChunkName: "chunks/billing" */ '../views/User/Billing'),
|
|
||||||
meta: {
|
|
||||||
requiresAuth: true,
|
|
||||||
title: 'billing',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
-8
@@ -1,30 +1,22 @@
|
|||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
import uploadRequest from './modules/uploadRequest'
|
|
||||||
import fileFunctions from './modules/fileFunctions'
|
import fileFunctions from './modules/fileFunctions'
|
||||||
import broadcasting from './modules/broadcasting'
|
|
||||||
import fileBrowser from './modules/fileBrowser'
|
import fileBrowser from './modules/fileBrowser'
|
||||||
import payments from './modules/payments'
|
|
||||||
import userAuth from './modules/userAuth'
|
import userAuth from './modules/userAuth'
|
||||||
import sharing from './modules/sharing'
|
import sharing from './modules/sharing'
|
||||||
import lists from './modules/lists'
|
import lists from './modules/lists'
|
||||||
import teams from './modules/teams'
|
|
||||||
import app from './modules/app'
|
import app from './modules/app'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
uploadRequest,
|
|
||||||
fileFunctions,
|
fileFunctions,
|
||||||
broadcasting,
|
|
||||||
fileBrowser,
|
fileBrowser,
|
||||||
payments,
|
|
||||||
userAuth,
|
userAuth,
|
||||||
sharing,
|
sharing,
|
||||||
lists,
|
lists,
|
||||||
teams,
|
|
||||||
app,
|
app,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Vendored
-49
@@ -5,8 +5,6 @@ import router from '../../router'
|
|||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
isVisibleNavigationBars: localStorage.getItem('is_navigation_bars') !== 'false',
|
isVisibleNavigationBars: localStorage.getItem('is_navigation_bars') !== 'false',
|
||||||
isVisibleNotificationCenter: false,
|
|
||||||
notificationCount: 0,
|
|
||||||
isDarkMode: false,
|
isDarkMode: false,
|
||||||
isVisibleSidebar: localStorage.getItem('file_info_visibility') === 'true' || false,
|
isVisibleSidebar: localStorage.getItem('file_info_visibility') === 'true' || false,
|
||||||
itemViewType: localStorage.getItem('preview_type') || 'list',
|
itemViewType: localStorage.getItem('preview_type') || 'list',
|
||||||
@@ -126,60 +124,13 @@ const mutations = {
|
|||||||
REPLACE_CONFIG_VALUE(state, { key, value }) {
|
REPLACE_CONFIG_VALUE(state, { key, value }) {
|
||||||
state.config[key] = value
|
state.config[key] = value
|
||||||
},
|
},
|
||||||
SET_SOCIAL_LOGIN_CONFIGURED(state, service) {
|
|
||||||
if (service === 'facebook') {
|
|
||||||
state.config.allowedFacebookLogin = true
|
|
||||||
state.config.isFacebookLoginConfigured = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === 'google') {
|
|
||||||
state.config.allowedGoogleLogin = true
|
|
||||||
state.config.isGoogleLoginConfigured = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === 'github') {
|
|
||||||
state.config.allowedGithubLogin = true
|
|
||||||
state.config.isGithubLoginConfigured = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === 'recaptcha') {
|
|
||||||
state.config.allowedRecaptcha = true
|
|
||||||
state.config.isRecaptchaConfigured = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SET_STRIPE_CREDENTIALS(state, data) {
|
|
||||||
state.config.stripe_public_key = data.key
|
|
||||||
state.config.isStripe = true
|
|
||||||
},
|
|
||||||
SET_PAYSTACK_CREDENTIALS(state, data) {
|
|
||||||
state.config.paystack_public_key = data.key
|
|
||||||
state.config.isPaystack = true
|
|
||||||
},
|
|
||||||
SET_PAYPAL_CREDENTIALS(state, data) {
|
|
||||||
state.config.paypal_client_id = data.key
|
|
||||||
state.config.isPayPal = true
|
|
||||||
|
|
||||||
if (data.live)
|
|
||||||
state.config.isPayPalLive = data.live
|
|
||||||
},
|
|
||||||
UPDATE_DARK_MODE_STATUS(state, val) {
|
UPDATE_DARK_MODE_STATUS(state, val) {
|
||||||
state.isDarkMode = val
|
state.isDarkMode = val
|
||||||
},
|
},
|
||||||
UPDATE_NOTIFICATION_COUNT(state, val) {
|
|
||||||
state.notificationCount = val
|
|
||||||
},
|
|
||||||
TOGGLE_NOTIFICATION_CENTER(state) {
|
|
||||||
state.isVisibleNotificationCenter = !state.isVisibleNotificationCenter
|
|
||||||
},
|
|
||||||
CLOSE_NOTIFICATION_CENTER(state) {
|
|
||||||
state.isVisibleNotificationCenter = false
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
isVisibleNotificationCenter: (state) => state.isVisibleNotificationCenter,
|
|
||||||
isVisibleNavigationBars: (state) => state.isVisibleNavigationBars,
|
isVisibleNavigationBars: (state) => state.isVisibleNavigationBars,
|
||||||
notificationCount: (state) => state.notificationCount,
|
|
||||||
isVisibleSidebar: (state) => state.isVisibleSidebar,
|
isVisibleSidebar: (state) => state.isVisibleSidebar,
|
||||||
itemViewType: (state) => state.itemViewType,
|
itemViewType: (state) => state.itemViewType,
|
||||||
api: (state) => state.config.api,
|
api: (state) => state.config.api,
|
||||||
|
|||||||
-84
@@ -1,84 +0,0 @@
|
|||||||
import { events } from '../../bus'
|
|
||||||
import i18n from "../../i18n"
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
remoteUploadQueue: undefined,
|
|
||||||
isBroadcasting: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
runConnection: ({ commit, getters, dispatch }) => {
|
|
||||||
commit('SET_RUNNING_COMMUNICATION')
|
|
||||||
|
|
||||||
Echo.private(`App.Users.Models.User.${getters.user.data.id}`)
|
|
||||||
.listen('.RemoteFile.Created', (event) => {
|
|
||||||
commit('UPDATE_REMOTE_UPLOAD_QUEUE', event.payload)
|
|
||||||
|
|
||||||
// If user is located in same directory as remote upload was called, then show the files
|
|
||||||
if (
|
|
||||||
event.payload.file &&
|
|
||||||
(!getters.currentFolder && !event.payload.file.data.attributes.parent_id) ||
|
|
||||||
(getters.currentFolder && event.payload.file.data.attributes.parent_id === getters.currentFolder.data.id)
|
|
||||||
) {
|
|
||||||
// Add received item into view
|
|
||||||
commit('ADD_NEW_ITEMS', event.payload.file)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.payload.progress.total === event.payload.progress.processed) {
|
|
||||||
events.$emit('toaster', {
|
|
||||||
type: 'success',
|
|
||||||
message: i18n.t('remote_download_finished'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.notification((notification) => {
|
|
||||||
// Play audio
|
|
||||||
new Audio('/audio/blop.wav').play()
|
|
||||||
|
|
||||||
// Call toaster notification
|
|
||||||
events.$emit('notification', {
|
|
||||||
data: {
|
|
||||||
type: notification.category,
|
|
||||||
id: notification.id,
|
|
||||||
attributes: {
|
|
||||||
action: notification.action,
|
|
||||||
description: notification.description,
|
|
||||||
title: notification.title,
|
|
||||||
category: notification.category,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reload user data to update notifications
|
|
||||||
dispatch('getAppData')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
SET_RUNNING_COMMUNICATION(state) {
|
|
||||||
state.isBroadcasting = true
|
|
||||||
},
|
|
||||||
UPDATE_REMOTE_UPLOAD_QUEUE(state, payload) {
|
|
||||||
if (payload.progress.total !== payload.progress.processed) {
|
|
||||||
state.remoteUploadQueue = {
|
|
||||||
total: payload.progress.total,
|
|
||||||
processed: payload.progress.processed,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.remoteUploadQueue = undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const getters = {
|
|
||||||
remoteUploadQueue: (state) => state.remoteUploadQueue,
|
|
||||||
isBroadcasting: (state) => state.isBroadcasting,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
state: defaultState,
|
|
||||||
getters,
|
|
||||||
actions,
|
|
||||||
mutations,
|
|
||||||
}
|
|
||||||
-1
@@ -104,7 +104,6 @@ const actions = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/navigation`,
|
|
||||||
Public: `/api/browse/navigation/${router.currentRoute.params.token}`,
|
Public: `/api/browse/navigation/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || '/api/browse/navigation'
|
}[router.currentRoute.name] || '/api/browse/navigation'
|
||||||
|
|
||||||
|
|||||||
-5
@@ -59,7 +59,6 @@ const actions = {
|
|||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/move`,
|
|
||||||
Public: `/api/editor/move/${router.currentRoute.params.token}`,
|
Public: `/api/editor/move/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || '/api/move'
|
}[router.currentRoute.name] || '/api/move'
|
||||||
|
|
||||||
@@ -87,7 +86,6 @@ const actions = {
|
|||||||
createFolder: ({ commit, getters, dispatch }, folder) => {
|
createFolder: ({ commit, getters, dispatch }, folder) => {
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/create-folder`,
|
|
||||||
Public: `/api/editor/create-folder/${router.currentRoute.params.token}`,
|
Public: `/api/editor/create-folder/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || '/api/create-folder'
|
}[router.currentRoute.name] || '/api/create-folder'
|
||||||
|
|
||||||
@@ -126,7 +124,6 @@ const actions = {
|
|||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/rename/${data.id}`,
|
|
||||||
Public: `/api/editor/rename/${data.id}/${router.currentRoute.params.token}`,
|
Public: `/api/editor/rename/${data.id}/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || `/api/rename/${data.id}`
|
}[router.currentRoute.name] || `/api/rename/${data.id}`
|
||||||
|
|
||||||
@@ -149,7 +146,6 @@ const actions = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/upload`,
|
|
||||||
Public: `/api/editor/upload/${router.currentRoute.params.token}`,
|
Public: `/api/editor/upload/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || '/api/upload'
|
}[router.currentRoute.name] || '/api/upload'
|
||||||
|
|
||||||
@@ -317,7 +313,6 @@ const actions = {
|
|||||||
|
|
||||||
// Get route
|
// Get route
|
||||||
let route = {
|
let route = {
|
||||||
RequestUpload: `/api/upload-request/${router.currentRoute.params.token}/remove`,
|
|
||||||
Public: `/api/editor/remove/${router.currentRoute.params.token}`,
|
Public: `/api/editor/remove/${router.currentRoute.params.token}`,
|
||||||
}[router.currentRoute.name] || '/api/remove'
|
}[router.currentRoute.name] || '/api/remove'
|
||||||
|
|
||||||
|
|||||||
Vendored
-617
@@ -89,48 +89,6 @@ const defaultState = {
|
|||||||
value: 'sa-east-1',
|
value: 'sa-east-1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
transactionColumns: [
|
|
||||||
{
|
|
||||||
label: 'note',
|
|
||||||
field: 'note',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'user',
|
|
||||||
field: 'user_id',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'status',
|
|
||||||
field: 'status',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'type',
|
|
||||||
field: 'type',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'total',
|
|
||||||
field: 'amount',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'payed_at',
|
|
||||||
field: 'created_at',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'service',
|
|
||||||
field: 'driver',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'actions',
|
|
||||||
field: 'actions',
|
|
||||||
sortable: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
roles: [
|
roles: [
|
||||||
{
|
{
|
||||||
label: 'roles.admin',
|
label: 'roles.admin',
|
||||||
@@ -141,24 +99,6 @@ const defaultState = {
|
|||||||
value: 'user',
|
value: 'user',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
subscriptionTypes: [
|
|
||||||
{
|
|
||||||
label: 'Metered',
|
|
||||||
value: 'metered',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Fixed',
|
|
||||||
value: 'fixed',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'None',
|
|
||||||
value: 'none',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
teamPermissions: {
|
|
||||||
'can-edit': 'can_edit',
|
|
||||||
'can-view': 'can_view',
|
|
||||||
},
|
|
||||||
countries: [
|
countries: [
|
||||||
{ label: 'Czech Republic', value: 'CZ' },
|
{ label: 'Czech Republic', value: 'CZ' },
|
||||||
{ label: 'Slovakia', value: 'SK' },
|
{ label: 'Slovakia', value: 'SK' },
|
||||||
@@ -434,558 +374,6 @@ const defaultState = {
|
|||||||
value: 168,
|
value: 168,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
intervalList: [
|
|
||||||
{
|
|
||||||
label: 'monthly',
|
|
||||||
value: 'month',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'yearly',
|
|
||||||
value: 'year',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
currencyList: [
|
|
||||||
{
|
|
||||||
label: 'USD - United States Dollar',
|
|
||||||
value: 'USD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'EUR - Euro',
|
|
||||||
value: 'EUR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GBP - British Pound',
|
|
||||||
value: 'GBP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AFN - Afghan Afghani',
|
|
||||||
value: 'AFN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ALL - Albanian Lek',
|
|
||||||
value: 'ALL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'DZD - Algerian Dinar',
|
|
||||||
value: 'DZD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AOA - Angolan Kwanza',
|
|
||||||
value: 'AOA',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ARS - Argentine Peso',
|
|
||||||
value: 'ARS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AMD - Armenian Dram',
|
|
||||||
value: 'AMD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AWG - Aruban Florin',
|
|
||||||
value: 'AWG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AUD - Australian Dollar',
|
|
||||||
value: 'AUD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AZN - Azerbaijani Manat',
|
|
||||||
value: 'AZN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BDT - Bangladeshi Taka',
|
|
||||||
value: 'BDT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BBD - Barbadian Dollar',
|
|
||||||
value: 'BBD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BZD - Belize Dollar',
|
|
||||||
value: 'BZD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BMD - Bermudian Dollar',
|
|
||||||
value: 'BMD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BOB - Bolivian Boliviano',
|
|
||||||
value: 'BOB',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BAM - Bosnia & Herzegovina Convertible Mark',
|
|
||||||
value: 'BAM',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BWP - Botswana Pula',
|
|
||||||
value: 'BWP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BRL - Brazilian Real',
|
|
||||||
value: 'BRL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BND - Brunei Dollar',
|
|
||||||
value: 'BND',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BGN - Bulgarian Lev',
|
|
||||||
value: 'BGN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'BIF - Burundian Franc',
|
|
||||||
value: 'BIF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KHR - Cambodian Riel',
|
|
||||||
value: 'KHR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CAD - Canadian Dollar',
|
|
||||||
value: 'CAD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CVE - Cape Verdean Escudo',
|
|
||||||
value: 'CVE',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KYD - Cayman Islands Dollar',
|
|
||||||
value: 'KYD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'XAF - Central African Cfa Franc',
|
|
||||||
value: 'XAF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'XPF - Cfp Franc',
|
|
||||||
value: 'XPF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CLP - Chilean Peso',
|
|
||||||
value: 'CLP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CNY - Chinese Renminbi Yuan',
|
|
||||||
value: 'CNY',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'COP - Colombian Peso',
|
|
||||||
value: 'COP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KMF - Comorian Franc',
|
|
||||||
value: 'KMF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CDF - Congolese Franc',
|
|
||||||
value: 'CDF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CRC - Costa Rican Colón',
|
|
||||||
value: 'CRC',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'HRK - Croatian Kuna',
|
|
||||||
value: 'HRK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CZK - Czech Koruna',
|
|
||||||
value: 'CZK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'DKK - Danish Krone',
|
|
||||||
value: 'DKK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'DJF - Djiboutian Franc',
|
|
||||||
value: 'DJF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'DOP - Dominican Peso',
|
|
||||||
value: 'DOP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'XCD - East Caribbean Dollar',
|
|
||||||
value: 'XCD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'EGP - Egyptian Pound',
|
|
||||||
value: 'EGP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ETB - Ethiopian Birr',
|
|
||||||
value: 'ETB',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'FKP - Falkland Islands Pound',
|
|
||||||
value: 'FKP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'FJD - Fijian Dollar',
|
|
||||||
value: 'FJD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GMD - Gambian Dalasi',
|
|
||||||
value: 'GMD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GEL - Georgian Lari',
|
|
||||||
value: 'GEL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GIP - Gibraltar Pound',
|
|
||||||
value: 'GIP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GTQ - Guatemalan Quetzal',
|
|
||||||
value: 'GTQ',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GNF - Guinean Franc',
|
|
||||||
value: 'GNF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'GYD - Guyanese Dollar',
|
|
||||||
value: 'GYD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'HTG - Haitian Gourde',
|
|
||||||
value: 'HTG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'HNL - Honduran Lempira',
|
|
||||||
value: 'HNL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'HKD - Hong Kong Dollar',
|
|
||||||
value: 'HKD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'HUF - Hungarian Forint',
|
|
||||||
value: 'HUF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ISK - Icelandic Króna',
|
|
||||||
value: 'ISK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'INR - Indian Rupee',
|
|
||||||
value: 'INR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'IDR - Indonesian Rupiah',
|
|
||||||
value: 'IDR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ILS - Israeli New Sheqel',
|
|
||||||
value: 'ILS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'JMD - Jamaican Dollar',
|
|
||||||
value: 'JMD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'JPY - Japanese Yen',
|
|
||||||
value: 'JPY',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KZT - Kazakhstani Tenge',
|
|
||||||
value: 'KZT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KES - Kenyan Shilling',
|
|
||||||
value: 'KES',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KGS - Kyrgyzstani Som',
|
|
||||||
value: 'KGS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'LAK - Lao Kip',
|
|
||||||
value: 'LAK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'LBP - Lebanese Pound',
|
|
||||||
value: 'LBP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'LSL - Lesotho Loti',
|
|
||||||
value: 'LSL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'LRD - Liberian Dollar',
|
|
||||||
value: 'LRD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MOP - Macanese Pataca',
|
|
||||||
value: 'MOP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MKD - Macedonian Denar',
|
|
||||||
value: 'MKD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MGA - Malagasy Ariary',
|
|
||||||
value: 'MGA',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MWK - Malawian Kwacha',
|
|
||||||
value: 'MWK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MYR - Malaysian Ringgit',
|
|
||||||
value: 'MYR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MVR - Maldivian Rufiyaa',
|
|
||||||
value: 'MVR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MRO - Mauritanian Ouguiya',
|
|
||||||
value: 'MRO',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MUR - Mauritian Rupee',
|
|
||||||
value: 'MUR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MXN - Mexican Peso',
|
|
||||||
value: 'MXN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MDL - Moldovan Leu',
|
|
||||||
value: 'MDL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MNT - Mongolian Tögrög',
|
|
||||||
value: 'MNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MAD - Moroccan Dirham',
|
|
||||||
value: 'MAD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MZN - Mozambican Metical',
|
|
||||||
value: 'MZN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'MMK - Myanmar Kyat',
|
|
||||||
value: 'MMK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NAD - Namibian Dollar',
|
|
||||||
value: 'NAD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NPR - Nepalese Rupee',
|
|
||||||
value: 'NPR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ANG - Netherlands Antillean Gulden',
|
|
||||||
value: 'ANG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TWD - New Taiwan Dollar',
|
|
||||||
value: 'TWD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NZD - New Zealand Dollar',
|
|
||||||
value: 'NZD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NIO - Nicaraguan Córdoba',
|
|
||||||
value: 'NIO',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NGN - Nigerian Naira',
|
|
||||||
value: 'NGN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'NOK - Norwegian Krone',
|
|
||||||
value: 'NOK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PKR - Pakistani Rupee',
|
|
||||||
value: 'PKR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PAB - Panamanian Balboa',
|
|
||||||
value: 'PAB',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PGK - Papua New Guinean Kina',
|
|
||||||
value: 'PGK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PYG - Paraguayan Guaraní',
|
|
||||||
value: 'PYG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PEN - Peruvian Nuevo Sol',
|
|
||||||
value: 'PEN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PHP - Philippine Peso',
|
|
||||||
value: 'PHP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'PLN - Polish Złoty',
|
|
||||||
value: 'PLN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'QAR - Qatari Riyal',
|
|
||||||
value: 'QAR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'RON - Romanian Leu',
|
|
||||||
value: 'RON',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'RUB - Russian Ruble',
|
|
||||||
value: 'RUB',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'RWF - Rwandan Franc',
|
|
||||||
value: 'RWF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'STD - São Tomé and Príncipe Dobra',
|
|
||||||
value: 'STD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SHP - Saint Helenian Pound',
|
|
||||||
value: 'SHP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SVC - Salvadoran Colón',
|
|
||||||
value: 'SVC',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'WST - Samoan Tala',
|
|
||||||
value: 'WST',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SAR - Saudi Riyal',
|
|
||||||
value: 'SAR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'RSD - Serbian Dinar',
|
|
||||||
value: 'RSD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SCR - Seychellois Rupee',
|
|
||||||
value: 'SCR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SLL - Sierra Leonean Leone',
|
|
||||||
value: 'SLL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SGD - Singapore Dollar',
|
|
||||||
value: 'SGD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SBD - Solomon Islands Dollar',
|
|
||||||
value: 'SBD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SOS - Somali Shilling',
|
|
||||||
value: 'SOS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ZAR - South African Rand',
|
|
||||||
value: 'ZAR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'KRW - South Korean Won',
|
|
||||||
value: 'KRW',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'LKR - Sri Lankan Rupee',
|
|
||||||
value: 'LKR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SRD - Surinamese Dollar',
|
|
||||||
value: 'SRD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SZL - Swazi Lilangeni',
|
|
||||||
value: 'SZL',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'SEK - Swedish Krona',
|
|
||||||
value: 'SEK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'CHF - Swiss Franc',
|
|
||||||
value: 'CHF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TJS - Tajikistani Somoni',
|
|
||||||
value: 'TJS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TZS - Tanzanian Shilling',
|
|
||||||
value: 'TZS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'THB - Thai Baht',
|
|
||||||
value: 'THB',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TOP - Tongan Paʻanga',
|
|
||||||
value: 'TOP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TTD - Trinidad and Tobago Dollar',
|
|
||||||
value: 'TTD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'TRY - Turkish Lira',
|
|
||||||
value: 'TRY',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'UGX - Ugandan Shilling',
|
|
||||||
value: 'UGX',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'UAH - Ukrainian Hryvnia',
|
|
||||||
value: 'UAH',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'AED - United Arab Emirates Dirham',
|
|
||||||
value: 'AED',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'UYU - Uruguayan Peso',
|
|
||||||
value: 'UYU',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'UZS - Uzbekistani Som',
|
|
||||||
value: 'UZS',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'VUV - Vanuatu Vatu',
|
|
||||||
value: 'VUV',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'VND - Vietnamese Đồng',
|
|
||||||
value: 'VND',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'XOF - West African Cfa Franc',
|
|
||||||
value: 'XOF',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'YER - Yemeni Rial',
|
|
||||||
value: 'YER',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ZMW - Zambian Kwacha',
|
|
||||||
value: 'ZMW',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
timezones: [
|
timezones: [
|
||||||
{
|
{
|
||||||
value: '-12.0',
|
value: '-12.0',
|
||||||
@@ -1115,12 +503,7 @@ const defaultState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
transactionColumns: (state) => state.transactionColumns,
|
|
||||||
subscriptionTypes: (state) => state.subscriptionTypes,
|
|
||||||
teamPermissions: (state) => state.teamPermissions,
|
|
||||||
expirationList: (state) => state.expirationList,
|
expirationList: (state) => state.expirationList,
|
||||||
currencyList: (state) => state.currencyList,
|
|
||||||
intervalList: (state) => state.intervalList,
|
|
||||||
timezones: (state) => state.timezones,
|
timezones: (state) => state.timezones,
|
||||||
countries: (state) => state.countries,
|
countries: (state) => state.countries,
|
||||||
s3Regions: (state) => state.s3Regions,
|
s3Regions: (state) => state.s3Regions,
|
||||||
|
|||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
import { events } from '../../bus'
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
singleChargeAmount: undefined,
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
callSingleChargeProcess: ({ commit }, amount) => {
|
|
||||||
// Open popup with payment methods
|
|
||||||
events.$emit('popup:open', { name: 'select-payment-method' })
|
|
||||||
|
|
||||||
// Store charge amount
|
|
||||||
commit('SET_SINGLE_CHARGE_AMOUNT', amount)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
SET_SINGLE_CHARGE_AMOUNT(state, amount) {
|
|
||||||
state.singleChargeAmount = amount
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const getters = {
|
|
||||||
singleChargeAmount: (state) => state.singleChargeAmount,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
state: defaultState,
|
|
||||||
getters,
|
|
||||||
actions,
|
|
||||||
mutations,
|
|
||||||
}
|
|
||||||
Vendored
-129
@@ -1,129 +0,0 @@
|
|||||||
import router from '../../router'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import i18n from '../../i18n'
|
|
||||||
import axios from 'axios'
|
|
||||||
import Vue from 'vue'
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
currentTeamFolder: undefined,
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
getTeamFolder: ({ commit, getters }, id) => {
|
|
||||||
commit('LOADING_STATE', { loading: true, data: [] })
|
|
||||||
|
|
||||||
if (typeof id === 'undefined') {
|
|
||||||
commit('SET_CURRENT_TEAM_FOLDER', null)
|
|
||||||
}
|
|
||||||
|
|
||||||
axios
|
|
||||||
.get(`${getters.api}/teams/folders/${id}${getters.sorting.URI}`)
|
|
||||||
.then((response) => {
|
|
||||||
let folders = response.data.folders.data
|
|
||||||
let files = response.data.files.data
|
|
||||||
|
|
||||||
commit('LOADING_STATE', {
|
|
||||||
loading: false,
|
|
||||||
data: folders.concat(files),
|
|
||||||
})
|
|
||||||
commit('SET_CURRENT_FOLDER', response.data.root)
|
|
||||||
|
|
||||||
if (
|
|
||||||
!getters.currentTeamFolder ||
|
|
||||||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
|
|
||||||
) {
|
|
||||||
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
events.$emit('scrollTop')
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
// Redirect if unauthenticated
|
|
||||||
if ([401, 403].includes(error.response.status)) {
|
|
||||||
commit('SET_AUTHORIZED', false)
|
|
||||||
router.push({ name: 'SignIn' })
|
|
||||||
} else {
|
|
||||||
// Show error message
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: i18n.t('popup_error.title'),
|
|
||||||
message: i18n.t('popup_error.message'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getSharedWithMeFolder: ({ commit, getters }, id) => {
|
|
||||||
commit('LOADING_STATE', { loading: true, data: [] })
|
|
||||||
|
|
||||||
if (typeof id === 'undefined') {
|
|
||||||
commit('SET_CURRENT_TEAM_FOLDER', null)
|
|
||||||
}
|
|
||||||
|
|
||||||
axios
|
|
||||||
.get(`${getters.api}/teams/shared-with-me/${id}${getters.sorting.URI}`)
|
|
||||||
.then((response) => {
|
|
||||||
let folders = response.data.folders.data
|
|
||||||
let files = response.data.files.data
|
|
||||||
|
|
||||||
commit('LOADING_STATE', {
|
|
||||||
loading: false,
|
|
||||||
data: folders.concat(files),
|
|
||||||
})
|
|
||||||
commit('SET_CURRENT_FOLDER', response.data.root)
|
|
||||||
|
|
||||||
if (
|
|
||||||
!getters.currentTeamFolder ||
|
|
||||||
getters.currentTeamFolder.data.id !== response.data.teamFolder.data.id
|
|
||||||
) {
|
|
||||||
commit('SET_CURRENT_TEAM_FOLDER', response.data.teamFolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
events.$emit('scrollTop')
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
// Redirect if unauthenticated
|
|
||||||
if ([401, 403].includes(error.response.status)) {
|
|
||||||
commit('SET_AUTHORIZED', false)
|
|
||||||
router.push({ name: 'SignIn' })
|
|
||||||
} else {
|
|
||||||
// Show error message
|
|
||||||
events.$emit('alert:open', {
|
|
||||||
title: i18n.t('popup_error.title'),
|
|
||||||
message: i18n.t('popup_error.message'),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getTeamFolderTree: ({ commit, getters }) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(`/api/teams/folders/${getters.currentTeamFolder.data.id}/tree${getters.sorting.URI}`)
|
|
||||||
.then((response) => {
|
|
||||||
resolve(response)
|
|
||||||
|
|
||||||
commit('UPDATE_FOLDER_TREE', response.data)
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(error)
|
|
||||||
|
|
||||||
Vue.prototype.$isSomethingWrong()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
SET_CURRENT_TEAM_FOLDER(state, payload) {
|
|
||||||
state.currentTeamFolder = payload
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const getters = {
|
|
||||||
currentTeamFolder: (state) => state.currentTeamFolder,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
state: defaultState,
|
|
||||||
getters,
|
|
||||||
actions,
|
|
||||||
mutations,
|
|
||||||
}
|
|
||||||
-83
@@ -1,83 +0,0 @@
|
|||||||
import router from '../../router'
|
|
||||||
import { events } from '../../bus'
|
|
||||||
import axios from 'axios'
|
|
||||||
import Vue from 'vue'
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
uploadRequest: undefined,
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
getUploadRequestFolder: ({ commit, getters }, id) => {
|
|
||||||
commit('LOADING_STATE', { loading: true, data: [] })
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
axios
|
|
||||||
.get(`/api/upload-request/${router.currentRoute.params.token}/browse/${id}${getters.sorting.URI}`)
|
|
||||||
.then((response) => {
|
|
||||||
let folders = response.data.folders.data
|
|
||||||
let files = response.data.files.data
|
|
||||||
|
|
||||||
commit('LOADING_STATE', {
|
|
||||||
loading: false,
|
|
||||||
data: folders.concat(files),
|
|
||||||
})
|
|
||||||
commit('SET_CURRENT_FOLDER', response.data.root)
|
|
||||||
|
|
||||||
events.$emit('scrollTop')
|
|
||||||
|
|
||||||
resolve(response)
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
Vue.prototype.$isSomethingWrong()
|
|
||||||
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getUploadRequestDetail: ({ commit }) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
axios.get(`/api/upload-request/${router.currentRoute.params.token}`)
|
|
||||||
.then((response) => {
|
|
||||||
resolve(response)
|
|
||||||
|
|
||||||
// Stop loading spinner
|
|
||||||
if (['active', 'filled', 'expired'].includes(response.data.data.attributes.status) )
|
|
||||||
commit('LOADING_STATE', { loading: false, data: [] })
|
|
||||||
|
|
||||||
commit('SET_UPLOAD_REQUEST', response.data)
|
|
||||||
|
|
||||||
// Set current folder if exist
|
|
||||||
if (! router.currentRoute.params.id) {
|
|
||||||
commit('SET_CURRENT_FOLDER', response.data.data.relationships.folder)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
closeUploadRequest: ({ commit }) => {
|
|
||||||
axios
|
|
||||||
.delete(`/api/upload-request/${router.currentRoute.params.token}`)
|
|
||||||
.then((response) => {
|
|
||||||
commit('LOADING_STATE', { loading: false, data: [] })
|
|
||||||
commit('SET_UPLOAD_REQUEST', response.data)
|
|
||||||
})
|
|
||||||
.catch(() => this.$isSomethingWrong())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
SET_UPLOAD_REQUEST(state, payload) {
|
|
||||||
state.uploadRequest = payload
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const getters = {
|
|
||||||
uploadRequest: (state) => state.uploadRequest,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
state: defaultState,
|
|
||||||
getters,
|
|
||||||
actions,
|
|
||||||
mutations,
|
|
||||||
}
|
|
||||||
-53
@@ -16,11 +16,6 @@ const actions = {
|
|||||||
resolve(response)
|
resolve(response)
|
||||||
|
|
||||||
commit('RETRIEVE_USER', response.data)
|
commit('RETRIEVE_USER', response.data)
|
||||||
commit('UPDATE_NOTIFICATION_COUNT', response.data.data.relationships.unreadNotifications.data.length)
|
|
||||||
|
|
||||||
if (! getters.isBroadcasting && getters.config.broadcasting === 'pusher') {
|
|
||||||
dispatch('runConnection')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
@@ -53,16 +48,6 @@ const actions = {
|
|||||||
router.push({name: 'Homepage'})
|
router.push({name: 'Homepage'})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
socialiteRedirect: ({ commit }, provider) => {
|
|
||||||
axios
|
|
||||||
.get(`/api/socialite/${provider}/redirect`)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.data.url) {
|
|
||||||
window.location.href = response.data.url
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => this.$isSomethingWrong())
|
|
||||||
},
|
|
||||||
addToFavourites: (context, folder) => {
|
addToFavourites: (context, folder) => {
|
||||||
let addFavourites = []
|
let addFavourites = []
|
||||||
let items = [folder]
|
let items = [folder]
|
||||||
@@ -116,19 +101,6 @@ const actions = {
|
|||||||
})
|
})
|
||||||
.catch(() => Vue.prototype.$isSomethingWrong())
|
.catch(() => Vue.prototype.$isSomethingWrong())
|
||||||
},
|
},
|
||||||
readAllNotifications: ({ commit }) => {
|
|
||||||
axios.post('/api/user/notifications/read')
|
|
||||||
.then(() => {
|
|
||||||
commit('UPDATE_NOTIFICATION_COUNT', 0)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteAllNotifications: ({ commit }) => {
|
|
||||||
axios.delete('/api/user/notifications')
|
|
||||||
.then(() => {
|
|
||||||
commit('FLUSH_NOTIFICATIONS')
|
|
||||||
})
|
|
||||||
.catch(() => Vue.prototype.$isSomethingWrong())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
@@ -178,34 +150,9 @@ const mutations = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
FLUSH_NOTIFICATIONS(state) {
|
|
||||||
state.user.data.relationships.readNotifications.data = []
|
|
||||||
state.user.data.relationships.unreadNotifications.data = []
|
|
||||||
},
|
|
||||||
CLEAR_NOTIFICATION_ACTION_DATA(state, notificationId) {
|
|
||||||
if (state.user.data.relationships.readNotifications.data.length) {
|
|
||||||
state.user.data.relationships.readNotifications.data.map(notification => {
|
|
||||||
if (notification.data.id === notificationId) {
|
|
||||||
notification.data.attributes.action = undefined
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.user.data.relationships.unreadNotifications.data.length) {
|
|
||||||
state.user.data.relationships.unreadNotifications.data.map(notification => {
|
|
||||||
if (notification.data.id === notificationId) {
|
|
||||||
notification.data.attributes.action = undefined
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
isLimitedUser: (state) =>
|
|
||||||
state.user &&
|
|
||||||
state.user.data.relationships.failedPayments &&
|
|
||||||
state.user.data.relationships.failedPayments.data.length === 3,
|
|
||||||
permission: (state) => state.permission,
|
permission: (state) => state.permission,
|
||||||
user: (state) => state.user,
|
user: (state) => state.user,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,6 @@
|
|||||||
<FilePreview />
|
<FilePreview />
|
||||||
<Spotlight />
|
<Spotlight />
|
||||||
|
|
||||||
<!--Spotlight Addons-->
|
|
||||||
<CreateUploadRequestPopup />
|
|
||||||
<CreateTeamFolderPopup />
|
|
||||||
<NotificationsPopup />
|
|
||||||
<RemoteUploadPopup />
|
|
||||||
|
|
||||||
<!--Mobile Navigation-->
|
<!--Mobile Navigation-->
|
||||||
<MobileNavigation />
|
<MobileNavigation />
|
||||||
|
|
||||||
@@ -18,7 +12,6 @@
|
|||||||
|
|
||||||
<!-- Create language popup -->
|
<!-- Create language popup -->
|
||||||
<CreateLanguage />
|
<CreateLanguage />
|
||||||
|
|
||||||
<MobileNavigationToolbar />
|
<MobileNavigationToolbar />
|
||||||
|
|
||||||
<ContentSidebar>
|
<ContentSidebar>
|
||||||
@@ -84,61 +77,13 @@ import {
|
|||||||
UsersIcon,
|
UsersIcon,
|
||||||
} from 'vue-feather-icons'
|
} from 'vue-feather-icons'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import CreateUploadRequestPopup from "../components/UploadRequest/CreateUploadRequestPopup";
|
|
||||||
import CreateTeamFolderPopup from "../components/Teams/CreateTeamFolderPopup";
|
|
||||||
import NotificationsPopup from "../components/Notifications/NotificationsPopup";
|
|
||||||
import RemoteUploadPopup from "../components/RemoteUpload/RemoteUploadPopup";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Admin',
|
name: 'Admin',
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['isVisibleNavigationBars', 'config']),
|
...mapGetters(['isVisibleNavigationBars', 'config']),
|
||||||
nav() {
|
nav() {
|
||||||
let subscriptionLinks = {
|
return [
|
||||||
metered: [
|
|
||||||
{
|
|
||||||
title: this.$t('payments'),
|
|
||||||
route: 'PaymentSettings',
|
|
||||||
icon: 'card',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('plans'),
|
|
||||||
route: 'Plans',
|
|
||||||
icon: 'database',
|
|
||||||
linkActivation: ['plans', 'plan'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('transactions'),
|
|
||||||
route: 'Invoices',
|
|
||||||
icon: 'file-text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
fixed: [
|
|
||||||
{
|
|
||||||
title: this.$t('payments'),
|
|
||||||
route: 'PaymentSettings',
|
|
||||||
icon: 'card',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('subscriptions'),
|
|
||||||
route: 'Subscriptions',
|
|
||||||
icon: 'dollar',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('plans'),
|
|
||||||
route: 'Plans',
|
|
||||||
icon: 'database',
|
|
||||||
linkActivation: ['plans', 'plan'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('transactions'),
|
|
||||||
route: 'Invoices',
|
|
||||||
icon: 'file-text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}[this.config.subscriptionType]
|
|
||||||
|
|
||||||
let sections = [
|
|
||||||
{
|
{
|
||||||
groupCollapsable: false,
|
groupCollapsable: false,
|
||||||
groupTitle: this.$t('admin'),
|
groupTitle: this.$t('admin'),
|
||||||
@@ -159,17 +104,6 @@ export default {
|
|||||||
route: 'AppSettings',
|
route: 'AppSettings',
|
||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
groupCollapsable: false,
|
|
||||||
groupTitle: this.$t('content'),
|
|
||||||
groupLinks: [
|
|
||||||
{
|
|
||||||
title: this.$t('pages'),
|
|
||||||
route: 'Pages',
|
|
||||||
icon: 'monitor',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: this.$t('languages'),
|
title: this.$t('languages'),
|
||||||
route: 'Language',
|
route: 'Language',
|
||||||
@@ -178,24 +112,9 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// 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
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
RemoteUploadPopup,
|
|
||||||
NotificationsPopup,
|
|
||||||
CreateTeamFolderPopup,
|
|
||||||
CreateUploadRequestPopup,
|
|
||||||
MobileNavigationToolbar,
|
MobileNavigationToolbar,
|
||||||
FilePreview,
|
FilePreview,
|
||||||
Spotlight,
|
Spotlight,
|
||||||
|
|||||||
@@ -6,11 +6,6 @@
|
|||||||
<AppSpecification v-if="config.isAdminVueFileManagerBar" :data="data" class="hidden lg:flex" />
|
<AppSpecification v-if="config.isAdminVueFileManagerBar" :data="data" class="hidden lg:flex" />
|
||||||
<AppSpecification v-if="config.isAdminVueFileManagerBar" :data="data" class="card shadow-card lg:hidden" />
|
<AppSpecification v-if="config.isAdminVueFileManagerBar" :data="data" class="card shadow-card lg:hidden" />
|
||||||
|
|
||||||
<!--Create metered plan alert-->
|
|
||||||
<AlertBox v-if="config.subscriptionType === 'metered' && config.isEmptyPlans" color="rose">
|
|
||||||
As you installed app with metered subscription type, you have to <router-link :to="{ name: 'CreateMeteredPlan' }" class="dark:text-rose-500 text-sm font-bold underline">create your plan</router-link> as soon as possible to prevent new user registration without automatically assigned subscription plan.
|
|
||||||
</AlertBox>
|
|
||||||
|
|
||||||
<!--Cron Alert-->
|
<!--Cron Alert-->
|
||||||
<AlertBox v-if="!data.app.isRunningCron && !config.isDev" color="rose">
|
<AlertBox v-if="!data.app.isRunningCron && !config.isDev" color="rose">
|
||||||
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.
|
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.
|
||||||
@@ -50,22 +45,6 @@
|
|||||||
<chevron-right-icon size="16" class="text-theme vue-feather" />
|
<chevron-right-icon size="16" class="text-theme vue-feather" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="config.subscriptionType !== 'none'" class="card mb-4 w-full shadow-card md:mb-0">
|
|
||||||
<FormLabel icon="dollar">
|
|
||||||
{{ $t('earnings') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<b class="-mt-3 mb-0.5 block text-2xl font-extrabold sm:text-3xl">
|
|
||||||
{{ data.app.earnings }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<router-link :to="{ name: 'Invoices' }" class="mt-6 flex items-center">
|
|
||||||
<span class="mr-2 whitespace-nowrap text-xs font-bold">
|
|
||||||
{{ $t('show_all_transactions') }}
|
|
||||||
</span>
|
|
||||||
<chevron-right-icon size="16" class="text-theme vue-feather" />
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--Upload bandwidth widgets-->
|
<!--Upload bandwidth widgets-->
|
||||||
@@ -110,18 +89,6 @@
|
|||||||
|
|
||||||
<WidgetLatestRegistrations />
|
<WidgetLatestRegistrations />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--Latest transactions widgets-->
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<WidgetLatestTransactions />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="loader" v-if="isLoading">
|
<div id="loader" v-if="isLoading">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
@@ -137,7 +104,6 @@ import FormLabel from '../../components/UI/Labels/FormLabel'
|
|||||||
import BarChart from '../../components/UI/BarChart/BarChart'
|
import BarChart from '../../components/UI/BarChart/BarChart'
|
||||||
import {mapGetters} from 'vuex'
|
import {mapGetters} from 'vuex'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import WidgetLatestTransactions from '../../components/Dashboard/Widgets/WidgetLatestTransactions'
|
|
||||||
import AlertBox from "../../components/UI/Others/AlertBox";
|
import AlertBox from "../../components/UI/Others/AlertBox";
|
||||||
import AppSpecification from "../../components/Dashboard/AppSpecification";
|
import AppSpecification from "../../components/Dashboard/AppSpecification";
|
||||||
|
|
||||||
@@ -146,7 +112,6 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
AppSpecification,
|
AppSpecification,
|
||||||
AlertBox,
|
AlertBox,
|
||||||
WidgetLatestTransactions,
|
|
||||||
WidgetLatestRegistrations,
|
WidgetLatestRegistrations,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<!--Datatable-->
|
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</DatatableWrapper>
|
|
||||||
|
|
||||||
<!--Empty State-->
|
|
||||||
<div v-if="config.isEmptyTransactions" class="flex items-center justify-center fixed top-0 bottom-0 left-0 right-0">
|
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
<h1 class="mb-1 text-2xl font-bold">
|
|
||||||
{{ $t('there_is_nothing') }}
|
|
||||||
</h1>
|
|
||||||
<p class="text-sm text-gray-600">
|
|
||||||
{{ $t('transaction_will_be_here') }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import FixedTransactionRow from '../../components/Subscription/FixedTransactionRow'
|
|
||||||
import MeteredTransactionDetailRow from '../../components/Subscription/MeteredTransactionDetailRow'
|
|
||||||
import MeteredTransactionRow from '../../components/Subscription/MeteredTransactionRow'
|
|
||||||
import MemberAvatar from '../../components/UI/Others/MemberAvatar'
|
|
||||||
import DatatableWrapper from '../../components/UI/Table/DatatableWrapper'
|
|
||||||
import ColorLabel from '../../components/UI/Labels/ColorLabel'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Invoices',
|
|
||||||
components: {
|
|
||||||
MeteredTransactionDetailRow,
|
|
||||||
MeteredTransactionRow,
|
|
||||||
FixedTransactionRow,
|
|
||||||
DatatableWrapper,
|
|
||||||
MemberAvatar,
|
|
||||||
ColorLabel,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config']),
|
|
||||||
columns() {
|
|
||||||
if (config.subscriptionType === 'fixed') {
|
|
||||||
return this.$store.getters.transactionColumns.filter((column) => !['type'].includes(column.field))
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.$store.getters.transactionColumns
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
showedTransactionDetailById: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
showTransactionDetail(id) {
|
|
||||||
if (this.showedTransactionDetailById === id) this.showedTransactionDetailById = undefined
|
|
||||||
else this.showedTransactionDetailById = id
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<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">
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: 'PageEdit',
|
|
||||||
params: { slug: row.data.attributes.slug },
|
|
||||||
}"
|
|
||||||
class="cursor-pointer text-sm font-bold"
|
|
||||||
tag="div"
|
|
||||||
>
|
|
||||||
{{ row.data.attributes.title }}
|
|
||||||
</router-link>
|
|
||||||
</td>
|
|
||||||
<td class="px-3 md:px-1">
|
|
||||||
<span class="text-sm font-bold">
|
|
||||||
{{ row.data.attributes.slug }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<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
|
|
||||||
)
|
|
||||||
"
|
|
||||||
v-model="row.data.attributes.visibility"
|
|
||||||
:state="row.data.attributes.visibility"
|
|
||||||
class="switch"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="pl-3 text-right md:pl-1">
|
|
||||||
<div class="flex w-full justify-end space-x-2">
|
|
||||||
<router-link
|
|
||||||
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"
|
|
||||||
:to="{
|
|
||||||
name: 'PageEdit',
|
|
||||||
params: {
|
|
||||||
slug: row.data.attributes.slug,
|
|
||||||
},
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<Edit2Icon size="15" class="opacity-75" />
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
</DatatableWrapper>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import DatatableWrapper from '../../components/UI/Table/DatatableWrapper'
|
|
||||||
import MobileActionButton from '../../components/UI/Buttons/MobileActionButton'
|
|
||||||
import EmptyPageContent from '../../components/Others/EmptyPageContent'
|
|
||||||
import SwitchInput from '../../components/Inputs/SwitchInput'
|
|
||||||
import MobileHeader from '../../components/Mobile/MobileHeader'
|
|
||||||
import SectionTitle from '../../components/UI/Labels/SectionTitle'
|
|
||||||
import ButtonBase from '../../components/UI/Buttons/ButtonBase'
|
|
||||||
import { Trash2Icon, Edit2Icon } from 'vue-feather-icons'
|
|
||||||
import ColorLabel from '../../components/UI/Labels/ColorLabel'
|
|
||||||
import Spinner from '../../components/UI/Others/Spinner'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Pages',
|
|
||||||
components: {
|
|
||||||
MobileActionButton,
|
|
||||||
EmptyPageContent,
|
|
||||||
DatatableWrapper,
|
|
||||||
SectionTitle,
|
|
||||||
MobileHeader,
|
|
||||||
SwitchInput,
|
|
||||||
Trash2Icon,
|
|
||||||
ButtonBase,
|
|
||||||
ColorLabel,
|
|
||||||
Edit2Icon,
|
|
||||||
Spinner,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isLoading: true,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
label: this.$t('page'),
|
|
||||||
field: 'title',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('slug'),
|
|
||||||
field: 'slug',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('status'),
|
|
||||||
field: 'visibility',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('action'),
|
|
||||||
sortable: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div v-if="!isLoading && page" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ page.data.attributes.title }}
|
|
||||||
</FormLabel>
|
|
||||||
<AppInputSwitch
|
|
||||||
:title="$t('visibility')"
|
|
||||||
:description="$t('admin_pages.form.visibility_help')"
|
|
||||||
>
|
|
||||||
<SwitchInput @input="changeStatus" class="switch" :state="page.data.attributes.visibility" />
|
|
||||||
</AppInputSwitch>
|
|
||||||
<AppInputText :title="$t('title')">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/pages/' + $route.params.slug, 'title', page.data.attributes.title)"
|
|
||||||
v-model="page.data.attributes.title"
|
|
||||||
:placeholder="$t('admin_pages.form.title_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
<AppInputText :title="$t('slug')">
|
|
||||||
<input v-model="page.data.attributes.slug" type="text" class="focus-border-theme input-dark" disabled />
|
|
||||||
</AppInputText>
|
|
||||||
<AppInputText :title="$t('content')" :is-last="true">
|
|
||||||
<textarea
|
|
||||||
@input="$updateText('/admin/pages/' + $route.params.slug, 'content', page.data.attributes.content)"
|
|
||||||
v-model="page.data.attributes.content"
|
|
||||||
:placeholder="$t('admin_pages.form.content_plac')"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
rows="18"
|
|
||||||
></textarea>
|
|
||||||
</AppInputText>
|
|
||||||
</div>
|
|
||||||
<div id="loader" v-if="isLoading">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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 FormLabel from '../../../components/UI/Labels/FormLabel'
|
|
||||||
import { required } from 'vee-validate/dist/rules'
|
|
||||||
import SwitchInput from '../../../components/Inputs/SwitchInput'
|
|
||||||
import MobileHeader from '../../../components/Mobile/MobileHeader'
|
|
||||||
import SectionTitle from '../../../components/UI/Labels/SectionTitle'
|
|
||||||
import ButtonBase from '../../../components/UI/Buttons/ButtonBase'
|
|
||||||
import Spinner from '../../../components/UI/Others/Spinner'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PageEdit',
|
|
||||||
components: {
|
|
||||||
AppInputSwitch,
|
|
||||||
AppInputText,
|
|
||||||
ValidationProvider,
|
|
||||||
ValidationObserver,
|
|
||||||
FormLabel,
|
|
||||||
SectionTitle,
|
|
||||||
MobileHeader,
|
|
||||||
SwitchInput,
|
|
||||||
ButtonBase,
|
|
||||||
required,
|
|
||||||
Spinner,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isLoading: true,
|
|
||||||
page: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
changeStatus(val) {
|
|
||||||
this.$updateText('/admin/pages/' + this.$route.params.slug, 'visibility', val)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
axios.get('/api/admin/pages/' + this.$route.params.slug).then((response) => {
|
|
||||||
this.page = response.data
|
|
||||||
this.isLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<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: 'PaymentSettings',
|
|
||||||
components: {
|
|
||||||
CardNavigation,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pages: [
|
|
||||||
{
|
|
||||||
title: this.$t('payments'),
|
|
||||||
route: 'AppPayments',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('billings'),
|
|
||||||
route: 'AppBillings',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$router.replace({ name: 'AppPayments' })
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PageTab :is-loading="isLoading">
|
|
||||||
<div v-if="billingInformation" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('admin_settings.billings.section_company') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.company_name')">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'billing_name', billingInformation.billing_name)"
|
|
||||||
v-model="billingInformation.billing_name"
|
|
||||||
:placeholder="$t('admin_settings.billings.company_name_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.vat')" :is-last="true">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'billing_vat_number', billingInformation.billing_vat_number)"
|
|
||||||
v-model="billingInformation.billing_vat_number"
|
|
||||||
:placeholder="$t('admin_settings.billings.vat_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</div>
|
|
||||||
<div v-if="billingInformation" class="card shadow-card">
|
|
||||||
<FormLabel>
|
|
||||||
{{ $t('admin_settings.billings.section_billing') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.country')">
|
|
||||||
<SelectInput
|
|
||||||
@input="$updateText('/admin/settings', 'billing_country', billingInformation.billing_country)"
|
|
||||||
v-model="billingInformation.billing_country"
|
|
||||||
:default="billingInformation.billing_country"
|
|
||||||
:options="countries"
|
|
||||||
:placeholder="$t('admin_settings.billings.country_plac')"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('billing_address')">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'billing_address', billingInformation.billing_address)"
|
|
||||||
v-model="billingInformation.billing_address"
|
|
||||||
:placeholder="$t('admin_settings.billings.address_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div class="flex space-x-4">
|
|
||||||
<AppInputText :title="$t('billing_city')" class="w-full">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'billing_city', billingInformation.billing_city)"
|
|
||||||
v-model="billingInformation.billing_city"
|
|
||||||
:placeholder="$t('admin_settings.billings.city_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.postal_code')" class="w-full">
|
|
||||||
<input
|
|
||||||
@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"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.state')">
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'billing_state', billingInformation.billing_state)"
|
|
||||||
v-model="billingInformation.billing_state"
|
|
||||||
:placeholder="$t('admin_settings.billings.state_plac')"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<AppInputText :title="$t('admin_settings.billings.phone_number')" :is-last="true">
|
|
||||||
<input
|
|
||||||
@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"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</div>
|
|
||||||
</PageTab>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
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'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'AppAppearance',
|
|
||||||
components: {
|
|
||||||
ValidationObserver,
|
|
||||||
ValidationProvider,
|
|
||||||
AppInputText,
|
|
||||||
PageTabGroup,
|
|
||||||
SelectInput,
|
|
||||||
ImageInput,
|
|
||||||
ButtonBase,
|
|
||||||
FormLabel,
|
|
||||||
required,
|
|
||||||
PageTab,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['countries']),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isLoading: true,
|
|
||||||
billingInformation: undefined,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
axios
|
|
||||||
.get('/api/admin/settings', {
|
|
||||||
params: {
|
|
||||||
column: 'billing_phone_number|billing_postal_code|billing_vat_number|billing_address|billing_country|billing_state|billing_city|billing_name',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
this.isLoading = false
|
|
||||||
|
|
||||||
this.billingInformation = {
|
|
||||||
billing_phone_number: response.data.billing_phone_number,
|
|
||||||
billing_postal_code: response.data.billing_postal_code,
|
|
||||||
billing_vat_number: response.data.billing_vat_number,
|
|
||||||
billing_address: response.data.billing_address,
|
|
||||||
billing_country: response.data.billing_country,
|
|
||||||
billing_state: response.data.billing_state,
|
|
||||||
billing_city: response.data.billing_city,
|
|
||||||
billing_name: response.data.billing_name,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,664 +0,0 @@
|
|||||||
<template>
|
|
||||||
<PageTab>
|
|
||||||
<!--Global payment settings-->
|
|
||||||
<div class="card shadow-card">
|
|
||||||
<FormLabel icon="dollar">
|
|
||||||
{{ $t('subscription_payments') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputSwitch
|
|
||||||
:title="$t('allow_subscription_payments')"
|
|
||||||
:description="$t('allow_subscription_payments_description')"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<SwitchInput
|
|
||||||
@input="$updateText('/admin/settings', 'allowed_payments', allowedPayments)"
|
|
||||||
v-model="allowedPayments"
|
|
||||||
:state="allowedPayments"
|
|
||||||
/>
|
|
||||||
</AppInputSwitch>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Metered settings-->
|
|
||||||
<div v-if="config.subscriptionType === 'metered' && allowedPayments" class="card shadow-card">
|
|
||||||
<FormLabel icon="bar-chart">
|
|
||||||
{{ $t('metered_billing_settings') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<AppInputSwitch
|
|
||||||
:title="$t('allow_registration_bonus')"
|
|
||||||
:description="$t('allow_registration_bonus_description')"
|
|
||||||
>
|
|
||||||
<SwitchInput
|
|
||||||
@input="$updateText('/admin/settings', 'allowed_registration_bonus', allowedRegistrationBonus)"
|
|
||||||
v-model="allowedRegistrationBonus"
|
|
||||||
:state="allowedRegistrationBonus"
|
|
||||||
/>
|
|
||||||
</AppInputSwitch>
|
|
||||||
|
|
||||||
<AppInputText
|
|
||||||
v-if="allowedRegistrationBonus"
|
|
||||||
:title="$t('registration_bonus_amount')"
|
|
||||||
:description="$t('registration_bonus_amount_description')"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
@input="$updateText('/admin/settings', 'registration_bonus_amount', registrationBonusAmount)"
|
|
||||||
v-model="registrationBonusAmount"
|
|
||||||
:placeholder="$t('registration_bonus_amount_')"
|
|
||||||
type="number"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<AppInputButton
|
|
||||||
:title="$t('metered_plan')"
|
|
||||||
:description="$t('metered_plan_description')"
|
|
||||||
:is-last="true"
|
|
||||||
>
|
|
||||||
<router-link
|
|
||||||
v-if="config.isCreatedMeteredPlan"
|
|
||||||
:to="{
|
|
||||||
name: 'PlanMeteredSettings',
|
|
||||||
params: { id: config.meteredPlanId },
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<ButtonBase v-if="config.isCreatedMeteredPlan" class="w-full sm:w-auto" button-style="theme">
|
|
||||||
{{ $t('plan_details') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<router-link v-if="!config.isCreatedMeteredPlan" :to="{ name: 'CreateMeteredPlan' }">
|
|
||||||
<ButtonBase class="w-full sm:w-auto" button-style="theme-solid">
|
|
||||||
{{ $t('create_plan') }}
|
|
||||||
</ButtonBase>
|
|
||||||
</router-link>
|
|
||||||
</AppInputButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Stripe method configuration-->
|
|
||||||
<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_pay_by_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-->
|
|
||||||
<div v-if="stripe.allowedService">
|
|
||||||
<AppInputText
|
|
||||||
:title="$t('webhook_url')"
|
|
||||||
:description="$t('copy_webhook_note')"
|
|
||||||
>
|
|
||||||
<CopyInput size="small" :str="getWebhookEndpoint('stripe')" />
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div v-if="stripe.isConfigured">
|
|
||||||
<AppInputText
|
|
||||||
@input="$updateText('/admin/settings', 'stripe_payment_description', stripe.paymentDescription)"
|
|
||||||
:title="$t('payment_description')"
|
|
||||||
:description="$t('payment_description_note')"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
rows="2"
|
|
||||||
@input="
|
|
||||||
$updateText(
|
|
||||||
'/admin/settings',
|
|
||||||
'stripe_payment_description',
|
|
||||||
stripe.paymentDescription,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
"
|
|
||||||
v-model="stripe.paymentDescription"
|
|
||||||
:placeholder="
|
|
||||||
$t('additional_info_about_payment_method_')
|
|
||||||
"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div
|
|
||||||
@click="stripe.isVisibleCredentialsForm = !stripe.isVisibleCredentialsForm"
|
|
||||||
class="flex cursor-pointer items-center"
|
|
||||||
:class="{ 'mb-4': stripe.isVisibleCredentialsForm }"
|
|
||||||
>
|
|
||||||
<edit2-icon size="14" class="vue-feather text-theme mr-2.5" />
|
|
||||||
<b class="text-sm">{{ $t('update_your_credentials') }}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Set up Stripe credentials-->
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="!stripe.isConfigured || stripe.isVisibleCredentialsForm"
|
|
||||||
@submit.prevent="storeCredentials('stripe')"
|
|
||||||
ref="stripe"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="rounded-xl p-5 shadow-lg"
|
|
||||||
>
|
|
||||||
<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 }"
|
|
||||||
>
|
|
||||||
<AppInputText :title="$t('admin_settings.payments.stripe_pub_key')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="stripe.credentials.key"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_pub_key_plac')"
|
|
||||||
type="text"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Secret Key" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('admin_settings.payments.stripe_sec_key')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="stripe.credentials.secret"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_sec_key_plac')"
|
|
||||||
type="text"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
<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"
|
|
||||||
:placeholder="$t('paste_webhook_secret')"
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Paystack method configuration-->
|
|
||||||
<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_pay_by_card')"
|
|
||||||
:is-last="!paystack.allowedService"
|
|
||||||
>
|
|
||||||
<SwitchInput
|
|
||||||
@input="$updateText('/admin/settings', 'allowed_paystack', paystack.allowedService)"
|
|
||||||
v-model="paystack.allowedService"
|
|
||||||
:state="paystack.allowedService"
|
|
||||||
/>
|
|
||||||
</AppInputSwitch>
|
|
||||||
|
|
||||||
<!--Paystack credentials are set up-->
|
|
||||||
<div v-if="paystack.allowedService">
|
|
||||||
<AppInputText
|
|
||||||
:title="$t('webhook_url')"
|
|
||||||
:description="$t('copy_webhook_note')"
|
|
||||||
>
|
|
||||||
<CopyInput size="small" :str="getWebhookEndpoint('paystack')" />
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div v-if="paystack.isConfigured">
|
|
||||||
<AppInputText
|
|
||||||
@input="
|
|
||||||
$updateText('/admin/settings', 'paystack_payment_description', paystack.paymentDescription)
|
|
||||||
"
|
|
||||||
:title="$t('payment_description')"
|
|
||||||
:description="$t('payment_description_note')"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
rows="2"
|
|
||||||
@input="
|
|
||||||
$updateText(
|
|
||||||
'/admin/settings',
|
|
||||||
'paystack_payment_description',
|
|
||||||
paystack.paymentDescription,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
"
|
|
||||||
v-model="paystack.paymentDescription"
|
|
||||||
:placeholder="
|
|
||||||
$t('additional_info_about_payment_method_')
|
|
||||||
"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div
|
|
||||||
@click="paystack.isVisibleCredentialsForm = !paystack.isVisibleCredentialsForm"
|
|
||||||
class="flex cursor-pointer items-center"
|
|
||||||
:class="{ 'mb-4': paystack.isVisibleCredentialsForm }"
|
|
||||||
>
|
|
||||||
<edit2-icon size="14" class="vue-feather text-theme mr-2.5" />
|
|
||||||
<b class="text-sm">{{ $t('update_your_credentials') }}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Set up Paystack credentials-->
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="!paystack.isConfigured || paystack.isVisibleCredentialsForm"
|
|
||||||
@submit.prevent="storeCredentials('paystack')"
|
|
||||||
ref="paystack"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="rounded-xl p-5 shadow-lg"
|
|
||||||
>
|
|
||||||
<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 }"
|
|
||||||
>
|
|
||||||
<AppInputText :title="$t('admin_settings.payments.stripe_pub_key')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="paystack.credentials.key"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_pub_key_plac')"
|
|
||||||
type="text"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Secret Key" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('admin_settings.payments.stripe_sec_key')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="paystack.credentials.secret"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_sec_key_plac')"
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--PayPal method configuration-->
|
|
||||||
<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_pay_by_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">
|
|
||||||
<AppInputText
|
|
||||||
:title="$t('webhook_url')"
|
|
||||||
:description="$t('copy_webhook_note')"
|
|
||||||
>
|
|
||||||
<CopyInput size="small" :str="getWebhookEndpoint('paypal')" />
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div v-if="paypal.isConfigured">
|
|
||||||
<AppInputSwitch :title="$t('Live Mode')" :description="$t('Toggle between live and sandbox mode')">
|
|
||||||
<SwitchInput
|
|
||||||
@input="$updateText('/admin/settings', 'paypal_live', config.isPayPalLive)"
|
|
||||||
v-model="config.isPayPalLive"
|
|
||||||
:state="config.isPayPalLive"
|
|
||||||
/>
|
|
||||||
</AppInputSwitch>
|
|
||||||
|
|
||||||
<AppInputText
|
|
||||||
@input="$updateText('/admin/settings', 'paypal_payment_description', paypal.paymentDescription)"
|
|
||||||
:title="$t('payment_description')"
|
|
||||||
:description="$t('payment_description_note')"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
rows="2"
|
|
||||||
@input="
|
|
||||||
$updateText(
|
|
||||||
'/admin/settings',
|
|
||||||
'paypal_payment_description',
|
|
||||||
paypal.paymentDescription,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
"
|
|
||||||
v-model="paypal.paymentDescription"
|
|
||||||
:placeholder="
|
|
||||||
$t('additional_info_about_payment_method_')
|
|
||||||
"
|
|
||||||
type="text"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
|
|
||||||
<div
|
|
||||||
@click="paypal.isVisibleCredentialsForm = !paypal.isVisibleCredentialsForm"
|
|
||||||
class="flex cursor-pointer items-center"
|
|
||||||
:class="{ 'mb-4': paypal.isVisibleCredentialsForm }"
|
|
||||||
>
|
|
||||||
<edit2-icon size="14" class="vue-feather text-theme mr-2.5" />
|
|
||||||
<b class="text-sm">{{ $t('update_your_credentials') }}</b>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Set up Paypal credentials-->
|
|
||||||
<ValidationObserver
|
|
||||||
v-if="!paypal.isConfigured || paypal.isVisibleCredentialsForm"
|
|
||||||
@submit.prevent="storeCredentials('paypal')"
|
|
||||||
ref="paypal"
|
|
||||||
v-slot="{ invalid }"
|
|
||||||
tag="form"
|
|
||||||
class="rounded-xl p-5 shadow-lg"
|
|
||||||
>
|
|
||||||
<FormLabel v-if="!paypal.isConfigured" icon="shield">
|
|
||||||
{{ $t('configure_your_credentials') }}
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<ValidationProvider>
|
|
||||||
<AppInputSwitch v-if="! paypal.isConfigured" :title="$t('Live Mode')" :description="$t('Toggle between live and sandbox mode')">
|
|
||||||
<SwitchInput v-model="paypal.credentials.live" :state="paypal.credentials.live" />
|
|
||||||
</AppInputSwitch>
|
|
||||||
</ValidationProvider>
|
|
||||||
|
|
||||||
<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"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_pub_key_plac')"
|
|
||||||
type="text"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Secret Key" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('admin_settings.payments.stripe_sec_key')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="paypal.credentials.secret"
|
|
||||||
:placeholder="$t('admin_settings.payments.stripe_sec_key_plac')"
|
|
||||||
type="text"
|
|
||||||
:class="{ '!border-rose-600': errors[0] }"
|
|
||||||
class="focus-border-theme input-dark"
|
|
||||||
/>
|
|
||||||
</AppInputText>
|
|
||||||
</ValidationProvider>
|
|
||||||
<ValidationProvider tag="div" mode="passive" name="Webhook ID" rules="required" v-slot="{ errors }">
|
|
||||||
<AppInputText :title="$t('Webhook ID')" :error="errors[0]">
|
|
||||||
<input
|
|
||||||
v-model="paypal.credentials.webhook"
|
|
||||||
:placeholder="$t('Paste your webhook id')"
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
</PageTab>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { Edit2Icon, Trash2Icon } from 'vue-feather-icons'
|
|
||||||
import AppInputButton from '../../../../components/Forms/Layouts/AppInputButton'
|
|
||||||
import DatatableWrapper from '../../../../components/UI/Table/DatatableWrapper'
|
|
||||||
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 AppInputSwitch from '../../../../components/Forms/Layouts/AppInputSwitch'
|
|
||||||
import FormLabel from '../../../../components/UI/Labels/FormLabel'
|
|
||||||
import ButtonBase from '../../../../components/UI/Buttons/ButtonBase'
|
|
||||||
import CopyInput from '../../../../components/Inputs/CopyInput'
|
|
||||||
import AppInputText from '../../../../components/Forms/Layouts/AppInputText'
|
|
||||||
import PageTab from '../../../../components/Layout/PageTab'
|
|
||||||
import InfoBox from '../../../../components/UI/Others/InfoBox'
|
|
||||||
import { required } from 'vee-validate/dist/rules'
|
|
||||||
import { events } from '../../../../bus'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'AppPayments',
|
|
||||||
components: {
|
|
||||||
AppInputButton,
|
|
||||||
DatatableWrapper,
|
|
||||||
ValidationObserver,
|
|
||||||
ValidationProvider,
|
|
||||||
AppInputSwitch,
|
|
||||||
AppInputText,
|
|
||||||
PageTabGroup,
|
|
||||||
SwitchInput,
|
|
||||||
SelectInput,
|
|
||||||
ImageInput,
|
|
||||||
ButtonBase,
|
|
||||||
CopyInput,
|
|
||||||
FormLabel,
|
|
||||||
Trash2Icon,
|
|
||||||
Edit2Icon,
|
|
||||||
required,
|
|
||||||
PageTab,
|
|
||||||
InfoBox,
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['config']),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
allowedRegistrationBonus: true,
|
|
||||||
registrationBonusAmount: undefined,
|
|
||||||
|
|
||||||
allowedPayments: false,
|
|
||||||
|
|
||||||
isLoading: false,
|
|
||||||
isError: false,
|
|
||||||
errorMessage: '',
|
|
||||||
stripe: {
|
|
||||||
allowedService: true,
|
|
||||||
isConfigured: false,
|
|
||||||
isVisibleCredentialsForm: false,
|
|
||||||
paymentDescription: undefined,
|
|
||||||
credentials: {
|
|
||||||
key: undefined,
|
|
||||||
secret: undefined,
|
|
||||||
webhook: undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
paystack: {
|
|
||||||
allowedService: true,
|
|
||||||
isConfigured: false,
|
|
||||||
isVisibleCredentialsForm: false,
|
|
||||||
paymentDescription: undefined,
|
|
||||||
credentials: {
|
|
||||||
key: undefined,
|
|
||||||
secret: undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
paypal: {
|
|
||||||
allowedService: true,
|
|
||||||
isConfigured: false,
|
|
||||||
isVisibleCredentialsForm: false,
|
|
||||||
paymentDescription: undefined,
|
|
||||||
credentials: {
|
|
||||||
key: undefined,
|
|
||||||
secret: undefined,
|
|
||||||
webhook: undefined,
|
|
||||||
live: undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
label: this.$t('name'),
|
|
||||||
field: 'name',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('currency'),
|
|
||||||
field: 'currency',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('interval'),
|
|
||||||
field: 'interval',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('subscribers'),
|
|
||||||
sortable: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: this.$t('action'),
|
|
||||||
sortable: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
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/payment-service', {
|
|
||||||
service: service,
|
|
||||||
key: this[service].credentials.key,
|
|
||||||
secret: this[service].credentials.secret,
|
|
||||||
webhook: this[service].credentials.webhook || undefined,
|
|
||||||
live: this[service].credentials.live,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// Update Credentials
|
|
||||||
let commitKey = {
|
|
||||||
stripe: 'SET_STRIPE_CREDENTIALS',
|
|
||||||
paystack: 'SET_PAYSTACK_CREDENTIALS',
|
|
||||||
paypal: 'SET_PAYPAL_CREDENTIALS',
|
|
||||||
}[service]
|
|
||||||
|
|
||||||
// Commit credentials
|
|
||||||
this.$store.commit(commitKey, this[service].credentials)
|
|
||||||
|
|
||||||
this[service].allowedService = true
|
|
||||||
this[service].isConfigured = 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))
|
|
||||||
},
|
|
||||||
getWebhookEndpoint(service) {
|
|
||||||
return `${this.config.host}/api/subscriptions/${service}/webhooks`
|
|
||||||
},
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// Set payment description
|
|
||||||
this.stripe.paymentDescription = this.config.stripe_payment_description
|
|
||||||
this.paystack.paymentDescription = this.config.paystack_payment_description
|
|
||||||
this.paypal.paymentDescription = this.config.paypal_payment_description
|
|
||||||
|
|
||||||
// Set if service is allowed
|
|
||||||
this.stripe.allowedService = this.config.isStripe
|
|
||||||
this.paystack.allowedService = this.config.isPaystack
|
|
||||||
this.paypal.allowedService = this.config.isPayPal
|
|
||||||
|
|
||||||
if (this.config.stripe_public_key) this.stripe.isConfigured = true
|
|
||||||
|
|
||||||
if (this.config.paystack_public_key) this.paystack.isConfigured = true
|
|
||||||
|
|
||||||
if (this.config.paypal_client_id) this.paypal.isConfigured = true
|
|
||||||
|
|
||||||
this.allowedPayments = this.config.allowed_payments
|
|
||||||
|
|
||||||
// Set metered
|
|
||||||
this.allowedRegistrationBonus = this.config.allowed_registration_bonus
|
|
||||||
this.registrationBonusAmount = this.config.registration_bonus_amount
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
events.$off('action:confirmed')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user