diff --git a/Source/Plugins/Core/com.equella.core/js/tsrc/legacycontent/LegacyContent.tsx b/Source/Plugins/Core/com.equella.core/js/tsrc/legacycontent/LegacyContent.tsx index af429cd41e..c67c9a0a56 100644 --- a/Source/Plugins/Core/com.equella.core/js/tsrc/legacycontent/LegacyContent.tsx +++ b/Source/Plugins/Core/com.equella.core/js/tsrc/legacycontent/LegacyContent.tsx @@ -18,6 +18,7 @@ import { CircularProgress, Grid } from "@material-ui/core"; import * as OEQ from "@openequella/rest-api-client"; import Axios from "axios"; +import { isEqual } from "lodash"; import * as React from "react"; import { v4 } from "uuid"; import { @@ -123,6 +124,21 @@ export interface LegacyContentProps extends BaseOEQRouteComponentProps { children?: never; } +interface LegacyContentSubmission { + /** + * Indicate whether there is a request submitted to `LegacyContentApi` already but not completed yet. + */ + submitting: boolean; + /** + * Where to send the form data. + */ + action?: string; + /** + * Payload of the submission. + */ + payload?: StateData; +} + export type SubmitResponse = | ExternalRedirect | LegacyContentResponse @@ -165,6 +181,9 @@ export const LegacyContent = React.memo(function LegacyContent({ }: LegacyContentProps) { const [content, setContent] = React.useState(); const [updatingContent, setUpdatingContent] = React.useState(true); + const submittingForm = React.useRef({ + submitting: false, + }); const baseUrl = document.getElementsByTagName("base")[0].href; @@ -242,6 +261,24 @@ export const LegacyContent = React.memo(function LegacyContent({ submitValues: StateData, callback?: (response: SubmitResponse) => void ) { + if (formAction) { + const { submitting, action, payload } = submittingForm.current; + if ( + submitting && + formAction === action && + isEqual(submitValues, payload) + ) { + console.error(`ignore redundant submission to ${formAction}`); + return; + } + + submittingForm.current = { + submitting: true, + action: formAction, + payload: submitValues, + }; + } + submitRequest(toRelativeUrl(formAction || pathname), submitValues) .then((content) => { if (callback) { @@ -263,6 +300,11 @@ export const LegacyContent = React.memo(function LegacyContent({ ? fromAxiosResponse(error.response) : generateFromError(error); handleError(fullScreen, errorResponse); + }) + .finally(() => { + if (formAction) { + submittingForm.current = { submitting: false }; + } }); } diff --git a/build.sbt b/build.sbt index 19ef8d031e..2fa4e0e8d5 100644 --- a/build.sbt +++ b/build.sbt @@ -116,7 +116,7 @@ name := "Equella" equellaMajor in ThisBuild := 2021 equellaMinor in ThisBuild := 1 -equellaPatch in ThisBuild := 2 +equellaPatch in ThisBuild := 3 equellaStream in ThisBuild := "Stable" equellaBuild in ThisBuild := buildConfig.value.getString("build.buildname") diff --git a/project/plugins.sbt b/project/plugins.sbt index 47d4e4a307..4c7548c246 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,7 +4,7 @@ addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10") -addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "1.0.2") addSbtPlugin("de.johoop" % "sbt-testng-plugin" % "3.1.1")