@@ -3,6 +3,7 @@ import Router from 'vue-router'; | |||||
import HomePage from '../account/HomePage' | import HomePage from '../account/HomePage' | ||||
import ActivationPage from '../auth/ActivationPage' | import ActivationPage from '../auth/ActivationPage' | ||||
import ModelSetupPage from '../admin/ModelSetupPage' | |||||
import RegisterPage from '../auth/RegisterPage' | import RegisterPage from '../auth/RegisterPage' | ||||
import LoginPage from '../auth/LoginPage' | import LoginPage from '../auth/LoginPage' | ||||
import MultifactorAuthPage from '../auth/MultifactorAuthPage' | import MultifactorAuthPage from '../auth/MultifactorAuthPage' | ||||
@@ -74,6 +75,7 @@ export const router = new Router({ | |||||
{ path: '/admin/accounts', component: AccountsPage }, | { path: '/admin/accounts', component: AccountsPage }, | ||||
{ path: '/admin/accounts/:uuid', component: ProfilePage }, | { path: '/admin/accounts/:uuid', component: ProfilePage }, | ||||
{ path: '/admin/model', component: ModelSetupPage }, | |||||
// otherwise redirect to home | // otherwise redirect to home | ||||
{ path: '*', redirect: '/' } | { path: '*', redirect: '/' } | ||||
@@ -1,6 +1,7 @@ | |||||
let landingPage = null; | let landingPage = null; | ||||
export const util = { | export const util = { | ||||
USER_KEY: 'user', | |||||
getLandingPage: function () { return landingPage; }, | getLandingPage: function () { return landingPage; }, | ||||
setLandingPage: function (page) { landingPage = page; }, | setLandingPage: function (page) { landingPage = page; }, | ||||
resetLandingPage: function () { landingPage = null; }, | resetLandingPage: function () { landingPage = null; }, | ||||
@@ -11,6 +11,7 @@ export const userService = { | |||||
updatePolicyById, | updatePolicyById, | ||||
addPolicyContactById, | addPolicyContactById, | ||||
removePolicyContactByUuid, | removePolicyContactByUuid, | ||||
setLocale, | |||||
update, | update, | ||||
delete: _delete, | delete: _delete, | ||||
approveAction, | approveAction, | ||||
@@ -104,6 +105,16 @@ function denyAction(id, code, messages, errors) { | |||||
return fetch(`${config.apiUrl}/auth/deny/${code}`, util.postWithAuth()).then(util.handleCrudResponse(messages, errors)); | return fetch(`${config.apiUrl}/auth/deny/${code}`, util.postWithAuth()).then(util.handleCrudResponse(messages, errors)); | ||||
} | } | ||||
function setLocale(locale, messages, errors) { | |||||
const user = util.currentUser(); | |||||
if (user != null && user.token) { | |||||
return fetch(`${config.apiUrl}/me/locale/${locale}`, util.postWithAuth()).then(util.handleCrudResponse(messages, errors)); | |||||
} else { | |||||
const loc = {locale: locale}; | |||||
return Promise.resolve(loc); | |||||
} | |||||
} | |||||
function update(user, messages, errors) { | function update(user, messages, errors) { | ||||
return fetch(`${config.apiUrl}/users/${user.uuid}`, util.postWithAuth(user)).then(util.handleCrudResponse(messages, errors)); | return fetch(`${config.apiUrl}/users/${user.uuid}`, util.postWithAuth(user)).then(util.handleCrudResponse(messages, errors)); | ||||
} | } | ||||
@@ -1,16 +1,14 @@ | |||||
import { userService, systemService } from '../_services'; | import { userService, systemService } from '../_services'; | ||||
import { router, util } from '../_helpers'; | import { router, util } from '../_helpers'; | ||||
// todo: why can't we import currentUser from api-util and use that here? | |||||
// when I try to do that, webpack succeeds but then an error occurs loading any page, with the | |||||
// error message "_helpers.currentUser is not defined" | |||||
// const user = JSON.parse(localStorage.getItem('user')); | |||||
const user = util.currentUser(); | const user = util.currentUser(); | ||||
const defaultStatus = { | const defaultStatus = { | ||||
loggingIn: false, | loggingIn: false, | ||||
loggedIn: false, | loggedIn: false, | ||||
registering: false, | registering: false, | ||||
updating: false, | |||||
settingLocale: false, | |||||
activating: false, | activating: false, | ||||
approving: false, | approving: false, | ||||
denying: false, | denying: false, | ||||
@@ -22,12 +20,13 @@ const state = { | |||||
activated: null, | activated: null, | ||||
status: Object.assign({}, defaultStatus, {loggedIn: (user != null)}), | status: Object.assign({}, defaultStatus, {loggedIn: (user != null)}), | ||||
user: user, | user: user, | ||||
actionStatus: {} | |||||
actionStatus: {}, | |||||
locale: user == null ? 'detect' : (typeof user.locale !== 'undefined' && user.locale !== null ? user.locale : 'detect') | |||||
}; | }; | ||||
const actions = { | const actions = { | ||||
refreshUser({ commit }) { | refreshUser({ commit }) { | ||||
commit('refreshUser', JSON.parse(localStorage.getItem('user'))); | |||||
commit('refreshUser', JSON.parse(localStorage.getItem(util.USER_KEY))); | |||||
}, | }, | ||||
login({ dispatch, commit }, { user, messages, errors }) { | login({ dispatch, commit }, { user, messages, errors }) { | ||||
commit('loginRequest', { name: user.name }); | commit('loginRequest', { name: user.name }); | ||||
@@ -75,6 +74,15 @@ const actions = { | |||||
} | } | ||||
); | ); | ||||
}, | }, | ||||
setLocale({ commit }, {locale, messages, errors}) { | |||||
state.locale = locale; | |||||
commit('setLocaleRequest', locale); | |||||
userService.setLocale(locale, messages, errors) | |||||
.then( | |||||
user => commit('setLocaleSuccess', user), | |||||
error => commit('setLocaleFailure', error) | |||||
); | |||||
}, | |||||
update({ dispatch, commit }, {user, messages, errors}) { | update({ dispatch, commit }, {user, messages, errors}) { | ||||
commit('updateRequest', user); | commit('updateRequest', user); | ||||
userService.update(user, messages, errors) | userService.update(user, messages, errors) | ||||
@@ -152,8 +160,9 @@ const mutations = { | |||||
} else { | } else { | ||||
state.status = {}; | state.status = {}; | ||||
} | } | ||||
localStorage.setItem('user', JSON.stringify(user)); | |||||
localStorage.setItem(util.USER_KEY, JSON.stringify(user)); | |||||
state.user = user; | state.user = user; | ||||
state.locale = (typeof user.locale !== 'undefined' && user.locale !== null ? user.locale : state.locale); | |||||
}, | }, | ||||
loginFailure(state) { | loginFailure(state) { | ||||
state.status.loggingIn = false; | state.status.loggingIn = false; | ||||
@@ -171,13 +180,54 @@ const mutations = { | |||||
}, | }, | ||||
registerSuccess(state, user) { | registerSuccess(state, user) { | ||||
state.status.registering = false; | state.status.registering = false; | ||||
localStorage.setItem(util.USER_KEY, JSON.stringify(user)); | |||||
state.user = user; | state.user = user; | ||||
state.locale = (typeof user.locale !== 'undefined' && user.locale !== null ? user.locale : state.locale); | |||||
}, | }, | ||||
registerFailure(state) { | registerFailure(state) { | ||||
state.status.registering = false; | state.status.registering = false; | ||||
state.status = {}; | state.status = {}; | ||||
}, | }, | ||||
setLocaleRequest(state, locale) { | |||||
console.log('setLocaleRequest: setting locale='+locale); | |||||
state.status.settingLocale = true; | |||||
state.locale = locale; | |||||
const user = util.currentUser(); | |||||
if (user === null) { | |||||
localStorage.setItem(util.USER_KEY, JSON.stringify({locale: locale})); | |||||
} else { | |||||
user.locale = locale; | |||||
localStorage.setItem(util.USER_KEY, JSON.stringify(user)); | |||||
} | |||||
state.user = user; | |||||
}, | |||||
setLocaleSuccess(state, user) { | |||||
console.log('setLocaleSuccess: user='+JSON.stringify(user)); | |||||
state.locale = ''+state.locale; | |||||
state.status.settingLocale = false; | |||||
}, | |||||
setLocaleFailure(state) { | |||||
console.log('setLocaleFailure'); | |||||
state.status.settingLocale = false; | |||||
state.status = {}; | |||||
}, | |||||
updateRequest(state, user) { | |||||
state.status.updating = true; | |||||
state.user = user; | |||||
}, | |||||
updateSuccess(state, user) { | |||||
state.status.updating = false; | |||||
localStorage.setItem(util.USER_KEY, JSON.stringify(user)); | |||||
state.user = user; | |||||
state.locale = (typeof user.locale !== 'undefined' && user.locale !== null ? user.locale : state.locale); | |||||
}, | |||||
updateFailure(state) { | |||||
state.status.updating = false; | |||||
state.status = {}; | |||||
}, | |||||
approveActionRequest(state) { | approveActionRequest(state) { | ||||
state.status.approving = true; | state.status.approving = true; | ||||
state.actionStatus = { requesting: true, type: 'approve' }; | state.actionStatus = { requesting: true, type: 'approve' }; | ||||
@@ -216,7 +266,7 @@ const mutations = { | |||||
state.user = user; | state.user = user; | ||||
} else if (user.multifactorAuth) { | } else if (user.multifactorAuth) { | ||||
state.user.multifactorAuth = user.multifactorAuth; | state.user.multifactorAuth = user.multifactorAuth; | ||||
localStorage.setItem('user', JSON.stringify(user)); | |||||
localStorage.setItem(util.USER_KEY, JSON.stringify(user)); | |||||
} | } | ||||
}, | }, | ||||
sendAuthenticatorCodeFailure(state, error) { | sendAuthenticatorCodeFailure(state, error) { | ||||
@@ -1,12 +1,15 @@ | |||||
import { systemService } from '../_services'; | import { systemService } from '../_services'; | ||||
import { account } from "./account.module"; | import { account } from "./account.module"; | ||||
import {router} from "../_helpers"; | |||||
import { router } from "../_helpers"; | |||||
const state = { | const state = { | ||||
configs: { | configs: { | ||||
allowRegistration: false, | allowRegistration: false, | ||||
paymentsEnabled: false, | paymentsEnabled: false, | ||||
sageLauncher: false | |||||
sageLauncher: false, | |||||
cloudDrivers: [], | |||||
entityClasses: [], | |||||
locales: ['en_US'] | |||||
}, | }, | ||||
status: { activating: false }, | status: { activating: false }, | ||||
activated: null, | activated: null, | ||||
@@ -26,6 +29,7 @@ const state = { | |||||
return {count: parseInt(ms), units: ''}; | return {count: parseInt(ms), units: ''}; | ||||
} | } | ||||
}, | }, | ||||
messageGroupsLoaded: [], | |||||
countries: [], | countries: [], | ||||
locales: [], | locales: [], | ||||
timezones: [], | timezones: [], | ||||
@@ -74,6 +78,11 @@ const actions = { | |||||
error => commit('loadMessagesFailure', error) | error => commit('loadMessagesFailure', error) | ||||
); | ); | ||||
}, | }, | ||||
reloadMessages({ commit }, locale) { | |||||
for (let i=0; i<this.messageGroupsLoaded.length; i++) { | |||||
this.loadMessages(this.messageGroupsLoaded[i], locale); | |||||
} | |||||
}, | |||||
loadTimezones({ commit }) { | loadTimezones({ commit }) { | ||||
commit('loadTimezonesRequest'); | commit('loadTimezonesRequest'); | ||||
systemService.loadTimezones().then( | systemService.loadTimezones().then( | ||||
@@ -141,6 +150,10 @@ const getters = { | |||||
href: '/admin/users', | href: '/admin/users', | ||||
title: messages.label_menu_admin_users, | title: messages.label_menu_admin_users, | ||||
icon: messages.label_menu_admin_users_icon | icon: messages.label_menu_admin_users_icon | ||||
}, { | |||||
href: '/admin/model', | |||||
title: messages.label_menu_admin_model, | |||||
icon: messages.label_menu_admin_model_icon | |||||
}] | }] | ||||
}; | }; | ||||
menu.splice(1, 0, admin_menu); | menu.splice(1, 0, admin_menu); | ||||
@@ -213,6 +226,7 @@ const mutations = { | |||||
loadMessagesRequest(state) {}, | loadMessagesRequest(state) {}, | ||||
loadMessagesSuccess(state, {group, messages}) { | loadMessagesSuccess(state, {group, messages}) { | ||||
// console.log('loadMessages (group='+group+'), messages='+JSON.stringify(messages)); | // console.log('loadMessages (group='+group+'), messages='+JSON.stringify(messages)); | ||||
if (state.messageGroupsLoaded.indexOf(group) === -1) state.messageGroupsLoaded.push(group); | |||||
state.messages = new Proxy(Object.assign({}, state.messages, messages), messageNotFoundHandler); | state.messages = new Proxy(Object.assign({}, state.messages, messages), messageNotFoundHandler); | ||||
if (messages.country_codes) { | if (messages.country_codes) { | ||||
const countries = []; | const countries = []; | ||||
@@ -0,0 +1,42 @@ | |||||
<template> | |||||
<div> | |||||
<h2>{{messages.form_title_model_setup}}</h2> | |||||
<form @submit.prevent="setupModel"> | |||||
<div class="form-group"> | |||||
<label for="configType">{{messages.field_label_entity_type}}</label> | |||||
<select v-model="configType" name="configType" class="form-control"> | |||||
<option v-for="opt in system.configs.entityClasses" v-bind:value="opt">{{opt}}</option> | |||||
</select> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import { mapState, mapActions, mapGetters } from 'vuex' | |||||
export default { | |||||
data() { | |||||
return { | |||||
configType: system.configs.entityClasses[0] | |||||
}; | |||||
}, | |||||
computed: { | |||||
...mapState('system', ['configs', 'messages']) | |||||
}, | |||||
created () { | |||||
const locale = 'detect'; | |||||
this.loadSystemConfigs(); // determine if we can show the registration link | |||||
this.loadMessages('pre_auth', locale); | |||||
this.loadMessages('post_auth', locale); | |||||
}, | |||||
methods: { | |||||
// ...mapActions('system', ['loadIsActivated', 'activate']), | |||||
...mapActions('system', ['loadIsActivated', 'loadSystemConfigs', 'loadMessages', 'loadTimezones']), | |||||
setupModel(e) { | |||||
console.log('setupModel called'); | |||||
} | |||||
} | |||||
}; | |||||
</script> |
@@ -9,25 +9,55 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div> | |||||
<hr/> | |||||
<button @click="toggleLocaleView()">{{messages.button_label_set_locale}}</button> | |||||
<div v-if="showLocaleSelector"> | |||||
<div class="form-group"> | |||||
<label for="locale">{{messages.field_label_locale}}</label> | |||||
<select v-if="this.locales && this.locales.length > 0" v-model="selectedLocale" name="locale" class="form-control"> | |||||
<option value="detect">{{messages['locale_detect']}}</option> | |||||
<option v-for="opt in this.locales" v-bind:value="opt">{{messages['locale_'+opt]}}</option> | |||||
</select> | |||||
<div v-if="errors.has('locale')" class="invalid-feedback">{{ errors.first('locale') }}</div> | |||||
</div> | |||||
<button @click="updateLocale" class="btn btn-primary">{{messages.button_label_set_locale}}</button> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import { mapState, mapGetters, mapActions } from 'vuex' | import { mapState, mapGetters, mapActions } from 'vuex' | ||||
import { util } from '../_helpers' | |||||
export default { | export default { | ||||
name: 'app', | name: 'app', | ||||
data() { | |||||
return { | |||||
showLocaleSelector: false, | |||||
selectedLocale: 'detect' | |||||
} | |||||
}, | |||||
computed: { | computed: { | ||||
...mapState('account', ['status']), | |||||
...mapState('account', ['status', 'user', 'locale']), | |||||
...mapState('system', ['activated', 'configs', 'messages', 'menu']), | ...mapState('system', ['activated', 'configs', 'messages', 'menu']), | ||||
...mapGetters('system', ['menu']), | ...mapGetters('system', ['menu']), | ||||
...mapState({ | ...mapState({ | ||||
alert: state => state.alert | alert: state => state.alert | ||||
}) | |||||
}), | |||||
locales () { return this.configs.locales; } | |||||
}, | }, | ||||
methods: { | methods: { | ||||
...mapActions({ clearAlert: 'alert/clear' }), | ...mapActions({ clearAlert: 'alert/clear' }), | ||||
...mapActions('system', ['loadIsActivated', 'loadSystemConfigs', 'loadMessages', 'loadTimezones']) | |||||
...mapActions('account', ['setLocale']), | |||||
...mapActions('system', ['loadIsActivated', 'loadSystemConfigs', 'loadMessages', 'reloadMessages', 'loadTimezones']), | |||||
toggleLocaleView() { this.showLocaleSelector = !this.showLocaleSelector; }, | |||||
updateLocale() { | |||||
if (this.selectedLocale) { | |||||
this.setLocale({locale: this.selectedLocale, messages: this.messages, errors: this.errors}); | |||||
} | |||||
} | |||||
}, | }, | ||||
watch: { | watch: { | ||||
$route (to, from){ | $route (to, from){ | ||||
@@ -35,20 +65,30 @@ export default { | |||||
this.clearAlert(); | this.clearAlert(); | ||||
}, | }, | ||||
activated (active) { | activated (active) { | ||||
console.log('App.watch.activated: received: '+active); | |||||
if (!active) this.$router.replace('/activate'); | if (!active) this.$router.replace('/activate'); | ||||
}, | |||||
user (u) { | |||||
if (typeof u === 'undefined' || u === null || typeof u.locale === 'undefined' || u.locale === null) { | |||||
return; | |||||
} | |||||
this.selectedLocale = u.locale; | |||||
this.reloadMessages(this.selectedLocale); | |||||
}, | |||||
locale (loc) { | |||||
this.selectedLocale = loc; | |||||
this.reloadMessages(this.selectedLocale) | |||||
} | } | ||||
}, | }, | ||||
created() { | created() { | ||||
const user = util.currentUser(); | |||||
this.selectedLocale = (user !== null && typeof user.locale !== 'undefined' && user.locale !== null ? user.locale : 'detect'); | |||||
this.loadIsActivated(); | this.loadIsActivated(); | ||||
this.loadSystemConfigs(); // determine if we can show the registration link | this.loadSystemConfigs(); // determine if we can show the registration link | ||||
// todo: allow user to choose locale | |||||
const locale = 'detect'; | |||||
this.loadMessages('pre_auth', locale); | |||||
this.loadMessages('countries', locale); | |||||
this.loadMessages('timezones', locale); | |||||
this.loadTimezones(); | this.loadTimezones(); | ||||
this.loadMessages('pre_auth', this.selectedLocale); | |||||
this.loadMessages('countries', this.selectedLocale); | |||||
this.loadMessages('timezones', this.selectedLocale); | |||||
} | } | ||||
}; | }; | ||||
</script> | </script> |