From 98f5d3f39ba5c0902ba4f606b0e2d986fe6b4520 Mon Sep 17 00:00:00 2001 From: Tobias Date: Thu, 11 Apr 2019 16:18:18 +0200 Subject: [PATCH] added user repo and group management working now --- package-lock.json | 13 +++++ package.json | 3 +- src/api/Repository.js | 29 +++++++++- src/api/RepositoryFactory.js | 2 + src/api/groupRepository.js | 2 +- src/api/index.ts | 8 +++ src/api/userRepository.js | 19 +++++++ src/components/Group.vue | 105 +++++++++++------------------------ src/components/User.vue | 100 +++++++++++++++++++++++++++++++-- src/main.ts | 2 + src/store.ts | 50 +++++++++++------ 11 files changed, 236 insertions(+), 97 deletions(-) create mode 100644 src/api/userRepository.js diff --git a/package-lock.json b/package-lock.json index 0ba11df..687b23d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11914,6 +11914,11 @@ "util.promisify": "~1.0.0" } }, + "sweetalert2": { + "version": "7.33.1", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-7.33.1.tgz", + "integrity": "sha512-69KYtyhtxejFG0HDb8aVhAwbpAWPSTZwaL5vxDHgojErD2KeFxTmRgmkbiLtMC8UdTFXRmvTPtZTF4459MUb7w==" + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -12972,6 +12977,14 @@ "loader-utils": "^1.0.2" } }, + "vue-sweetalert2": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vue-sweetalert2/-/vue-sweetalert2-1.6.4.tgz", + "integrity": "sha512-MsVPeie+DjyP/rTPHlGxOsnR10DCXq/6xUiMZtBURZq8111Q/U6c8xJ0do55Yj99odf7ru2J2eJz6GeGs8i0kA==", + "requires": { + "sweetalert2": "7.x" + } + }, "vue-template-compiler": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.8.tgz", diff --git a/package.json b/package.json index ac835b7..7120fe0 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "vue-i18n": "^8.9.0", "vue-property-decorator": "^7.0.0", "vue-router": "^3.0.1", - "vuejs-logger": "1.5.3", + "vue-sweetalert2": "^1.6.4", + "vuejs-logger": "^1.5.3", "vuex": "^3.0.1", "vuex-persistedstate": "^2.5.4", "vuex-typex": "^3.1.4" diff --git a/src/api/Repository.js b/src/api/Repository.js index 35ceacb..3982bad 100644 --- a/src/api/Repository.js +++ b/src/api/Repository.js @@ -7,6 +7,33 @@ import store from "@/store"; const baseDomain = "http://localhost:5443"; const API_URL = `${baseDomain}/api/v1`; -export default axios.create({ +const api = axios.create({ baseURL: API_URL, headers: { Authorization: `Bearer ${store.state.access_token}` }, }); + +api.interceptors.response.use(function (response) { + return response; +}, function (error) { + if (401 === error.response.status) { + Vue.swal({ + title: "Session Expired", + text: "Your token/session has expired. Would you like to be redirected to the login page?", + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "Yes", + }).then( (result) => { + if(result.value) { + console.log("redirect to login!"); + window.location = '/login'; + } else { + console.log("redirect to home!"); + window.location = '/'; + } + }); + } else { + return Promise.reject(error); + } +}); + +export default api; diff --git a/src/api/RepositoryFactory.js b/src/api/RepositoryFactory.js index ae7ed2d..412b417 100644 --- a/src/api/RepositoryFactory.js +++ b/src/api/RepositoryFactory.js @@ -1,9 +1,11 @@ // RepositoryFactory.js import GroupRepository from "./groupRepository"; +import UserRepository from "./userRepository"; const repositories = { group: GroupRepository, + user: UserRepository, }; export const RepositoryFactory = { diff --git a/src/api/groupRepository.js b/src/api/groupRepository.js index 315bbf9..7415eb9 100644 --- a/src/api/groupRepository.js +++ b/src/api/groupRepository.js @@ -5,7 +5,7 @@ import Repository from "./Repository"; const resource = "/group"; export default { - get() { + getGroups() { return Repository.get(`${resource}`); }, diff --git a/src/api/index.ts b/src/api/index.ts index 916a76e..80d0b84 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -49,6 +49,14 @@ export function createUser(jwt: any, userData: any) { return axios.post(`${API_URL}/v1/user`, userData, { headers: { Authorization: `Bearer ${jwt}` } }); } +export function fetchUserGroups(jwt: any) { + return axios.get(`${API_URL}/v1/group`, { headers: { Authorization: `Bearer ${jwt}` } }); +} + +export function fetchUserGroup(jwt: any, groupId: any) { + return axios.get(`${API_URL}/v1/group/${groupId}`, { headers: { Authorization: `Bearer ${jwt}` } }); +} + export function fetchProfile(jwt: any) { Vue.$log.debug("JWT: "+ jwt); return axios.get(`${API_URL}/v1/user/profile`, { headers: { Authorization: `Bearer ${jwt}` } }); diff --git a/src/api/userRepository.js b/src/api/userRepository.js new file mode 100644 index 0000000..0451002 --- /dev/null +++ b/src/api/userRepository.js @@ -0,0 +1,19 @@ +// groupRepository.js + +import Repository from "./Repository"; + +const resource = "/user"; + +export default { + getUsers() { + return Repository.get(`${resource}`); + }, + + getUser(userId) { + return Repository.get(`${resource}/${userId}`); + }, + + createUser(userData) { + return Repository.post(`${resource}`, userData); + }, +}; diff --git a/src/components/Group.vue b/src/components/Group.vue index b3efc23..2418e65 100644 --- a/src/components/Group.vue +++ b/src/components/Group.vue @@ -30,39 +30,18 @@ - -
- - - - - - - - - - - -
{{col}} -
-
{{row[col]}}
- -
-

