Added meaningful error messages for the rest of API calls

This commit is contained in:
Alejandro Celaya
2020-12-21 23:41:50 +01:00
parent ee95d5a1b7
commit 4c3772d5c8
13 changed files with 82 additions and 33 deletions

View File

@@ -12,6 +12,7 @@ import { formatIsoDate } from '../utils/helpers/date';
import { ShlinkVisitsParams } from '../utils/services/types';
import { DateInterval, DateRange, intervalToDateRange } from '../utils/dates/types';
import { Result } from '../utils/Result';
import { ShlinkApiError } from '../api/ShlinkApiError';
import SortableBarGraph from './helpers/SortableBarGraph';
import GraphCard from './helpers/GraphCard';
import LineChartCard from './helpers/LineChartCard';
@@ -83,7 +84,7 @@ const VisitsStats: FC<VisitsStatsProps> = ({ children, visitsInfo, getVisits, ca
return !subPath ? `${baseUrl}${query}` : `${baseUrl}${subPath}${query}`;
};
const { visits, loading, loadingLarge, error, progress } = visitsInfo;
const { visits, loading, loadingLarge, error, errorData, progress } = visitsInfo;
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
() => processStatsFromVisits(normalizedVisits),
@@ -131,7 +132,11 @@ const VisitsStats: FC<VisitsStatsProps> = ({ children, visitsInfo, getVisits, ca
}
if (error) {
return <Result type="error">An error occurred while loading visits :(</Result>;
return (
<Result type="error">
<ShlinkApiError errorData={errorData} fallbackMessage="An error occurred while loading visits :(" />
</Result>
);
}
if (isEmpty(visits)) {

View File

@@ -1,7 +1,7 @@
import { flatten, prop, range, splitEvery } from 'ramda';
import { Action, Dispatch } from 'redux';
import { ShlinkPaginator, ShlinkVisits } from '../../utils/services/types';
import { Visit } from '../types';
import { Visit, VisitsLoadFailedAction } from '../types';
const ITEMS_PER_PAGE = 5000;
const PARALLEL_REQUESTS_COUNT = 4;
@@ -71,6 +71,6 @@ export const getVisitsWithLoader = async <T extends Action<string> & { visits: V
dispatch({ ...extraFinishActionData, visits, type: actionMap.finish });
} catch (e) {
dispatch({ type: actionMap.error });
dispatch<VisitsLoadFailedAction>({ type: actionMap.error, errorData: e.response?.data });
}
};

View File

@@ -1,6 +1,6 @@
import { Action, Dispatch } from 'redux';
import { shortUrlMatches } from '../../short-urls/helpers';
import { Visit, VisitsInfo, VisitsLoadProgressChangedAction } from '../types';
import { Visit, VisitsInfo, VisitsLoadFailedAction, VisitsLoadProgressChangedAction } from '../types';
import { ShortUrlIdentifier } from '../../short-urls/data';
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder';
@@ -24,7 +24,10 @@ interface ShortUrlVisitsAction extends Action<string>, ShortUrlIdentifier {
visits: Visit[];
}
type ShortUrlVisitsCombinedAction = ShortUrlVisitsAction & VisitsLoadProgressChangedAction & CreateVisitsAction;
type ShortUrlVisitsCombinedAction = ShortUrlVisitsAction
& VisitsLoadProgressChangedAction
& CreateVisitsAction
& VisitsLoadFailedAction;
const initialState: ShortUrlVisits = {
visits: [],
@@ -39,7 +42,7 @@ const initialState: ShortUrlVisits = {
export default buildReducer<ShortUrlVisits, ShortUrlVisitsCombinedAction>({
[GET_SHORT_URL_VISITS_START]: () => ({ ...initialState, loading: true }),
[GET_SHORT_URL_VISITS_ERROR]: () => ({ ...initialState, error: true }),
[GET_SHORT_URL_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }),
[GET_SHORT_URL_VISITS]: (_, { visits, shortCode, domain }) => ({
...initialState,
visits,

View File

@@ -1,5 +1,5 @@
import { Action, Dispatch } from 'redux';
import { Visit, VisitsInfo, VisitsLoadProgressChangedAction } from '../types';
import { Visit, VisitsInfo, VisitsLoadFailedAction, VisitsLoadProgressChangedAction } from '../types';
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder';
import { GetState } from '../../container/types';
@@ -24,6 +24,11 @@ export interface TagVisitsAction extends Action<string> {
tag: string;
}
type TagsVisitsCombinedAction = TagVisitsAction
& VisitsLoadProgressChangedAction
& CreateVisitsAction
& VisitsLoadFailedAction;
const initialState: TagVisits = {
visits: [],
tag: '',
@@ -34,9 +39,9 @@ const initialState: TagVisits = {
progress: 0,
};
export default buildReducer<TagVisits, TagVisitsAction & VisitsLoadProgressChangedAction & CreateVisitsAction>({
export default buildReducer<TagVisits, TagsVisitsCombinedAction>({
[GET_TAG_VISITS_START]: () => ({ ...initialState, loading: true }),
[GET_TAG_VISITS_ERROR]: () => ({ ...initialState, error: true }),
[GET_TAG_VISITS_ERROR]: (_, { errorData }) => ({ ...initialState, error: true, errorData }),
[GET_TAG_VISITS]: (_, { visits, tag }) => ({ ...initialState, visits, tag }),
[GET_TAG_VISITS_LARGE]: (state) => ({ ...state, loadingLarge: true }),
[GET_TAG_VISITS_CANCEL]: (state) => ({ ...state, cancelLoad: true }),

View File

@@ -1,11 +1,13 @@
import { Action } from 'redux';
import { ShortUrl } from '../../short-urls/data';
import { ProblemDetailsError } from '../../utils/services/types';
export interface VisitsInfo {
visits: Visit[];
loading: boolean;
loadingLarge: boolean;
error: boolean;
errorData?: ProblemDetailsError;
progress: number;
cancelLoad: boolean;
}
@@ -14,6 +16,10 @@ export interface VisitsLoadProgressChangedAction extends Action<string> {
progress: number;
}
export interface VisitsLoadFailedAction extends Action<string> {
errorData?: ProblemDetailsError;
}
interface VisitLocation {
countryCode: string | null;
countryName: string | null;