vue router implemented

This commit is contained in:
carodej
2020-04-07 14:48:29 +02:00
parent bde58fbf60
commit ae4353cc4b
21 changed files with 722 additions and 998 deletions
+101 -6
View File
@@ -1,25 +1,120 @@
<template>
<div id="app">
<VueFileManager style="height: 100%; width: 100%"/>
<div id="vue-file-manager" :class="appSize">
<div id="popups">
<!--System alerts-->
<Alert />
<!--Popup-->
<PopupMoveItem />
<!--Mobile Menu-->
<MobileOptionList />
<!--Background vignette-->
<Vignette />
</div>
<div id="application-wrapper" v-if="isLogged">
<!--Navigation Sidebar-->
<Sidebar />
<!--File page-->
<router-view />
</div>
<router-view v-if="! isLogged" />
</div>
</template>
<script>
import VueFileManager from './components/VueFileManager.vue'
import MobileOptionList from '@/components/VueFileManagerComponents/FilesView/MobileOptionList'
import PopupMoveItem from '@/components/VueFileManagerComponents/Others/PopupMoveItem'
import Vignette from '@/components/VueFileManagerComponents/Others/Vignette'
import Alert from '@/components/VueFileManagerComponents/FilesView/Alert'
import Sidebar from '@/components/VueFileManagerComponents/Sidebar/Sidebar'
import {ResizeSensor} from 'css-element-queries'
import {mapGetters} from 'vuex'
export default {
name: 'app',
components: {
VueFileManager
MobileOptionList,
PopupMoveItem,
Vignette,
Sidebar,
Alert,
},
computed: {
...mapGetters([
'appSize', 'isLogged', 'isGuest'
]),
},
methods: {
handleAppResize() {
let appView = document.getElementById('vue-file-manager')
.offsetWidth
if (appView <= 690)
this.$store.commit('SET_APP_WIDTH', 'small')
if (appView > 690 && appView < 960)
this.$store.commit('SET_APP_WIDTH', 'medium')
if (appView > 960)
this.$store.commit('SET_APP_WIDTH', 'large')
},
},
beforeMount() {
// Store config to vuex
this.$store.commit('SET_AUTHORIZED', this.$root.$data.config.hasAuthCookie)
this.$store.commit('SET_CONFIG', this.$root.$data.config)
},
mounted() {
// Handle VueFileManager width
var VueFileManager = document.getElementById('vue-file-manager');
new ResizeSensor(VueFileManager, this.handleAppResize);
}
}
</script>
<style lang="scss">
@import "@assets/app.scss";
#app {
height: 100%;
* {
outline: 0;
margin: 0;
padding: 0;
font-family: 'Nunito', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
font-size: 16px;
}
// Dark mode support
@media (prefers-color-scheme: dark) {
body, html {
background: $dark_mode_background;
color: $dark_mode_text_primary;
img {
opacity: .8;
}
}
}
#auth {
width: 100%;
height: 100%;
}
#vue-file-manager {
position: absolute;
width: 100%;
height: 100%;
overflow-y: auto;
}
</style>
-150
View File
@@ -1,150 +0,0 @@
<template>
<div id="vue-file-manager" :class="appSize">
<router-view />
<!--Authentication pages-->
<!--<Auth v-if="isGuest" />-->
<!--<div v-if="isLogged" id="auth">
<div id="popups">
&lt;!&ndash;System alerts&ndash;&gt;
<Alert />
&lt;!&ndash;Popup&ndash;&gt;
<PopupMoveItem />
&lt;!&ndash;Mobile Menu&ndash;&gt;
<MobileOptionList />
&lt;!&ndash;Background vignette&ndash;&gt;
<Vignette />
</div>
<div id="application-wrapper">
&lt;!&ndash;Navigation Sidebar&ndash;&gt;
<Sidebar />
&lt;!&ndash;User settings Page&ndash;&gt;
<UserSettings v-if="isCurrentView('user-settings')"/>
&lt;!&ndash;File page&ndash;&gt;
<FilesView v-if="isCurrentView('files')"/>
</div>
</div>-->
</div>
</template>
<script>
import MobileOptionList from '@/components/VueFileManagerComponents/FilesView/MobileOptionList'
import PopupMoveItem from '@/components/VueFileManagerComponents/Others/PopupMoveItem'
import UserSettings from '@/components/VueFileManagerComponents/UserSettings'
import Vignette from '@/components/VueFileManagerComponents/Others/Vignette'
import Alert from '@/components/VueFileManagerComponents/FilesView/Alert'
import FilesView from '@/components/VueFileManagerComponents/FilesView'
import Sidebar from '@/components/VueFileManagerComponents/Sidebar'
import Auth from '@/components/VueFileManagerComponents/Auth'
import {ResizeSensor} from 'css-element-queries'
import {mapGetters} from 'vuex'
import {events} from "../bus";
export default {
name: 'VueFileManager',
components: {
MobileOptionList,
PopupMoveItem,
UserSettings,
FilesView,
Vignette,
Sidebar,
Alert,
Auth,
},
computed: {
...mapGetters([
'isLogged', 'isGuest', 'currentView', 'appSize'
]),
},
methods: {
isCurrentView(view) {
return this.currentView === view
},
handleAppResize() {
let appView = document.getElementById('vue-file-manager')
.offsetWidth
if (appView <= 690)
this.$store.commit('SET_APP_WIDTH', 'small')
if (appView > 690 && appView < 960)
this.$store.commit('SET_APP_WIDTH', 'medium')
if (appView > 960)
this.$store.commit('SET_APP_WIDTH', 'large')
},
},
beforeMount() {
// Store config to vuex
this.$store.commit('SET_AUTHORIZED', this.$root.$data.config.hasAuthCookie)
this.$store.commit('SET_CONFIG', this.$root.$data.config)
},
mounted() {
// Handle VueFileManager width
var VueFileManager = document.getElementById('vue-file-manager');
new ResizeSensor(VueFileManager, this.handleAppResize);
}
}
</script>
<style lang="scss">
@import "@assets/app.scss";
* {
outline: 0;
margin: 0;
padding: 0;
font-family: 'Nunito', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
font-size: 16px;
}
// Dark mode support
@media (prefers-color-scheme: dark) {
body, html {
background: $dark_mode_background;
color: $dark_mode_text_primary;
img {
opacity: .8;
}
}
}
#auth {
width: 100%;
height: 100%;
}
#vue-file-manager {
position: relative;
width: 100%;
height: 100%;
overflow-y: auto;
}
#application-wrapper {
display: flex;
height: 100%;
#content {
position: relative;
width: 100%;
}
}
</style>
@@ -1,555 +0,0 @@
<template>
<AuthContentWrapper ref="auth">
<!--Log In by Email-->
<AuthContent name="log-in" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_login.title') }}</h1>
<h2>{{ $t('page_login.subtitle') }}</h2>
<ValidationObserver @submit.prevent="logIn" ref="log_in" v-slot="{ invalid }" tag="form"
class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="loginEmail" :placeholder="$t('page_login.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" :text="$t('page_login.button_next')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span v-if="config.userRegistration" class="additional-link">{{ $t('page_login.registration_text') }} <b
@click="goToAuthPage('sign-up')">{{ $t('page_login.registration_button') }}</b></span>
</AuthContent>
<!--Log in By Password-->
<AuthContent name="sign-in" :visible="false">
<div class="user" v-if="checkedAccount">
<img class="user-avatar" :src="checkedAccount.avatar" :alt="checkedAccount.name">
<h1>{{ $t('page_sign_in.title', {name: checkedAccount.name}) }}</h1>
<h2>{{ $t('page_sign_in.subtitle') }}</h2>
</div>
<ValidationObserver @submit.prevent="singIn" ref="sign_in" v-slot="{ invalid }" tag="form"
class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="User Password" rules="required"
v-slot="{ errors }">
<input v-model="loginPassword" :placeholder="$t('page_sign_in.placeholder_password')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">{{ $t('page_sign_in.password_reset_text') }} <b @click="goToAuthPage('forgotten-password')">{{ $t('page_sign_in.password_reset_button') }}</b></span>
</AuthContent>
<!--Forgotten your password?-->
<AuthContent name="forgotten-password" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.title') }}</h1>
<h2>{{ $t('page_forgotten_password.subtitle') }}</h2>
<ValidationObserver @submit.prevent="forgottenPassword" ref="forgotten_password" v-slot="{ invalid }"
tag="form" class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverEmail" :placeholder="$t('page_login.placeholder_email')" type="email"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" :text="$t('page_forgotten_password.button_get_link')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Create new password-->
<AuthContent name="create-new-password" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_create_password.title') }}</h1>
<h2>{{ $t('page_create_password.subtitle') }}</h2>
<ValidationObserver @submit.prevent="createNewPassword" ref="create_new_password" v-slot="{ invalid }"
tag="form" class="form block-form create-new-password">
<div class="block-wrapper">
<label>{{ $t('page_create_password.label_email') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverPassword.email" :placeholder="$t('page_login.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>{{ $t('page_create_password.label_new_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPassword" :placeholder="$t('page_create_password.label_new_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPasswordConfirm" :placeholder="$t('page_create_password.label_confirm_pass')"
type="password" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton icon="chevron-right" :text="$t('page_create_password.button_update')" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Registration-->
<AuthContent name="sign-up" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_registration.title') }}</h1>
<h2>{{ $t('page_registration.subtitle') }}</h2>
<ValidationObserver @submit.prevent="signUp" ref="sign_up" 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="register.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>{{ $t('page_registration.label_name') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Full Name" rules="required"
v-slot="{ errors }">
<input v-model="register.name" :placeholder="$t('page_registration.placeholder_name')" type="text"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_pass') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Your New Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password" :placeholder="$t('page_registration.placeholder_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>{{ $t('page_registration.label_confirm_pass') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Your Password"
rules="required" v-slot="{ errors }">
<input v-model="register.password_confirmation" :placeholder="$t('page_registration.placeholder_confirm_pass')"
type="password" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton icon="chevron-right" :text="$t('page_registration.button_create_account')" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
<span class="additional-link">{{ $t('page_registration.have_an_account') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Password reset link sended-->
<AuthContent name="password-reset-link-sended" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.pass_sennded_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_sennded_subtitle') }}</h2>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
</AuthContent>
<!--Password reset successfully-->
<AuthContent name="password-reset-successfully" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.pass_reseted_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_reseted_subtitle') }}</h2>
<AuthButton icon="chevron-right" @click.native="goToAuthPage('log-in')" :text="$t('page_forgotten_password.pass_reseted_signin')"/>
</AuthContent>
</AuthContentWrapper>
</template>
<script>
import AuthContentWrapper from '@/components/VueFileManagerComponents/Auth/AuthContentWrapper'
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import AuthContent from '@/components/VueFileManagerComponents/Auth/AuthContent'
import AuthButton from '@/components/VueFileManagerComponents/Auth/AuthButton'
import {required} from 'vee-validate/dist/rules'
import {mapGetters} from 'vuex'
import axios from 'axios'
export default {
name: 'Auth',
components: {
AuthContentWrapper,
ValidationProvider,
ValidationObserver,
AuthContent,
AuthButton,
required,
},
computed: {
...mapGetters(['config']),
},
watch: {
loginEmail(val) {
this.recoverEmail = val
}
},
data() {
return {
isLoading: false,
checkedAccount: undefined,
loginPassword: '',
loginEmail: '',
recoverEmail: '',
recoverPassword: {
token: undefined,
email: '',
newPassword: '',
newPasswordConfirm: '',
},
register: {
name: '',
email: '',
password: '',
password_confirmation: '',
},
}
},
methods: {
goToAuthPage(slug) {
this.$refs.auth.$children.forEach(page => {
// Hide current step
page.isVisible = false
if (page.$props.name === slug) {
// Go to next step
page.isVisible = true
}
})
},
async logIn() {
// Validate fields
const isValid = await this.$refs.log_in.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get verify account
axios
.post(this.$store.getters.api + '/user/check', {
email: this.loginEmail,
})
.then(response => {
// End loading
this.isLoading = false
this.checkedAccount = response.data
this.goToAuthPage('sign-in')
})
.catch(error => {
if (error.response.status == 404) {
this.$refs.log_in.setErrors({
'E-Mail': [error.response.data.message]
});
}
// End loading
this.isLoading = false
})
},
async singIn() {
// Validate fields
const isValid = await this.$refs.sign_in.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user token
axios
.post(this.$store.getters.api + '/user/login', {
email: this.loginEmail,
password: this.loginPassword,
})
.then(() => {
// End loading
this.isLoading = false
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
})
.catch(error => {
if (error.response.status == 400) {
this.$refs.sign_in.setErrors({
'User Password': [this.$t('validation_errors.incorrect_password')]
});
}
// End loading
this.isLoading = false
})
},
async forgottenPassword() {
// Validate fields
const isValid = await this.$refs.forgotten_password.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user reset link
axios
.post(this.$store.getters.api + '/password/email', {
email: this.recoverEmail
})
.then(() => {
// End loading
this.isLoading = false
this.goToAuthPage('password-reset-link-sended')
}).catch(error => {
if (error.response.status == 422) {
this.$refs.forgotten_password.setErrors({
'E-Mail': error.response.data.message
});
}
// End loading
this.isLoading = false
})
},
async createNewPassword() {
// Validate fields
const isValid = await this.$refs.create_new_password.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user reset link
axios
.post(this.$store.getters.api + '/password/reset', {
email: this.recoverPassword.email,
token: this.recoverPassword.token,
password: this.recoverPassword.newPassword,
password_confirmation: this.recoverPassword.newPasswordConfirm,
})
.then(() => {
// End loading
this.isLoading = false
this.goToAuthPage('password-reset-successfully')
})
.catch(error => {
if (error.response.status == 422) {
if (error.response.data.error) {
this.$refs.create_new_password.setErrors({
'E-Mail': error.response.data.error
});
}
if (error.response.data.errors['password']) {
this.$refs.create_new_password.setErrors({
'New Password': error.response.data.errors['password']
});
}
}
// End loading
this.isLoading = false
})
},
async signUp() {
// Validate fields
const isValid = await this.$refs.sign_up.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user token
axios
.post(this.$store.getters.api + '/user/register', this.register)
.then(() => {
// End loading
this.isLoading = false
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
})
.catch(error => {
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
})
}
},
mounted() {
// Check if user try to get reset page
let pathname = location.pathname.split('/')[1]
let token = location.search.split('token=')[1]
if (pathname === this.$t('routes.create_new_password')) {
this.recoverPassword.token = token
this.goToAuthPage('create-new-password')
} else {
this.goToAuthPage('log-in')
}
}
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
@import '@assets/vue-file-manager/_forms';
.auth-form {
text-align: center;
max-width: 600px;
padding: 25px 20px;
display: table-cell;
vertical-align: middle;
.user-avatar {
width: 100px;
height: 100px;
object-fit: cover;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);
}
.logo {
width: 120px;
margin-bottom: 20px;
}
h1 {
@include font-size(34);
font-weight: 800;
line-height: 1.2;
margin-bottom: 2px;
color: $text;
}
h2 {
@include font-size(23);
font-weight: 500;
margin-bottom: 50px;
color: $text;
}
.block-form {
margin-left: auto;
margin-right: auto;
.block-wrapper label {
text-align: right;
}
}
}
@media only screen and (min-width: 690px) and (max-width: 960px) {
.auth-form {
padding-left: 20%;
padding-right: 20%;
}
}
@media only screen and (max-width: 690px) {
.auth-form {
width: 100%;
h1 {
@include font-size(30);
}
h2 {
@include font-size(21);
}
}
}
@media (prefers-color-scheme: dark) {
.auth-form {
h1, h2, .additional-link {
color: $dark_mode_text_primary;
}
}
}
</style>
@@ -26,7 +26,10 @@
},
methods: {
goHome() {
if (this.isSmallAppSize) events.$emit('show:sidebar')
if (this.isSmallAppSize) {
events.$emit('show:sidebar')
this.$router.push({name: 'Files'})
}
}
}
}
@@ -1,11 +1,12 @@
<template>
<transition name="sidebar">
<div id="sidebar" v-if="isVisibleSidebar || ! isSmallAppSize">
<div id="sidebar" v-if="app && (isVisibleSidebar || ! isSmallAppSize)">
<!--User Headline-->
<UserHeadline/>
<div v-if="app" class="content-scroller">
<!--Content-->
<div class="content-scroller">
<!--Locations-->
<div class="menu-list-wrapper">
@@ -63,6 +64,7 @@
<!--Storage Size Info-->
<StorageSize v-if="config.storageLimit"/>
<!--Mobile logout button-->
<div v-if="isSmallAppSize" class="log-out-button">
<ButtonBase @click.native="$store.dispatch('logOut')" button-style="danger">{{ $t('context_menu.log_out') }}</ButtonBase>
</div>
@@ -12,7 +12,11 @@
<transition name="user-menu">
<div class="user-menu" v-if="isOpenedMenu">
<ul class="menu-options" id="menu-options-list" @click="closeMenu">
<li class="menu-option" @click="$goToView('user-settings')">{{ $t('context_menu.profile_settings') }}</li>
<li class="menu-option">
<router-link :to="{name: 'Profile'}">
{{ $t('context_menu.profile_settings') }}
</router-link>
</li>
<li class="menu-option" @click="$store.dispatch('logOut')">{{ $t('context_menu.log_out') }}</li>
</ul>
</div>
@@ -43,7 +47,7 @@
// If is mobile, then go to user settings page, else, open menu
if ( this.isSmallAppSize ) {
this.$goToView('user-settings')
this.$router.push({name: 'Profile'})
} else {
this.isOpenedMenu = !this.isOpenedMenu
@@ -147,6 +151,11 @@
width: 100%;
color: $text;
a {
text-decoration: none;
color: $text;
}
&:hover {
background: $light_background;
color: $theme;
-6
View File
@@ -6,12 +6,6 @@ import axios from 'axios'
const Helpers = {
install(Vue) {
Vue.prototype.$goToView = function(view) {
events.$emit('show:content')
this.$store.commit('SET_CURRENT_VIEW', view)
}
Vue.prototype.$updateText = debounce(function (route, name, value) {
if (value === '') return
+2 -2
View File
@@ -4,7 +4,7 @@ import VueRouter from 'vue-router'
import router from './router'
import i18n from './i18n/index.js'
import App from './App.vue'
import store from './store/index'
import store from './store'
import Helpers from './helpers'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
@@ -72,8 +72,8 @@ Vue.config.productionTip = false
var vueFileManager = new Vue({
i18n,
router,
store,
router,
data: {
config,
},
+58 -7
View File
@@ -1,10 +1,14 @@
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store'
import Index from './views/Index'
import SignUp from './views/SignUp'
import ForgottenPassword from './views/ForgottenPassword'
//import ForgottenPassword from './views/ForgottenPassword'
import Index from './views/Auth/SignIn'
import SignUp from './views/Auth/SignUp'
import ForgottenPassword from './views/Auth/ForgottenPassword'
import CreateNewPassword from './views/Auth/CreateNewPassword'
import Files from './views/Files'
import Profile from './views/Profile'
Vue.use(Router)
@@ -12,25 +16,53 @@ const router = new Router({
mode: 'history',
routes: [
{
name: 'index',
name: 'SignIn',
path: '/',
component: Index,
meta: {
requiresAuth: false
},
},
{
name: 'SignUp',
path: '/sign-up',
component: SignUp,
meta: {
requiresAuth: false
},
},
{
name: 'ForgottenPassword',
path: '/forgotten-password',
component: ForgottenPassword,
meta: {
requiresAuth: false
},
},
/*{
{
name: 'CreateNewPassword',
path: '/create-new-password',
component: CreateNewPassword,
},*/
meta: {
requiresAuth: false
},
},
{
name: 'Files',
path: '/files',
component: Files,
meta: {
requiresAuth: true
},
},
{
name: 'Profile',
path: '/profile',
component: Profile,
meta: {
requiresAuth: true
},
},
],
scrollBehavior(to, from, savedPosition) {
@@ -39,6 +71,25 @@ const router = new Router({
} else {
return {x: 0, y: 0}
}
},
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if ( ! store.getters.isLogged || ! config.hasAuthCookie) {
next({
name: 'SignIn',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
-5
View File
@@ -1,5 +1,4 @@
const defaultState = {
currentView: 'files',
appSize: undefined,
config: undefined,
}
@@ -10,15 +9,11 @@ const mutations = {
SET_CONFIG(state, config) {
state.config = config
},
SET_CURRENT_VIEW(state, view) {
state.currentView = view
},
SET_APP_WIDTH(state, scale) {
state.appSize = scale
},
}
const getters = {
currentView: state => state.currentView,
appSize: state => state.appSize,
api: state => state.config.api,
config: state => state.config,
+5 -4
View File
@@ -1,6 +1,7 @@
import axios from 'axios'
import {events} from '@/bus'
import i18n from '@/i18n/index.js'
import router from '@/router'
const defaultState = {
fileInfoPanelVisible: localStorage.getItem('file_info_visibility') == 'true' || false,
@@ -22,8 +23,8 @@ const actions = {
events.$emit('show:content')
// Go to files view
if (context.getters.currentView !== 'files') {
context.commit('SET_CURRENT_VIEW', 'files')
if (router.currentRoute.name !== 'Files') {
router.push({name: 'Files'})
}
context.commit('LOADING_STATE', true)
@@ -72,8 +73,8 @@ const actions = {
events.$emit('show:content')
// Go to files view
if (context.getters.currentView !== 'files') {
context.commit('SET_CURRENT_VIEW', 'files')
if (router.currentRoute.name !== 'Files') {
router.push({name: 'Files'})
}
if (! back) context.commit('FLUSH_BROWSER_HISTORY')
+6 -1
View File
@@ -1,11 +1,13 @@
import axios from 'axios'
import {events} from '@/bus'
import i18n from '@/i18n/index.js'
import router from '@/router'
const defaultState = {
authorized: undefined,
app: undefined,
}
const actions = {
getAppData: ({commit, dispatch, getters}) => {
@@ -29,7 +31,8 @@ const actions = {
// Commit Remove Access Token from vuex storage
commit('DESTROY_DATA')
commit('SET_CURRENT_VIEW', 'files')
router.push({name: 'SignIn'})
})
},
addToFavourites: (context, folder) => {
@@ -85,6 +88,7 @@ const actions = {
},
}
const mutations = {
RETRIEVE_APP_DATA(state, app) {
state.app = app
@@ -132,6 +136,7 @@ const mutations = {
})
}
}
const getters = {
isLogged: state => state.authorized,
isGuest: state => ! state.authorized,
@@ -0,0 +1,177 @@
<template>
<AuthContentWrapper ref="auth">
<!--Create new password-->
<AuthContent name="create-new-password" :visible="true">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_create_password.title') }}</h1>
<h2>{{ $t('page_create_password.subtitle') }}</h2>
<ValidationObserver @submit.prevent="createNewPassword" ref="create_new_password" v-slot="{ invalid }"
tag="form" class="form block-form create-new-password">
<div class="block-wrapper">
<label>{{ $t('page_create_password.label_email') }}</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="E-Mail" rules="required"
v-slot="{ errors }">
<input v-model="recoverPassword.email" :placeholder="$t('page_login.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>{{ $t('page_create_password.label_new_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="New Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPassword" :placeholder="$t('page_create_password.label_new_pass')" type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div class="block-wrapper">
<label>{{ $t('page_create_password.label_confirm_pass') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="Confirm Password"
rules="required" v-slot="{ errors }">
<input v-model="recoverPassword.newPasswordConfirm" :placeholder="$t('page_create_password.label_confirm_pass')"
type="password" :class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
</div>
<div>
<AuthButton icon="chevron-right" :text="$t('page_create_password.button_update')" :loading="isLoading" :disabled="isLoading"/>
</div>
</ValidationObserver>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }}
<router-link :to="{name: 'SignIn'}">
{{ $t('page_forgotten_password.password_remember_button') }}
</router-link>
</span>
</AuthContent>
<!--Password reset successfully-->
<AuthContent name="password-reset-successfully" :visible="false">
<img class="logo" :src="config.app_logo" :alt="config.app_name">
<h1>{{ $t('page_forgotten_password.pass_reseted_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_reseted_subtitle') }}</h2>
<router-link :to="{name: 'SignIn'}">
<AuthButton icon="chevron-right" :text="$t('page_forgotten_password.pass_reseted_signin')"/>
</router-link>
</AuthContent>
</AuthContentWrapper>
</template>
<script>
import AuthContentWrapper from '@/components/VueFileManagerComponents/Auth/AuthContentWrapper'
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import AuthContent from '@/components/VueFileManagerComponents/Auth/AuthContent'
import AuthButton from '@/components/VueFileManagerComponents/Auth/AuthButton'
import {required} from 'vee-validate/dist/rules'
import {mapGetters} from 'vuex'
import axios from 'axios'
export default {
name: 'CreateNewPassword',
components: {
AuthContentWrapper,
ValidationProvider,
ValidationObserver,
AuthContent,
AuthButton,
required,
},
computed: {
...mapGetters(['config']),
},
data() {
return {
isLoading: false,
recoverPassword: {
token: undefined,
email: '',
newPassword: '',
newPasswordConfirm: '',
},
}
},
methods: {
goToAuthPage(slug) {
this.$refs.auth.$children.forEach(page => {
// Hide current step
page.isVisible = false
if (page.$props.name === slug) {
// Go to next step
page.isVisible = true
}
})
},
async createNewPassword() {
// Validate fields
const isValid = await this.$refs.create_new_password.validate();
if (!isValid) return;
// Start loading
this.isLoading = true
// Send request to get user reset link
axios
.post(this.$store.getters.api + '/password/reset', {
email: this.recoverPassword.email,
token: this.recoverPassword.token,
password: this.recoverPassword.newPassword,
password_confirmation: this.recoverPassword.newPasswordConfirm,
})
.then(() => {
// End loading
this.isLoading = false
this.goToAuthPage('password-reset-successfully')
})
.catch(error => {
if (error.response.status == 422) {
if (error.response.data.error) {
this.$refs.create_new_password.setErrors({
'E-Mail': error.response.data.error
});
}
if (error.response.data.errors['password']) {
this.$refs.create_new_password.setErrors({
'New Password': error.response.data.errors['password']
});
}
}
// End loading
this.isLoading = false
})
},
},
mounted() {
// Get token
this.recoverPassword.token = this.$route.params.token
}
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
@import '@assets/vue-file-manager/_forms';
@import '@assets/vue-file-manager/_auth';
</style>
@@ -19,7 +19,11 @@
<AuthButton icon="chevron-right" :text="$t('page_forgotten_password.button_get_link')" :loading="isLoading" :disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }}
<router-link :to="{name: 'SignIn'}">
{{ $t('page_forgotten_password.password_remember_button') }}
</router-link>
</span>
</AuthContent>
<!--Password reset link sended-->
@@ -28,7 +32,11 @@
<h1>{{ $t('page_forgotten_password.pass_sennded_title') }}</h1>
<h2>{{ $t('page_forgotten_password.pass_sennded_subtitle') }}</h2>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
<span class="additional-link">{{ $t('page_forgotten_password.password_remember_text') }}
<router-link :to="{name: 'SignIn'}">
{{ $t('page_forgotten_password.password_remember_button') }}
</router-link>
</span>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -43,7 +51,7 @@
import axios from 'axios'
export default {
name: 'Auth',
name: 'ForgottenPassword',
components: {
AuthContentWrapper,
ValidationProvider,
@@ -88,7 +96,7 @@
// Send request to get user reset link
axios
.post(this.$store.getters.api + '/password/email', {
.post('/api/password/email', {
email: this.recoverEmail
})
.then(() => {
@@ -116,83 +124,5 @@
<style scoped lang="scss">
@import "@assets/app.scss";
@import '@assets/vue-file-manager/_forms';
.auth-form {
text-align: center;
max-width: 600px;
padding: 25px 20px;
display: table-cell;
vertical-align: middle;
.user-avatar {
width: 100px;
height: 100px;
object-fit: cover;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);
}
.logo {
width: 120px;
margin-bottom: 20px;
}
h1 {
@include font-size(34);
font-weight: 800;
line-height: 1.2;
margin-bottom: 2px;
color: $text;
}
h2 {
@include font-size(23);
font-weight: 500;
margin-bottom: 50px;
color: $text;
}
.block-form {
margin-left: auto;
margin-right: auto;
.block-wrapper label {
text-align: right;
}
}
}
@media only screen and (min-width: 690px) and (max-width: 960px) {
.auth-form {
padding-left: 20%;
padding-right: 20%;
}
}
@media only screen and (max-width: 690px) {
.auth-form {
width: 100%;
h1 {
@include font-size(30);
}
h2 {
@include font-size(21);
}
}
}
@media (prefers-color-scheme: dark) {
.auth-form {
h1, h2, .additional-link {
color: $dark_mode_text_primary;
}
}
}
@import '@assets/vue-file-manager/_auth';
</style>
@@ -16,11 +16,15 @@
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" :text="$t('page_login.button_next')" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_login.button_next')" :loading="isLoading"
:disabled="isLoading"/>
</ValidationObserver>
<span v-if="config.userRegistration" class="additional-link">{{ $t('page_login.registration_text') }} <b
@click="goToAuthPage('sign-up')">{{ $t('page_login.registration_button') }}</b></span>
<span v-if="config.userRegistration" class="additional-link">{{ $t('page_login.registration_text') }}
<router-link :to="{name: 'SignUp'}">
{{ $t('page_login.registration_button') }}
</router-link>
</span>
</AuthContent>
<!--Log in By Password-->
@@ -36,15 +40,21 @@
class="form inline-form">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="User Password" rules="required"
v-slot="{ errors }">
<input v-model="loginPassword" :placeholder="$t('page_sign_in.placeholder_password')" type="password"
<input v-model="loginPassword" :placeholder="$t('page_sign_in.placeholder_password')"
type="password"
:class="{'is-error': errors[0]}"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider>
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')" :loading="isLoading" :disabled="isLoading"/>
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')" :loading="isLoading"
:disabled="isLoading"/>
</ValidationObserver>
<span class="additional-link">{{ $t('page_sign_in.password_reset_text') }} <b @click="goToAuthPage('forgotten-password')">{{ $t('page_sign_in.password_reset_button') }}</b></span>
<span class="additional-link">{{ $t('page_sign_in.password_reset_text') }}
<router-link :to="{name: 'ForgottenPassword'}">
{{ $t('page_sign_in.password_reset_button') }}
</router-link>
</span>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -59,7 +69,7 @@
import axios from 'axios'
export default {
name: 'Auth',
name: 'SignIn',
components: {
AuthContentWrapper,
ValidationProvider,
@@ -75,8 +85,8 @@
return {
isLoading: false,
checkedAccount: undefined,
loginPassword: '',
loginEmail: '',
loginPassword: 'vuefilemanager',
loginEmail: 'howdy@hi5ve.digital',
}
},
methods: {
@@ -106,7 +116,7 @@
// Send request to get verify account
axios
.post(this.$store.getters.api + '/user/check', {
.post('/api/user/check', {
email: this.loginEmail,
})
.then(response => {
@@ -115,6 +125,8 @@
this.isLoading = false
this.checkedAccount = response.data
// Show sign in password page
this.goToAuthPage('sign-in')
})
.catch(error => {
@@ -142,7 +154,7 @@
// Send request to get user token
axios
.post(this.$store.getters.api + '/user/login', {
.post('/api/user/login', {
email: this.loginEmail,
password: this.loginPassword,
})
@@ -153,6 +165,9 @@
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
// Go to files page
this.$router.push({name: 'Files'})
})
.catch(error => {
@@ -167,90 +182,12 @@
this.isLoading = false
})
},
}
},
}
</script>
<style scoped lang="scss">
@import "@assets/app.scss";
@import '@assets/vue-file-manager/_forms';
.auth-form {
text-align: center;
max-width: 600px;
padding: 25px 20px;
display: table-cell;
vertical-align: middle;
.user-avatar {
width: 100px;
height: 100px;
object-fit: cover;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);
}
.logo {
width: 120px;
margin-bottom: 20px;
}
h1 {
@include font-size(34);
font-weight: 800;
line-height: 1.2;
margin-bottom: 2px;
color: $text;
}
h2 {
@include font-size(23);
font-weight: 500;
margin-bottom: 50px;
color: $text;
}
.block-form {
margin-left: auto;
margin-right: auto;
.block-wrapper label {
text-align: right;
}
}
}
@media only screen and (min-width: 690px) and (max-width: 960px) {
.auth-form {
padding-left: 20%;
padding-right: 20%;
}
}
@media only screen and (max-width: 690px) {
.auth-form {
width: 100%;
h1 {
@include font-size(30);
}
h2 {
@include font-size(21);
}
}
}
@media (prefers-color-scheme: dark) {
.auth-form {
h1, h2, .additional-link {
color: $dark_mode_text_primary;
}
}
}
@import '@assets/vue-file-manager/_auth';
</style>
@@ -55,7 +55,11 @@
</div>
</ValidationObserver>
<span class="additional-link">{{ $t('page_registration.have_an_account') }} <b @click="goToAuthPage('log-in')">{{ $t('page_forgotten_password.password_remember_button') }}</b></span>
<span class="additional-link">{{ $t('page_registration.have_an_account') }}
<router-link :to="{name: 'SignIn'}">
{{ $t('page_forgotten_password.password_remember_button') }}
</router-link>
</span>
</AuthContent>
</AuthContentWrapper>
@@ -71,7 +75,7 @@
import axios from 'axios'
export default {
name: 'Auth',
name: 'SignUp',
components: {
AuthContentWrapper,
ValidationProvider,
@@ -107,7 +111,7 @@
// Send request to get user token
axios
.post(this.$store.getters.api + '/user/register', this.register)
.post('/api/user/register', this.register)
.then(() => {
// End loading
@@ -115,6 +119,9 @@
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
// Go to files page
this.$router.push({name: 'Files'})
})
.catch(error => {
@@ -146,83 +153,5 @@
<style scoped lang="scss">
@import "@assets/app.scss";
@import '@assets/vue-file-manager/_forms';
.auth-form {
text-align: center;
max-width: 600px;
padding: 25px 20px;
display: table-cell;
vertical-align: middle;
.user-avatar {
width: 100px;
height: 100px;
object-fit: cover;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);
}
.logo {
width: 120px;
margin-bottom: 20px;
}
h1 {
@include font-size(34);
font-weight: 800;
line-height: 1.2;
margin-bottom: 2px;
color: $text;
}
h2 {
@include font-size(23);
font-weight: 500;
margin-bottom: 50px;
color: $text;
}
.block-form {
margin-left: auto;
margin-right: auto;
.block-wrapper label {
text-align: right;
}
}
}
@media only screen and (min-width: 690px) and (max-width: 960px) {
.auth-form {
padding-left: 20%;
padding-right: 20%;
}
}
@media only screen and (max-width: 690px) {
.auth-form {
width: 100%;
h1 {
@include font-size(30);
}
h2 {
@include font-size(21);
}
}
}
@media (prefers-color-scheme: dark) {
.auth-form {
h1, h2, .additional-link {
color: $dark_mode_text_primary;
}
}
}
@import '@assets/vue-file-manager/_auth';
</style>
+10
View File
@@ -5,3 +5,13 @@
@import 'vue-file-manager/_variables';
@import 'vue-file-manager/_mixins';
//@import 'vue-file-manager/_forms';
#application-wrapper {
display: flex;
height: 100%;
#content {
position: relative;
width: 100%;
}
}
+85
View File
@@ -0,0 +1,85 @@
.auth-form {
text-align: center;
max-width: 600px;
padding: 25px 20px;
display: table-cell;
vertical-align: middle;
.additional-link {
a {
font-weight: 700;
text-decoration: none;
}
}
.user-avatar {
width: 100px;
height: 100px;
object-fit: cover;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(25, 54, 60, 0.2);
}
.logo {
width: 120px;
margin-bottom: 20px;
}
h1 {
@include font-size(34);
font-weight: 800;
line-height: 1.2;
margin-bottom: 2px;
color: $text;
}
h2 {
@include font-size(23);
font-weight: 500;
margin-bottom: 50px;
color: $text;
}
.block-form {
margin-left: auto;
margin-right: auto;
.block-wrapper label {
text-align: right;
}
}
}
@media only screen and (min-width: 690px) and (max-width: 960px) {
.auth-form {
padding-left: 20%;
padding-right: 20%;
}
}
@media only screen and (max-width: 690px) {
.auth-form {
width: 100%;
h1 {
@include font-size(30);
}
h2 {
@include font-size(21);
}
}
}
@media (prefers-color-scheme: dark) {
.auth-form {
h1, h2, .additional-link {
color: $dark_mode_text_primary;
}
}
}