Skip to content

Commit

Permalink
Handle internal server error on upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Kadrian committed May 14, 2024
1 parent cbdf7bb commit 91ee257
Show file tree
Hide file tree
Showing 13 changed files with 50 additions and 81 deletions.
2 changes: 1 addition & 1 deletion frontend/src/js/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { useEffect, useState } from "react";
import { useIsCacheEnabled } from "../common/feature-flags/useIsCacheEnabled";
import { clearIndexedDBCache } from "../common/helpers/indexedDBCache";
import Header from "../header/Header";
import SnackMessage from "../snack-message/SnackMessage";
import { useStartup } from "../startup/useStartup";

import { SnackMessage } from "../snack-message/SnackMessage";
import { About } from "./About";
import Content from "./Content";

Expand Down
3 changes: 1 addition & 2 deletions frontend/src/js/dataset/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
import { useLoadQueries } from "../previous-queries/list/actions";
import { queryResultReset } from "../query-runner/actions";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";
import { clearQuery, loadSavedQuery } from "../standard-query-editor/actions";
import type { StandardQueryStateT } from "../standard-query-editor/queryReducer";

Expand Down Expand Up @@ -65,7 +64,7 @@ export const useLoadDatasets = () => {
dispatch(
setMessage({
message: t("datasetSelector.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
dispatch(loadDatasets.failure(e as Error));
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/js/entity-history/LoadHistoryDropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useDispatch } from "react-redux";
import type { SelectOptionT } from "../api/types";
import { parseCSV } from "../file/csv";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";
import DropzoneWithFileInput, {
DragItemFile,
} from "../ui-components/DropzoneWithFileInput";
Expand Down Expand Up @@ -46,7 +45,7 @@ export const LoadHistoryDropzone = ({
dispatch(
setMessage({
message: t("history.load.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
return;
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/js/entity-history/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { exists } from "../common/helpers/exists";
import { useDatasetId } from "../dataset/selectors";
import { loadCSV, parseCSVWithHeaderToObj } from "../file/csv";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";

import { EntityEvent, EntityId } from "./reducer";
import { isDateColumn, isSourceColumn } from "./timeline/util";
Expand Down Expand Up @@ -302,7 +301,7 @@ export function useUpdateHistorySession() {
dispatch(
setMessage({
message: t("history.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/js/entity-history/saveAndLoad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useDispatch } from "react-redux";
import { downloadBlob } from "../common/helpers/downloadBlob";
import { toCSV } from "../file/csv";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";

import { EntityIdsStatus } from "./History";
import { LoadingPayload } from "./LoadHistoryDropzone";
Expand Down Expand Up @@ -90,7 +89,7 @@ export const useLoadHistory = ({
dispatch(
setMessage({
message: t("history.load.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
return;
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/js/external-forms/FormConfigLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { DNDType } from "../common/constants/dndTypes";
import { Language, useActiveLang } from "../localization/useActiveLang";
import type { FormConfigT } from "../previous-queries/list/reducer";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";
import Dropzone from "../ui-components/Dropzone";

import { setExternalForm } from "./actions";
Expand Down Expand Up @@ -151,7 +150,7 @@ const FormConfigLoader: FC<Props> = ({
message: t("formConfig.loadSuccess", {
label: formConfigToLoadNext.label,
}),
type: SnackMessageType.SUCCESS,
type: "success",
}),
);
},
Expand Down Expand Up @@ -179,7 +178,7 @@ const FormConfigLoader: FC<Props> = ({
dispatch(
setMessage({
message: t("formConfig.loadError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/js/preview/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { GetQueryResponseT, PreviewStatisticsResponse } from "../api/types";
import { StateT } from "../app/reducers";
import { ErrorObject } from "../common/actions/genericActions";
import { setMessage } from "../snack-message/actions";
import { SnackMessageType } from "../snack-message/reducer";
import { PreviewStateT } from "./reducer";

export type PreviewActions = ActionType<
Expand Down Expand Up @@ -106,7 +105,7 @@ export function useLoadPreviewData() {
dispatch(
setMessage({
message: t("preview.loadingError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
dispatch(loadPreview.failure({}));
Expand Down
17 changes: 8 additions & 9 deletions frontend/src/js/previous-queries/list/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
} from "../../api/types";
import { useDatasetId } from "../../dataset/selectors";
import { setMessage } from "../../snack-message/actions";
import { SnackMessageType } from "../../snack-message/reducer";

import type { FormConfigT, PreviousQueryT } from "./reducer";

Expand Down Expand Up @@ -59,7 +58,7 @@ export const useLoadQueries = () => {
dispatch(
setMessage({
message: t("previousQueries.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -97,7 +96,7 @@ export const useLoadQuery = () => {
dispatch(
setMessage({
message: t("previousQuery.loadError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -142,7 +141,7 @@ export const useUpdateQuery = () => {
dispatch(
setMessage({
message: errorMessage,
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -172,7 +171,7 @@ export const useRemoveQuery = () => {
dispatch(
setMessage({
message: t("previousQuery.deleteError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -218,7 +217,7 @@ export const useLoadFormConfigs = () => {
dispatch(
setMessage({
message: t("formConfigs.error"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -257,7 +256,7 @@ export const useLoadFormConfig = () => {
dispatch(
setMessage({
message: t("formConfig.loadError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -297,7 +296,7 @@ export const useUpdateFormConfig = () => {
dispatch(
setMessage({
message: errorMessage,
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down Expand Up @@ -328,7 +327,7 @@ export const useRemoveFormConfig = () => {
dispatch(
setMessage({
message: t("formConfig.deleteError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useDispatch, useSelector } from "react-redux";
import type { StateT } from "../../app/reducers";
import { useDatasetId } from "../../dataset/selectors";
import { setMessage } from "../../snack-message/actions";
import { SnackMessageType } from "../../snack-message/reducer";

import {
removeFolder,
Expand Down Expand Up @@ -74,7 +73,7 @@ export const useDeleteProjectItemFolder = () => {
dispatch(
setMessage({
message: t("previousQuery.retagError"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
return Promise.reject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type {
import type { StateT } from "../../app/reducers";
import IconButton from "../../button/IconButton";
import { setMessage } from "../../snack-message/actions";
import { SnackMessageType } from "../../snack-message/reducer";
import WithTooltip from "../../tooltip/WithTooltip";
import { useLoadQueries } from "../list/actions";

Expand Down Expand Up @@ -59,18 +58,20 @@ const UploadQueryResults = ({
setLoading(true);

const result = await postQueryUpload(datasetId, query);

setUploadResult(result);

loadQueries(datasetId);
} catch (e) {
if ((e as { status?: number }).status === 400) {
if (
(e as { status?: number }).status === 400 &&
"resolved" in (e as object)
) {
setUploadResult(e as UploadQueryResponseT);
} else {
dispatch(
setMessage({
message: t("uploadQueryResultsModal.uploadFailed"),
type: SnackMessageType.ERROR,
type: "error",
}),
);
}
Expand Down
68 changes: 24 additions & 44 deletions frontend/src/js/snack-message/SnackMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,36 @@
import styled from "@emotion/styled";
import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { FC, memo, useRef } from "react";
import { memo, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";

import type { StateT } from "../app/reducers";
import { useClickOutside } from "../common/helpers/useClickOutside";
import FaIcon from "../icon/FaIcon";

import tw from "tailwind-styled-components";
import { resetMessage as resetMessageAction } from "./actions";
import { SnackMessageStateT, SnackMessageType } from "./reducer";

const snackMessageTypeToColor: Record<SnackMessageType, string> = {
[SnackMessageType.ERROR]: "rgba(0, 0, 0, 0.75)",
[SnackMessageType.SUCCESS]: "rgba(12, 100, 39, 0.9)", // #0C6427
[SnackMessageType.DEFAULT]: "rgba(0, 0, 0, 0.75)",
};

const Root = styled("div")<{ type: SnackMessageType }>`
position: fixed;
z-index: 10;
bottom: 20px;
right: 20px;
background-color: ${({ type }) =>
snackMessageTypeToColor[type ?? SnackMessageType.DEFAULT]};
color: white;
display: flex;
flex-direction: row;
align-items: flex-start;
max-width: 500px;
border-radius: 5px;
import { SnackMessageStateT } from "./reducer";

const Root = tw("div")<{ $success?: boolean }>`
fixed
z-10
bottom-5
right-5
text-white
flex items-start
max-w-[500px]
rounded-lg
${({ $success }) =>
$success ? "bg-primary-500 bg-opacity-90" : "bg-black bg-opacity-75"}
`;

const Relative = styled("div")`
position: relative;
padding: 12px 40px 12px 20px;
const ClearZone = tw("div")`
absolute top-3 right-4
z-[11]
cursor-pointer
opacity-80 hover:opacity-100
`;

const ClearZone = styled("div")`
position: absolute;
top: 12px;
right: 18px;
z-index: 11;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
`;

const SnackMessage: FC = memo(function SnackMessageComponent() {
export const SnackMessage = memo(function SnackMessageComponent() {
const ref = useRef(null);
const { message, type } = useSelector<StateT, SnackMessageStateT>(
(state) => state.snackMessage,
Expand All @@ -65,17 +47,15 @@ const SnackMessage: FC = memo(function SnackMessageComponent() {
return (
<div ref={ref}>
{message && (
<Root type={type}>
<Relative>
<Root $success={type === "success"}>
<div className="relative py-3 pr-10 pl-5">
<div dangerouslySetInnerHTML={{ __html: message }} />
<ClearZone onClick={resetMessage}>
<FaIcon white large icon={faTimes} />
</ClearZone>
</Relative>
</div>
</Root>
)}
</div>
);
});

export default SnackMessage;
4 changes: 2 additions & 2 deletions frontend/src/js/snack-message/actions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ActionType, createAction } from "typesafe-actions";

import { SnackMessageType } from "./reducer";
import { SnackMessageStateT } from "./reducer";

export type SnackMessageActions = ActionType<
typeof setMessage | typeof resetMessage
>;

export const setMessage = createAction("snack-message/SET")<{
message: string | null;
type: SnackMessageType;
type: SnackMessageStateT["type"];
}>();

export const resetMessage = createAction("snack-message/RESET")();
8 changes: 2 additions & 6 deletions frontend/src/js/snack-message/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ import { Action } from "../app/actions";

import { resetMessage, setMessage } from "./actions";

export enum SnackMessageType {
ERROR = "error",
SUCCESS = "success",
DEFAULT = "default",
}
type SnackMessageType = "error" | "success" | "default";
export interface SnackMessageStateT {
message: string | null;
type: SnackMessageType;
}

const initialState: SnackMessageStateT = {
message: null,
type: SnackMessageType.DEFAULT,
type: "default",
};

function reducer(
Expand Down

0 comments on commit 91ee257

Please sign in to comment.