Passed API error while creating URLs to display proper error messages

This commit is contained in:
Alejandro Celaya 2020-12-21 20:53:31 +01:00
parent 18d417e78c
commit 54b1ab12cd
3 changed files with 32 additions and 16 deletions

View file

@ -9,6 +9,7 @@ import { ShortUrlCreation } from '../reducers/shortUrlCreation';
import { StateFlagTimeout } from '../../utils/helpers/hooks';
import { Result } from '../../utils/Result';
import './CreateShortUrlResult.scss';
import { isInvalidArgumentError } from '../../utils/services/types';
export interface CreateShortUrlResultProps extends ShortUrlCreation {
resetCreateShortUrl: () => void;
@ -16,7 +17,7 @@ export interface CreateShortUrlResultProps extends ShortUrlCreation {
}
const CreateShortUrlResult = (useStateFlagTimeout: StateFlagTimeout) => (
{ error, result, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps,
{ error, errorData, result, resetCreateShortUrl, canBeClosed = false }: CreateShortUrlResultProps,
) => {
const [ showCopyTooltip, setShowCopyTooltip ] = useStateFlagTimeout();
@ -28,7 +29,8 @@ const CreateShortUrlResult = (useStateFlagTimeout: StateFlagTimeout) => (
return (
<Result type="error" className="mt-3">
{canBeClosed && <FontAwesomeIcon icon={closeIcon} className="float-right pointer" onClick={resetCreateShortUrl} />}
An error occurred while creating the URL :(
{errorData?.detail ?? 'An error occurred while creating the URL :('}
{isInvalidArgumentError(errorData) && <p>Invalid elements: [{errorData.invalidElements.join(', ')}]</p>}
</Result>
);
}

View file

@ -3,6 +3,7 @@ import { GetState } from '../../container/types';
import { ShortUrl, ShortUrlData } from '../data';
import { buildReducer, buildActionCreator } from '../../utils/helpers/redux';
import { ShlinkApiClientBuilder } from '../../utils/services/ShlinkApiClientBuilder';
import { ProblemDetailsError } from '../../utils/services/types';
/* eslint-disable padding-line-between-statements */
export const CREATE_SHORT_URL_START = 'shlink/createShortUrl/CREATE_SHORT_URL_START';
@ -15,21 +16,26 @@ export interface ShortUrlCreation {
result: ShortUrl | null;
saving: boolean;
error: boolean;
errorData?: ProblemDetailsError;
}
export interface CreateShortUrlAction extends Action<string> {
result: ShortUrl;
}
export interface CreateShortUrlFailedAction extends Action<string> {
errorData?: ProblemDetailsError;
}
const initialState: ShortUrlCreation = {
result: null,
saving: false,
error: false,
};
export default buildReducer<ShortUrlCreation, CreateShortUrlAction>({
export default buildReducer<ShortUrlCreation, CreateShortUrlAction & CreateShortUrlFailedAction>({
[CREATE_SHORT_URL_START]: (state) => ({ ...state, saving: true, error: false }),
[CREATE_SHORT_URL_ERROR]: (state) => ({ ...state, saving: false, error: true }),
[CREATE_SHORT_URL_ERROR]: (state, { errorData }) => ({ ...state, saving: false, error: true, errorData }),
[CREATE_SHORT_URL]: (_, { result }) => ({ result, saving: false, error: false }),
[RESET_CREATE_SHORT_URL]: () => initialState,
}, initialState);
@ -46,7 +52,7 @@ export const createShortUrl = (buildShlinkApiClient: ShlinkApiClientBuilder) =>
dispatch<CreateShortUrlAction>({ type: CREATE_SHORT_URL, result });
} catch (e) {
dispatch({ type: CREATE_SHORT_URL_ERROR });
dispatch<CreateShortUrlFailedAction>({ type: CREATE_SHORT_URL_ERROR, errorData: e.response?.data });
throw e;
}

View file

@ -25,12 +25,12 @@ interface ShlinkTagsStats {
export interface ShlinkTags {
tags: string[];
stats?: ShlinkTagsStats[]; // Is only optional in old Shlink versions
stats?: ShlinkTagsStats[]; // Is only optional in Shlink older than v2.2
}
export interface ShlinkTagsResponse {
data: string[];
stats?: ShlinkTagsStats[]; // Is only optional in old Shlink versions
stats?: ShlinkTagsStats[]; // Is only optional in Shlink older than v2.2
}
export interface ShlinkPaginator {
@ -41,7 +41,7 @@ export interface ShlinkPaginator {
export interface ShlinkVisits {
data: Visit[];
pagination?: ShlinkPaginator; // Is only optional in old Shlink versions
pagination: ShlinkPaginator;
}
export interface ShlinkVisitsOverview {
@ -60,14 +60,6 @@ export interface ShlinkShortUrlMeta extends ShortUrlMeta {
longUrl?: string;
}
export interface ProblemDetailsError {
type: string;
detail: string;
title: string;
status: number;
[extraProps: string]: any;
}
export interface ShlinkDomain {
domain: string;
isDefault: boolean;
@ -76,3 +68,19 @@ export interface ShlinkDomain {
export interface ShlinkDomainsResponse {
data: ShlinkDomain[];
}
export interface ProblemDetailsError {
type: string;
detail: string;
title: string;
status: number;
[extraProps: string]: any;
}
export interface InvalidArgumentError extends ProblemDetailsError {
type: 'INVALID_ARGUMENT';
invalidElements: string[];
}
export const isInvalidArgumentError = (error?: ProblemDetailsError): error is InvalidArgumentError =>
error?.type === 'INVALID_ARGUMENT';