landing page

This commit is contained in:
carodej
2020-07-08 09:07:11 +02:00
parent 5a5125967f
commit a43f0e6908
46 changed files with 2926 additions and 641 deletions
+1 -1
View File
@@ -34,7 +34,7 @@
</ContentGroup>
<!--SaaS-->
<ContentGroup v-if="config.isSaaS" title="SaaS" class="navigator">
<ContentGroup v-if="config.isSaaS" title="Subscription" class="navigator">
<div class="menu-list-wrapper vertical">
<router-link :to="{name: 'Plans'}" class="menu-list-item link">
<div class="icon">
@@ -18,7 +18,7 @@
</div>
</router-link>
<router-link replace :to="{name: 'AppBillings'}"
<router-link v-if="config.isSaaS" replace :to="{name: 'AppBillings'}"
class="menu-list-item link">
<div class="icon">
<file-text-icon size="17"></file-text-icon>
@@ -38,6 +38,16 @@
</div>
</router-link>
<router-link v-if="config.isSaaS" replace :to="{name: 'AppPayments'}"
class="menu-list-item link">
<div class="icon">
<credit-card-icon size="17"></credit-card-icon>
</div>
<div class="label">
Payments
</div>
</router-link>
<router-link replace :to="{name: 'AppOthers'}"
class="menu-list-item link">
<div class="icon">
@@ -57,16 +67,18 @@
</template>
<script>
import {UsersIcon, SettingsIcon, Trash2Icon, EyeIcon, FileTextIcon, CodeIcon, MailIcon} from 'vue-feather-icons'
import {UsersIcon, SettingsIcon, Trash2Icon, EyeIcon, FileTextIcon, CodeIcon, MailIcon, CreditCardIcon} from 'vue-feather-icons'
import MobileHeader from '@/components/Mobile/MobileHeader'
import SectionTitle from '@/components/Others/SectionTitle'
import PageHeader from '@/components/Others/PageHeader'
import Spinner from '@/components/FilesView/Spinner'
import { mapGetters } from 'vuex'
import axios from 'axios'
export default {
name: 'AppSettings',
components: {
CreditCardIcon,
CodeIcon,
MailIcon,
FileTextIcon,
@@ -79,6 +91,9 @@
PageHeader,
Spinner,
},
computed: {
...mapGetters(['config']),
},
}
</script>
@@ -0,0 +1,114 @@
<template>
<PageTab :is-loading="isLoading" class="form-fixed-width">
<!--Personal Information-->
<PageTabGroup>
<div class="form block-form">
<FormLabel>Stripe Payments</FormLabel>
<InfoBox>
<p>Your Stripe credentials is not showed because these values are secret and must not be revealed by stranger. You can change your Stripe credentials in your <b>.env</b> file.</p>
</InfoBox>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">Allow Subscription Payments:</label>
</div>
<SwitchInput @input="$updateText('/settings', 'payments_active', payments.status)" v-model="payments.status" class="switch" :state="payments.status"/>
</div>
</div>
</div>
<div class="block-wrapper">
<label>Stripe webhook URL:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Webhook URL" rules="required" v-slot="{ errors }">
<input :value="stripeWebhookEndpoint" type="text" disabled/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
</div>
</PageTabGroup>
</PageTab>
</template>
<script>
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import StorageItemDetail from '@/components/Others/StorageItemDetail'
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import SelectInput from '@/components/Others/Forms/SelectInput'
import SwitchInput from '@/components/Others/Forms/SwitchInput'
import ImageInput from '@/components/Others/Forms/ImageInput'
import FormLabel from '@/components/Others/Forms/FormLabel'
import ButtonBase from '@/components/FilesView/ButtonBase'
import SetupBox from '@/components/Others/Forms/SetupBox'
import PageTab from '@/components/Others/Layout/PageTab'
import InfoBox from '@/components/Others/Forms/InfoBox'
import {required} from 'vee-validate/dist/rules'
import {mapGetters} from 'vuex'
import axios from 'axios'
export default {
name: 'AppPayments',
components: {
ValidationObserver,
ValidationProvider,
StorageItemDetail,
PageTabGroup,
SwitchInput,
SelectInput,
ImageInput,
ButtonBase,
FormLabel,
SetupBox,
required,
PageTab,
InfoBox,
},
computed: {
...mapGetters(['config']),
stripeWebhookEndpoint() {
return this.config.host + '/stripe/webhook'
}
},
data() {
return {
isLoading: true,
payments: {
status: undefined,
configured: undefined,
},
}
},
mounted() {
axios.get('/api/settings', {
params: {
column: 'payments_active|payments_configured'
}
})
.then(response => {
this.isLoading = false
this.payments.configured = parseInt(response.data.payments_configured)
this.payments.status = parseInt(response.data.payments_active)
})
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@import '@assets/vue-file-manager/_forms';
.block-form {
max-width: 100%;
}
@media only screen and (max-width: 960px) {
}
@media (prefers-color-scheme: dark) {
}
</style>
+5
View File
@@ -48,6 +48,7 @@
link-name="Show All Users"
></WidgetTotals>
<WidgetTotals
v-if="config.isSaaS"
class="widget"
icon="star"
title="Total Premium Users"
@@ -84,6 +85,7 @@
import ColorLabel from '@/components/Others/ColorLabel'
import Spinner from '@/components/FilesView/Spinner'
import {CreditCardIcon} from "vue-feather-icons"
import { mapGetters } from 'vuex'
import axios from 'axios'
export default {
@@ -103,6 +105,9 @@
ColorLabel,
Spinner,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
isLoading: false,
+2 -2
View File
@@ -143,7 +143,7 @@
},
{
label: 'Subscription Plan',
field: 'data.attributes.role',
field: 'data.attributes.subscription',
sortable: true,
hidden: ! this.config.isSaaS,
},
@@ -154,7 +154,7 @@
},
{
label: this.$t('admin_page_user.table.storage_capacity'),
field: 'data.attributes.storage.capacity',
field: 'relationships.storage.data.attributes.capacity',
sortable: true
},
{
+11
View File
@@ -9,6 +9,7 @@
<div class="user-thumbnail">
<div class="avatar">
<img :src="user.data.attributes.avatar" :alt="user.data.attributes.name">
<!--<img :src="user.data.attributes.avatar" :alt="user.data.attributes.name" class="blurred">-->
</div>
<div class="info">
<b class="name">
@@ -151,15 +152,25 @@
display: flex;
align-items: center;
cursor: pointer;
padding-bottom: 10px;
padding-top: 15px;
.avatar {
margin-right: 20px;
position: relative;
img {
line-height: 0;
width: 62px;
height: 62px;
border-radius: 12px;
z-index: 1;
position: relative;
&.blurred {
@include blurred-image;
top: 0;
}
}
}
+199
View File
@@ -0,0 +1,199 @@
<template>
<div class="landing-page">
<!--Navigation-->
<Navigation class="page-wrapper small"/>
<!--Page content-->
<div class="page-wrapper small">
<!--Headline-->
<PageTitle
class="headline"
title="Contact Us"
description="Dominion, open bearing brought may dominion male beginning."
></PageTitle>
<!--Content-->
<div class="page-content">
<ValidationObserver @submit.prevent="contactForm" ref="contactForm" v-slot="{ invalid }" tag="form"
class="form block-form">
<div class="block-wrapper">
<label>{{ $t('page_registration.label_email') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="contact.email" :placeholder="$t('page_registration.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>Message:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Message" rules="required"
v-slot="{ errors }">
<textarea v-model="contact.message" placeholder="Type your message here..." rows="4" :class="{'is-error': errors[0]}"></textarea>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton class="submit-button" icon="chevron-right" text="Send Message" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
</div>
</div>
<!--Footer-->
<PageFooter/>
</div>
</template>
<script>
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import AuthButton from '@/components/Auth/AuthButton'
import {required} from 'vee-validate/dist/rules'
import PageTitle from '@/components/Index/Components/PageTitle'
import PageFooter from '@/components/Index/IndexPageFooter'
import Navigation from '@/components/Index/IndexNavigation'
import {mapGetters} from 'vuex'
import axios from 'axios'
export default {
name: 'ContactUs',
components: {
ValidationProvider,
ValidationObserver,
AuthButton,
PageFooter,
Navigation,
PageTitle,
required,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
isLoading: false,
contact: {
email: '',
message: '',
},
}
},
methods: {
async contactForm() {
// Validate fields
const isValid = await this.$refs.contactForm.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user token
axios
.post('/api/user/register', this.register)
.then(() => {
// End loading
this.isLoading = false
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
// Go to files page
this.$router.push({name: 'Files'})
})
.catch(error => {
if (error.response.status == 401) {
if (error.response.data.error === 'invalid_client') {
events.$emit('alert:open', {
emoji: '🤔',
title: this.$t('popup_passport_error.title'),
message: this.$t('popup_passport_error.message')
})
}
}
if (error.response.status == 500) {
events.$emit('alert:open', {
emoji: '🤔',
title: this.$t('popup_signup_error.title'),
message: this.$t('popup_signup_error.message')
})
}
if (error.response.status == 422) {
if (error.response.data.errors['email']) {
this.$refs.sign_up.setErrors({
'E-Mail': error.response.data.errors['email']
});
}
if (error.response.data.errors['password']) {
this.$refs.sign_up.setErrors({
'Your New Password': error.response.data.errors['password']
});
}
}
// End loading
this.isLoading = false
})
}
},
created() {
this.$scrollTop()
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_landing-page';
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@import '@assets/vue-file-manager/_forms';
.headline {
padding-top: 70px;
padding-bottom: 50px;
}
.page-content {
p {
@include font-size(20);
font-weight: 500;
line-height: 1.65;
padding-bottom: 30px;
}
}
.form.block-form {
.submit-button {
margin-top: 20px;
margin-left: 0;
margin-right: 0;
}
}
@media (prefers-color-scheme: dark) {
}
@media only screen and (max-width: 690px) {
}
</style>
+90
View File
@@ -0,0 +1,90 @@
<template>
<div class="landing-page">
<!--Navigation-->
<Navigation class="page-wrapper small"/>
<!--Page content-->
<div class="page-wrapper small">
<!--Headline-->
<PageTitle
class="headline"
title="Terms & Conditions"
></PageTitle>
<!--Content-->
<div class="page-content">
<p>Dominion, open bearing brought may dominion male beginning god land greater forth there fruit whose creepeth two their great there morning multiply Third image
first. Waters waters. Which, moving place let said their saw, behold good appear of days very dominion called shall creeping creepeth subdue living, over set
subdue above under form make appear blessed, given shall midst likeness midst days him fruit seasons void hath light it him and days gathering give itself his
heaven fruitful fourth darkness bearing. Bring third a our gathered fruitful man sixth place.</p>
<p>Have give land may man together unto appear bring it is creature. Gathering abundantly. Beast night. Blessed be Lights, second brought. Yielding without set the
open give one seed of fowl said living years said female. Second hath subdue, give dry which very there night is. Whales very seed heaven set image.</p>
<p>Was moved, air seas Without. Winged years third. Dry under upon very Light tree. Given be meat seed fish. Over earth was beast fruitful. Abundantly great female
sixth. Which divide our days fly heaven seasons. Lights form created darkness third morning, and won't whales. Living fowl bearing saying dominion first female.
That to lesser our doesn't morning place.</p>
</div>
</div>
<!--Footer-->
<PageFooter/>
</div>
</template>
<script>
import PageTitle from '@/components/Index/Components/PageTitle'
import PageFooter from '@/components/Index/IndexPageFooter'
import Navigation from '@/components/Index/IndexNavigation'
import {mapGetters} from 'vuex'
import axios from 'axios'
export default {
name: 'SaaSLandingPage',
components: {
PageFooter,
Navigation,
PageTitle,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
isLoading: false,
}
},
created() {
this.$scrollTop()
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_landing-page';
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.headline {
padding-top: 70px;
padding-bottom: 50px;
}
.page-content {
p {
@include font-size(20);
font-weight: 500;
line-height: 1.65;
padding-bottom: 30px;
}
}
@media (prefers-color-scheme: dark) {
}
@media only screen and (max-width: 690px) {
}
</style>
@@ -0,0 +1,72 @@
<template>
<div class="landing-page">
<!--Navigation-->
<Navigation class="page-wrapper medium" />
<!--Header-->
<PageHeader />
<!--VueFileManager ScreenShot-->
<HeroScreenshot />
<!--Main Features-->
<MainFeatures />
<!--Pricing Tables-->
<PricingTables />
<!--Get Started Call To Action-->
<GetStarted />
<!--Footer-->
<PageFooter />
</div>
</template>
<script>
import HeroScreenshot from '@/components/Index/IndexHeroScreenshot'
import PricingTables from '@/components/Index/IndexPricingTables'
import MainFeatures from '@/components/Index/IndexMainFeatures'
import Navigation from '@/components/Index/IndexNavigation'
import PageHeader from '@/components/Index/IndexPageHeader'
import GetStarted from '@/components/Index/IndexGetStarted'
import PageFooter from '@/components/Index/IndexPageFooter'
import { mapGetters } from 'vuex'
import axios from 'axios'
export default {
name: 'SaaSLandingPage',
components: {
HeroScreenshot,
PricingTables,
MainFeatures,
GetStarted,
Navigation,
PageHeader,
PageFooter,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
isLoading: false,
}
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vue-file-manager/_landing-page';
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
@media (prefers-color-scheme: dark) {
}
@media only screen and (max-width: 690px) {
}
</style>
+3 -1
View File
@@ -91,7 +91,7 @@
<span class="email">{{ user.data.attributes.email }}</span>
</div>
</div>
<div v-if="config.isSaaS" class="headline-actions">
<div v-if="config.isSaaS && config.app_payments_active" class="headline-actions">
<router-link :to="{name: 'UpgradePlan'}" v-if="! user.relationships.subscription || (user.relationships.subscription && ! user.relationships.subscription.data.attributes.is_highest)">
<ButtonBase class="upgrade-button" button-style="secondary" type="button">
Upgrade Plan
@@ -194,6 +194,8 @@
width: 62px;
height: 62px;
border-radius: 12px;
z-index: 1;
position: relative;
}
}
@@ -196,8 +196,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
+1 -2
View File
@@ -208,8 +208,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
@@ -422,8 +422,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
+1 -2
View File
@@ -173,8 +173,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
@@ -239,8 +239,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
@@ -111,8 +111,7 @@
})
.then(response => {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
// End loading
this.isLoading = false
@@ -704,8 +704,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
@@ -184,8 +184,7 @@
},
},
created() {
var container = document.getElementById('vue-file-manager')
container.scrollTop = 0
this.$scrollTop()
}
}
</script>
@@ -62,6 +62,9 @@
isLoading: false,
}
},
created() {
this.$scrollTop()
}
}
</script>
+5 -2
View File
@@ -25,7 +25,7 @@
</div>
</div>
</PageTabGroup>
<PageTabGroup v-if="billingInfo">
<PageTabGroup v-if="config.isSaaS && billingInfo">
<div class="form block-form">
<FormLabel>Billing Information</FormLabel>
<div class="block-wrapper">
@@ -115,7 +115,7 @@
import PageHeader from '@/components/Others/PageHeader'
import ThemeLabel from '@/components/Others/ThemeLabel'
import {required} from 'vee-validate/dist/rules'
import {mapGetters} from 'vuex'
import { mapGetters } from 'vuex'
import {debounce} from 'lodash'
export default {
@@ -135,6 +135,9 @@
ThemeLabel,
required,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
userInfo: undefined,