Browse Source

add locale setter. introduce model setup page

pull/1/head
Jonathan Cobb 4 years ago
parent
commit
7426503bbf
7 changed files with 180 additions and 20 deletions
  1. +2
    -0
      src/_helpers/router.js
  2. +1
    -0
      src/_helpers/util.js
  3. +11
    -0
      src/_services/user.service.js
  4. +58
    -8
      src/_store/account.module.js
  5. +16
    -2
      src/_store/system.module.js
  6. +42
    -0
      src/admin/ModelSetupPage.vue
  7. +50
    -10
      src/app/App.vue

+ 2
- 0
src/_helpers/router.js View File

@@ -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
- 0
src/_helpers/util.js View File

@@ -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
- 0
src/_services/user.service.js View File

@@ -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));
} }


+ 58
- 8
src/_store/account.module.js View File

@@ -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) {


+ 16
- 2
src/_store/system.module.js View File

@@ -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 = [];


+ 42
- 0
src/admin/ModelSetupPage.vue View File

@@ -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>

+ 50
- 10
src/app/App.vue View File

@@ -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>

Loading…
Cancel
Save