Commit 13710df5 authored by Tobinsk's avatar Tobinsk
Browse files

Merge branch '10-error-handling' into 'master'

Resolve "error handling"

Closes #10

See merge request !14
parents 9f8a71df cecdc1eb
......@@ -3,6 +3,7 @@
<div id="app">
<Navbar/>
<div class="content">
<Error></Error>
<router-view/>
</div>
</div>
......@@ -11,9 +12,10 @@
<script>
import Navbar from "@/components/Navbar";
import {mapActions} from 'vuex';
import Error from "@/components/Error";
export default {
components: {Navbar},
components: {Error, Navbar},
methods: {
...mapActions('provider', ['list']),
},
......
<template><div></div></template>
<script>
import {mapGetters} from 'vuex'
export default {
name: "Error",
watch: {
'getLatest': function (value) {
this.makeToast(value)
}
},
computed: {
...mapGetters('error', ['getLatest'])
},
methods: {
/***
* Make a bootsrap toast to inform about global errors
* @param error {MetagridError}
**/
makeToast(error) {
this.$bvToast.toast(error.message, {
title: error.title,
variant: this.toVariant(error.type),
autoHideDelay: 8000,
appendToast: true,
});
},
/**
* Transform a ErrorType to a bootstrap variant
* @param type {string}
* @return {string|*}
*/
toVariant(type) {
switch (type) {
case 'error':
return 'danger';
default:
return type;
}
}
}
}
</script>
import {Module} from 'vuex';
import {api, Concordance, Pagination, Person, SearchQuery} from '@/store';
import {api, Concordance, MetagridError, Pagination, Person, SearchQuery} from '@/store';
import {Actions, Getters, Mutations} from '@/store/concordance/type';
import {TmpPagination} from '@/store/proposal';
import {ErrorType} from '@/store/error';
// State of the concordance
export interface ConcordanceState {
......@@ -170,7 +171,7 @@ const concordance: Module<ConcordanceState, any> = {
* @param pagination
* @param state
*/
async [Actions.LIST]({ commit, state }, pagination: TmpPagination) {
async [Actions.LIST]({ commit, state, rootState }, pagination: TmpPagination) {
commit(Mutations.START_LOAD);
if(typeof pagination === "undefined") {
pagination = {
......@@ -187,7 +188,15 @@ const concordance: Module<ConcordanceState, any> = {
params.push(`from=${pagination.from}`);
params.push(`size=${pagination.size}`);
const data = await fetch(`${api}/v3/concordances/search?${params.join('&')}`).
then(d => d.json());
then(d => d.json()).catch((error) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t fetch list of concordances from server.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw error;
});
commit(Mutations.LIST, data.concordances);
commit(Mutations.FINISH_LOAD);
return data.meta.total;
......@@ -211,7 +220,15 @@ const concordance: Module<ConcordanceState, any> = {
*/
async [Actions.DESTROY]({commit}, id: string) {
await fetch(`${api}/v3/concordances/${id}`,
{method: 'DELETE' });
{method: 'DELETE' }).catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t delete concordances.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.CLEAR_EDIT_LIST)
},
......@@ -230,7 +247,16 @@ const concordance: Module<ConcordanceState, any> = {
'Content-Type': 'application/json'
},
})
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t merge concordances.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.CLEAR_EDIT_LIST);
commit(Mutations.APPEND, concordance)
},
......@@ -243,7 +269,16 @@ const concordance: Module<ConcordanceState, any> = {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then(r => r.json());
}).then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t update concordance.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.UPDATE, con);
}
}
......
import {Module} from 'vuex';
import {Getters, Mutations} from '@/store/error/type';
import {MetagridError} from '@/store';
// State of the error
export interface ErrorState {
errors: MetagridError[];
}
// SearchQueryKeys
export enum ErrorType {
info = 'info',
warn = 'warn',
error = 'error',
}
const error: Module<ErrorState, any> = {
namespaced: true,
state: {
errors: []
},
getters: {
/**
* Get all errors as a list
* @param state
*/
[Getters.LIST]: state => {
return state.errors
},
/**
* Just returns the newest error
* @param state
*/
[Getters.GET_LATEST]: state => {
return state.errors[state.errors.length -1]
},
},
mutations: {
/**
* Add an error to the stack
* @param state
* @param error
*/
[Mutations.ADD]: (state, error: MetagridError) => {
state.errors.push(error)
},
}
}
export default error;
export const Getters = {
LIST: 'list',
GET_LATEST: 'getLatest',
};
export const Mutations = {
ADD: 'add',
}
......@@ -4,6 +4,7 @@ import proposal from '@/store/proposal';
import concordance from '@/store/concordance';
import match from '@/store/match';
import provider from '@/store/provider';
import error, {ErrorType} from '@/store/error';
Vue.use(Vuex);
......@@ -84,11 +85,19 @@ export interface Match {
parameters: MatchParameter[];
}
// proposals interfaace
export interface MatchProposal {
base: Concordance;
proposals: Concordance[];
}
// metagridError interface for global error handling
export interface MetagridError {
title: string;
message: string;
type: ErrorType;
}
// SearchQueryKeys
enum SearchQueryKeys {
query = 'query',
......@@ -100,9 +109,11 @@ enum SearchQueryKeys {
export default new Vuex.Store( {
modules: {
error: error,
proposal: proposal,
concordance: concordance,
match: match,
provider: provider,
}
});
import {Module} from 'vuex';
import {api, Match, Pagination} from '@/store';
import {api, Match, MetagridError, Pagination} from '@/store';
import {Actions, Getters, Mutations} from '@/store/match/type';
import {ErrorType} from '@/store/error';
interface MatchState {
loading: boolean;
......@@ -113,7 +114,16 @@ const match: Module<MatchState, any> = {
async [Actions.LIST]({commit}, pagination: Pagination) {
commit(Mutations.START_LOAD);
const m = await fetch(`${api}/v3/matches`)
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t fetch list of matchings.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.LIST, m.matches);
commit(Mutations.FINISH_LOAD);
return m.meta.total;
......@@ -136,7 +146,16 @@ const match: Module<MatchState, any> = {
let match = state.list.find((m: any) => m.id === id);
if(typeof match === 'undefined') {
match = await fetch(`${api}/v3/matches/${id}`)
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t fetch matching from server.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
}
commit(Mutations.SET, match);
commit(Mutations.FINISH_LOAD);
......@@ -152,7 +171,16 @@ const match: Module<MatchState, any> = {
'Content-Type': 'application/json'
},
})
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t save matching.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.INSERT, m);
commit(Mutations.FINISH_LOAD);
return m;
......
import {api, Pagination, MatchProposal, Match} from '@/store';
import {api, Pagination, MatchProposal, Match, MetagridError} from '@/store';
import { Module} from "vuex"
import {Actions, Getters, Mutations} from '@/store/proposal/type';
import {ErrorType} from '@/store/error';
export interface TmpPagination {
from: number;
......@@ -113,7 +114,16 @@ const proposal: Module<ProposalState, any> = {
params.push(`from=${pagination.from}`);
params.push(`size=${pagination.size}`);
const proposals = await fetch(`${api}/v3/matches/${state.id}/proposals?${params.join("&")}`)
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t fetch proposals from server.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.FINISH_LOAD);
commit(Mutations.LIST, proposals);
// todo: return total
......@@ -138,7 +148,16 @@ const proposal: Module<ProposalState, any> = {
'Content-Type': 'application/json'
},
})
.then(r => r.json());
.then(r => r.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t test the matching.',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err;
});
commit(Mutations.LIST, proposals);
commit(Mutations.FINISH_LOAD);
},
......
import {Module} from 'vuex';
import {api, Provider} from '@/store';
import {api, MetagridError, Provider} from '@/store';
import {Actions, Getters, Mutations} from '@/store/provider/type';
import {ErrorType} from '@/store/error';
interface ProviderState {
list: Provider[];
......@@ -31,9 +32,18 @@ const provider: Module<ProviderState, any> = {
* Load all providers
* @param commit
*/
async [Actions.LIST]({commit}) {
async [Actions.LIST]({commit, rootState}) {
const data = await fetch(`${api}/v3/providers`).
then(d => d.json());
then(d => d.json())
.catch((err) => {
const metagridError: MetagridError = {
title: "Network error",
message: 'Can\'t fetch list of provider. Network error',
type: ErrorType.error
}
commit('error/add', metagridError, { root: true });
throw err
});
commit(Mutations.LIST, data.providers);
},
}
......
......@@ -152,8 +152,6 @@ describe('Test editing of a concordance', function () {
cy.get('body').should('have.class','edit-box-open')
cy.get('.edit-list').should('be.visible')
cy.get('.edit-list .action-header button:nth-child(2)').click();
});
})
})
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment