Skip to content

Commit

Permalink
Unify save requests
Browse files Browse the repository at this point in the history
When the user was saving (or saving and processing),
we would sent two sequential POST requests,
one for metadata and one for all the rest.
This unifies the requests into a single one.

Requires backend changes.
  • Loading branch information
Arnei committed Oct 15, 2024
1 parent 0c41910 commit df4434c
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 185 deletions.
2 changes: 0 additions & 2 deletions src/main/MainMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { basicButtonStyle } from "../cssStyles";
import { setIsPlaying } from "../redux/videoSlice";

import { useTranslation } from "react-i18next";
import { resetPostRequestState as metadataResetPostRequestState } from "../redux/metadataSlice";
import { resetPostRequestState } from "../redux/workflowPostSlice";
import { setIsDisplayEditView } from "../redux/subtitleSlice";

Expand Down Expand Up @@ -126,7 +125,6 @@ export const MainMenuButton: React.FC<mainMenuButtonInterface> = ({
dispatch(setIsPlaying(false));
// Reset states
dispatch(resetPostRequestState());
dispatch(metadataResetPostRequestState());
};

const mainMenuButtonStyle = css({
Expand Down
39 changes: 1 addition & 38 deletions src/main/Metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ import { calendarStyle, errorBoxStyle, selectFieldStyle, titleStyle, titleStyleB
import { useAppDispatch, useAppSelector } from "../redux/store";
import {
fetchMetadata,
postMetadata,
selectCatalogs,
Catalog,
MetadataField,
setFieldValue,
selectGetError,
selectGetStatus,
selectPostError,
selectPostStatus,
setFieldReadonly,
} from "../redux/metadataSlice";

Expand Down Expand Up @@ -49,8 +46,6 @@ const Metadata: React.FC = () => {
const catalogs = useAppSelector(selectCatalogs);
const getStatus = useAppSelector(selectGetStatus);
const getError = useAppSelector(selectGetError);
const postStatus = useAppSelector(selectPostStatus);
const postError = useAppSelector(selectPostError);
const theme = useTheme();

// Try to fetch URL from external API
Expand Down Expand Up @@ -433,7 +428,7 @@ const Metadata: React.FC = () => {

/**
* Callback for when the form is submitted
* Saves values in redux state and sends them to Opencast
* Saves values in redux state
* @param values
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -458,8 +453,6 @@ const Metadata: React.FC = () => {
}
});

// Send updated values to Opencast
dispatch(postMetadata());
});
};

Expand Down Expand Up @@ -730,36 +723,6 @@ const Metadata: React.FC = () => {
return renderCatalog(catalog, i, {});
})}

{/*
<div css={{display: "block", wordWrap: "normal", whiteSpace: "pre"}}>
{t("metadata.submit-helpertext", { buttonName: t("metadata.submit-button") })}
</div>
<div title="buttons" css={buttonContainerStyle}>
<button css={[basicButtonStyleCOPY, nagivationButtonStyle, submitButtonStyle]}
type="submit"
title={t("metadata.submit-button-tooltip")}
aria-label={t("metadata.submit-button-tooltip")}
disabled={submitting || pristine}>
{t("metadata.submit-button")}
</button>
<button css={[basicButtonStyleCOPY, nagivationButtonStyle, submitButtonStyle]}
type="button"
title={t("metadata.reset-button-tooltip")}
aria-label={t("metadata.reset-button-tooltip")}
onClick={() => {form.reset()}}
disabled={submitting || pristine}>
{t("metadata.reset-button")}
</button>
</div> */}

<div css={errorBoxStyle(postStatus === "failed", theme)} role="alert">
<span>A problem occurred during communication with Opencast. <br />
Changes could not be saved to Opencast.</span><br />
{postError ? "Details: " + postError : "No error details are available."}<br />
</div>

{/* For debugging the forms current values*/}
{/* <FormSpy subscription={{ values: true }}>
{({ values }) => (
Expand Down
53 changes: 16 additions & 37 deletions src/main/Save.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect } from "react";

import { css } from "@emotion/react";
import {
Expand All @@ -22,8 +22,9 @@ import { CallbackButton, PageButton } from "./Finish";

import { useTranslation } from "react-i18next";
import {
postMetadata, selectPostError, selectPostStatus, setHasChanges as metadataSetHasChanges,
setHasChanges as metadataSetHasChanges,
selectHasChanges as metadataSelectHasChanges,
selectCatalogs,
} from "../redux/metadataSlice";
import {
selectSubtitles, selectHasChanges as selectSubtitleHasChanges,
Expand All @@ -45,8 +46,6 @@ const Save: React.FC = () => {

const postWorkflowStatus = useAppSelector(selectStatus);
const postError = useAppSelector(selectError);
const postMetadataStatus = useAppSelector(selectPostStatus);
const postMetadataError = useAppSelector(selectPostError);
const theme = useTheme();
const metadataHasChanges = useAppSelector(metadataSelectHasChanges);
const hasChanges = useAppSelector(selectHasChanges);
Expand All @@ -62,7 +61,7 @@ const Save: React.FC = () => {

const render = () => {
// Post (successful) save
if (postWorkflowStatus === "success" && postMetadataStatus === "success"
if (postWorkflowStatus === "success"
&& !hasChanges && !metadataHasChanges && !subtitleHasChanges) {
return (
<>
Expand Down Expand Up @@ -95,12 +94,6 @@ const Save: React.FC = () => {
<span>{t("various.error-text")}</span><br />
{postError ? t("various.error-details-text", { errorMessage: postError }) : t("various.error-text")}<br />
</div>
<div css={errorBoxStyle(postMetadataStatus === "failed", theme)} role="alert">
<span>{t("various.error-text")}</span><br />
{postMetadataError ?
t("various.error-details-text", { errorMessage: postMetadataError }) : t("various.error-text")
}<br />
</div>
</div>
);
};
Expand All @@ -118,24 +111,23 @@ export const SaveButton: React.FC = () => {
const segments = useAppSelector(selectSegments);
const tracks = useAppSelector(selectTracks);
const subtitles = useAppSelector(selectSubtitles);
const metadata = useAppSelector(selectCatalogs);
const workflowStatus = useAppSelector(selectStatus);
const metadataStatus = useAppSelector(selectPostStatus);
const theme = useTheme();
const [metadataSaveStarted, setMetadataSaveStarted] = useState(false);

// Update based on current fetching status
let Icon = LuSave;
let spin = false;
let tooltip = null;
if (workflowStatus === "failed" || metadataStatus === "failed") {
if (workflowStatus === "failed") {
Icon = LuAlertCircle;
spin = false;
tooltip = t("save.confirmButton-failed-tooltip");
} else if (workflowStatus === "success" && metadataStatus === "success") {
} else if (workflowStatus === "success") {
Icon = LuCheck;
spin = false;
tooltip = t("save.confirmButton-success-tooltip");
} else if (workflowStatus === "loading" || metadataStatus === "loading") {
} else if (workflowStatus === "loading") {
Icon = LuLoader;
spin = true;
tooltip = t("save.confirmButton-attempting-tooltip");
Expand All @@ -160,36 +152,23 @@ export const SaveButton: React.FC = () => {
return subtitlesForPosting;
};

// Dispatches first save request
// Subsequent save requests should be wrapped in useEffect hooks,
// so they are only sent after the previous one has finished
const save = () => {
setMetadataSaveStarted(true);
dispatch(postMetadata());
dispatch(postVideoInformation({
segments: segments,
tracks: tracks,
subtitles: prepareSubtitles(),
metadata: metadata,
}));
};

// Subsequent save request
useEffect(() => {
if (metadataStatus === "success" && metadataSaveStarted) {
setMetadataSaveStarted(false);
dispatch(postVideoInformation({
segments: segments,
tracks: tracks,
subtitles: prepareSubtitles(),
}));

}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [metadataStatus]);

// Let users leave the page without warning after a successful save
useEffect(() => {
if (workflowStatus === "success" && metadataStatus === "success") {
if (workflowStatus === "success") {
dispatch(videoSetHasChanges(false));
dispatch(metadataSetHasChanges(false));
dispatch(subtitleSetHasChanges(false));
}
}, [dispatch, metadataStatus, workflowStatus]);
}, [dispatch, workflowStatus]);

return (
<ThemedTooltip title={tooltip == null ? tooltip = "" : tooltip}>
Expand Down
53 changes: 15 additions & 38 deletions src/main/WorkflowConfiguration.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect } from "react";

import { css } from "@emotion/react";
import {
Expand All @@ -24,10 +24,8 @@ import { setEnd } from "../redux/endSlice";

import { useTranslation } from "react-i18next";
import {
postMetadata,
selectPostError,
selectPostStatus,
setHasChanges as metadataSetHasChanges,
selectCatalogs,
} from "../redux/metadataSlice";
import {
selectSubtitles,
Expand All @@ -45,8 +43,6 @@ const WorkflowConfiguration: React.FC = () => {

const postAndProcessWorkflowStatus = useAppSelector(selectStatus);
const postAndProcessError = useAppSelector(selectError);
const postMetadataStatus = useAppSelector(selectPostStatus);
const postMetadataError = useAppSelector(selectPostError);
const theme = useTheme();

const workflowConfigurationStyle = css({
Expand All @@ -73,12 +69,6 @@ const WorkflowConfiguration: React.FC = () => {
{ errorMessage: postAndProcessError }) :
t("various.error-text")}<br />
</div>
<div css={errorBoxStyle(postMetadataStatus === "failed", theme)} role="alert">
<span>{t("various.error-text")}</span><br />
{postMetadataError ? t("various.error-details-text",
{ errorMessage: postMetadataError }) :
t("various.error-text")}<br />
</div>
</div>
);
};
Expand All @@ -96,20 +86,19 @@ export const SaveAndProcessButton: React.FC<{ text: string; }> = ({ text }) => {
const segments = useAppSelector(selectSegments);
const tracks = useAppSelector(selectTracks);
const subtitles = useAppSelector(selectSubtitles);
const metadata = useAppSelector(selectCatalogs);
const workflowStatus = useAppSelector(selectStatus);
const metadataStatus = useAppSelector(selectPostStatus);
const [metadataSaveStarted, setMetadataSaveStarted] = useState(false);
const theme = useTheme();

// Let users leave the page without warning after a successful save
useEffect(() => {
if (workflowStatus === "success" && metadataStatus === "success") {
if (workflowStatus === "success") {
dispatch(setEnd({ hasEnded: true, value: "success" }));
dispatch(videoSetHasChanges(false));
dispatch(metadataSetHasChanges(false));
dispatch(subtitleSetHasChanges(false));
}
}, [dispatch, metadataStatus, workflowStatus]);
}, [dispatch, workflowStatus]);

const prepareSubtitles = () => {
const subtitlesForPosting = [];
Expand All @@ -124,38 +113,26 @@ export const SaveAndProcessButton: React.FC<{ text: string; }> = ({ text }) => {
return subtitlesForPosting;
};

// Dispatches first save request
// Subsequent save requests should be wrapped in useEffect hooks,
// so they are only sent after the previous one has finished
const saveAndProcess = () => {
setMetadataSaveStarted(true);
dispatch(postMetadata());
dispatch(postVideoInformationWithWorkflow({
segments: segments,
tracks: tracks,
workflow: [{ id: selectedWorkflowId }],
subtitles: prepareSubtitles(),
metadata: metadata,
}));
};

// Subsequent save request
useEffect(() => {
if (metadataStatus === "success" && metadataSaveStarted) {
setMetadataSaveStarted(false);
dispatch(postVideoInformationWithWorkflow({
segments: segments,
tracks: tracks,
workflow: [{ id: selectedWorkflowId }],
subtitles: prepareSubtitles(),
}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [metadataStatus]);

// Update based on current fetching status
let Icon = LuDatabase;
let spin = false;
if (workflowStatus === "failed" || metadataStatus === "failed") {
if (workflowStatus === "failed") {
Icon = LuAlertCircle;
spin = false;
} else if (workflowStatus === "success" && metadataStatus === "success") {
} else if (workflowStatus === "success") {
Icon = LuCheck;
spin = false;
} else if (workflowStatus === "loading" || metadataStatus === "loading") {
} else if (workflowStatus === "loading") {
Icon = LuLoader;
spin = true;

Expand Down
Loading

0 comments on commit df4434c

Please sign in to comment.