{{ errorMsg }}

Add Group

- +

Name is: {{ group.name }}

Multiline message is:

{{ group.description }}


- - + + + @@ -79,28 +58,19 @@ data () { return { isLoading: false, - errorMsg: '', groups: [], - group: {}, - currentPage: 1, - elementsPerPage: 3, - ascending: false, + errorMsg: '', + group: {name:'', description:''}, sortColumn: '', - rows: [ - { id: 1, name: "Chandler Bing", phone: '305-917-1301', profession: 'IT Manager' }, - { id: 2, name: "Ross Geller", phone: '210-684-8953', profession: 'Paleontologist' }, - { id: 3, name: "Rachel Green", phone: '765-338-0312', profession: 'Waitress'}, - { id: 4, name: "Monica Geller", phone: '714-541-3336', profession: 'Head Chef' }, - { id: 5, name: "Joey Tribbiani", phone: '972-297-6037', profession: 'Actor' }, - { id: 6, name: "Phoebe Buffay", phone: '760-318-8376', profession: 'Masseuse' } - ], + currentPage: 1, + elementsPerPage: 5, }; }, methods: { - fetch(){ + fetch() { this.isLoading = true; // const { data } = await GroupRepository.get(); - GroupRepository.get() + GroupRepository.getGroups() .then(response => { this.groups = response.data; this.isLoading = false; @@ -108,6 +78,17 @@ }); }, + get_group_rows() { + var start = (this.currentPage-1) * this.elementsPerPage; + var end = start + this.elementsPerPage; + return this.groups.slice(start, end); + }, + num_group_pages() { + return Math.ceil(this.groups.length / this.elementsPerPage); + }, + change_page(page) { + this.currentPage = page; + }, sortTable(col) { if (this.sortColumn === col) { this.ascending = !this.ascending; @@ -118,7 +99,7 @@ var ascending = this.ascending; - this.rows.sort(function(a, b) { + this.groups.sort(function(a, b) { if (a[col] > b[col]) { return ascending ? 1 : -1 } else if (a[col] < b[col]) { @@ -127,44 +108,24 @@ return 0; }) }, - num_pages() { - return Math.ceil(this.rows.length / this.elementsPerPage); + createGroup(){ + this.$log.info("Creating new group..."); + GroupRepository.createGroup(this.group); + this.fetch(); }, - num_group_pages() { - return Math.ceil(this.groups.length / this.elementsPerPage); - }, - get_rows() { - var start = (this.currentPage-1) * this.elementsPerPage; - var end = start + this.elementsPerPage; - return this.rows.slice(start, end); - }, - get_group_rows() { - var start = (this.currentPage-1) * this.elementsPerPage; - var end = start + this.elementsPerPage; - return this.groups.slice(start, end); - }, - change_page(page) { - this.currentPage = page; - }, - }, - mounted () { + mounted() { this.fetch(); }, + beforeDestroy() { + }, computed: { - columns() { - if (this.rows.length === 0) { - return []; - } - return Object.keys(this.rows[0]) - }, group_columns() { if (this.groups.length === 0) { return []; } - return Object.keys(this.groups[0]) - } - + return Object.keys(this.groups[0]); + }, }, } diff --git a/src/components/User.vue b/src/components/User.vue index b360b80..b2a1864 100644 --- a/src/components/User.vue +++ b/src/components/User.vue @@ -5,6 +5,38 @@

Manage users

+
{{users}}
+ +
+ + + + + + + + + + + +
{{col}} +
+
{{row[col]}}
+ +
+ +

Add User

+ +

Name is: {{ user.first_name }}

+ +

{{ errorMsg }}

@@ -17,24 +49,80 @@ diff --git a/src/main.ts b/src/main.ts index 4395d13..03b7598 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,7 @@ import VueAxios from 'vue-axios'; import App from './App.vue'; import router from './router'; import store from './store'; +import VueSweetalert2 from 'vue-sweetalert2'; import VueCookies from 'vue-cookies'; import VueLogger from 'vuejs-logger'; import i18n from '@/plugins/i18n'; @@ -32,6 +33,7 @@ Vue.use(VueLogger, options); Vue.use(VueAxios, axios); Vue.use(FlagIcon); Vue.use(VueCookies); +Vue.use(VueSweetalert2); // setup fake backend // import { configureFakeBackend } from './helpers'; diff --git a/src/store.ts b/src/store.ts index 9596a01..b5e6c1a 100644 --- a/src/store.ts +++ b/src/store.ts @@ -4,28 +4,30 @@ import createPersistedState from 'vuex-persistedstate' // imports of AJAX functions will go here import { - fetchSurveys, - fetchSurvey, - getProviders, - saveSurveyResponse, - postNewSurvey, - authenticate, - register, - oidc_login, fetchUsers, getFreshToken, fetchProfile, + fetchSurveys, + fetchSurvey, + getProviders, + saveSurveyResponse, + postNewSurvey, + authenticate, + register, + oidc_login, fetchUsers, getFreshToken, fetchProfile, fetchUserGroups, } from '@/api'; import {isValidJwt, EventBus} from '@/utils'; +import {response} from "express"; Vue.use(Vuex); const state = { - // single source of data - surveys: [], - loginProviders: [], - currentSurvey: {}, - profile: {}, - users: [], - access_token: '', - refresh_token: '', + // single source of data + surveys: [], + loginProviders: [], + currentSurvey: {}, + profile: {}, + users: [], + userGroups: [], + access_token: '', + refresh_token: '', }; const actions = { @@ -59,6 +61,19 @@ const actions = { EventBus.$emit('failedLoadingUsers', error); }); }, + loadUserGroups(context: any) { + return fetchUserGroups(context.state.access_token) + .then((response) => { + Vue.$log.debug(response); + Vue.$log.debug(response.data); + context.commit('setUserGroups', { groups: response.data }); + EventBus.$emit('groupsLoaded', response.data); + }) + .catch((error) => { + Vue.$log.warn('Error loading user groups!', error); + EventBus.$emit('failedLoadingUserGroups', error); + }); + }, loadProfileAuthCheck(context:any){ if (!getters.isAuthenticated) { EventBus.$emit('accessTokenInvalid'); @@ -158,6 +173,9 @@ const mutations = { setUsers(sState: any, payload: any) { sState.users = payload.users; }, + setUserGroups(sState: any, payload: any) { + sState.userGroups = payload.groups; + }, setChoice(sState: any, payload: any) { const { questionId, choice } = payload; const nQuestions = sState.currentSurvey.questions.length;