diff --git a/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js b/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js
index 3e17b4f0..5f9b9820 100644
--- a/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js
+++ b/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js
@@ -8,6 +8,7 @@ import CardHeader from "@material-ui/core/CardHeader"
import { makeStyles } from "@material-ui/core/styles"
import { useDispatch, useSelector } from "react-redux"
+import WizardDraftObjectPicker from "components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker"
import WizardFillObjectDetailsForm from "components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm"
import WizardUploadObjectXMLForm from "components/NewDraftWizard/WizardForms/WizardUploadObjectXMLForm"
import { resetObjectType } from "features/wizardObjectTypeSlice"
@@ -28,7 +29,7 @@ const useStyles = makeStyles(theme => ({
marginTop: "-4px",
marginBottom: "-4px",
},
- cardContent: {
+ cardCenterContent: {
flexGrow: 1,
display: "flex",
justifyContent: "center",
@@ -97,15 +98,17 @@ const WizardAddObjectCard = () => {
testId: "xml",
},
existing: {
- title: "Choose existing object",
- component: Not implemented yet
,
+ title: "Choose from drafts",
+ component: ,
testId: "existing",
},
}
return (
- {cards[submissionType]["component"]}
+
+ {cards[submissionType]["component"]}
+
)
}
diff --git a/src/components/NewDraftWizard/WizardComponents/WizardAlert.js b/src/components/NewDraftWizard/WizardComponents/WizardAlert.js
index 98648a01..767f6a59 100644
--- a/src/components/NewDraftWizard/WizardComponents/WizardAlert.js
+++ b/src/components/NewDraftWizard/WizardComponents/WizardAlert.js
@@ -10,6 +10,7 @@ import DialogTitle from "@material-ui/core/DialogTitle"
import Alert from "@material-ui/lab/Alert"
import { useDispatch, useSelector } from "react-redux"
+import { resetDraftStatus } from "features/draftStatusSlice"
import { setAlert, resetAlert } from "features/wizardAlertSlice"
import { resetDraftObject } from "features/wizardDraftObjectSlice"
import { updateStatus } from "features/wizardStatusMessageSlice"
@@ -17,8 +18,8 @@ import { addObjectToDrafts } from "features/wizardSubmissionFolderSlice"
import draftAPIService from "services/draftAPI"
// Simple template for error messages
-const ErrorMessage = () => {
- return Connection error, cannot save draft.
+const ErrorMessage = message => {
+ return {message}
}
/*
@@ -39,31 +40,53 @@ const CancelFormDialog = ({
const draftObject = useSelector(state => state.draftObject)
const objectType = useSelector(state => state.objectType)
const [error, setError] = useState(false)
+ const [errorMessage, setErrorMessage] = useState("")
const dispatch = useDispatch()
- // Draft save logic. Get response depending on submission type
+ // Draft save logic
const saveDraft = async () => {
setError(false)
- const response = await draftAPIService.createFromJSON(objectType, draftObject)
- dispatch(
- updateStatus({
- successStatus: "success",
- response: response,
- errorPrefix: "",
- })
- )
-
- if (response.ok) {
- dispatch(
- addObjectToDrafts(submissionFolder.id, {
- accessionId: response.data.accessionId,
- schema: objectType,
- })
- )
- dispatch(resetDraftObject())
- handleDialog(true)
+ const err = "Connection error, cannot save draft."
+ if (draftObject.draftId) {
+ const response = await draftAPIService.patchFromJSON(objectType, draftObject.draftId, draftObject)
+ if (response.ok) {
+ dispatch(resetDraftStatus())
+ dispatch(
+ updateStatus({
+ successStatus: "success",
+ response: response,
+ errorPrefix: "",
+ })
+ )
+ dispatch(resetDraftObject())
+ handleDialog(true)
+ } else {
+ setError(true)
+ setErrorMessage(err)
+ }
} else {
- setError(true)
+ const response = await draftAPIService.createFromJSON(objectType, draftObject)
+ if (response.ok) {
+ dispatch(
+ updateStatus({
+ successStatus: "success",
+ response: response,
+ errorPrefix: "",
+ })
+ )
+ dispatch(resetDraftStatus())
+ dispatch(
+ addObjectToDrafts(submissionFolder.id, {
+ accessionId: response.data.accessionId,
+ schema: "draft-" + objectType,
+ })
+ )
+ dispatch(resetDraftObject())
+ handleDialog(true)
+ } else {
+ setError(true)
+ setErrorMessage(err)
+ }
}
}
@@ -233,7 +256,7 @@ const CancelFormDialog = ({
{dialogContent}
- {error && }
+ {error && }
{dialogActions}
)
diff --git a/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js b/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js
new file mode 100644
index 00000000..1485ffb8
--- /dev/null
+++ b/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js
@@ -0,0 +1,118 @@
+//@flow
+import React, { useState } from "react"
+
+import Button from "@material-ui/core/Button"
+import ButtonGroup from "@material-ui/core/ButtonGroup"
+import List from "@material-ui/core/List"
+import ListItem from "@material-ui/core/ListItem"
+import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction"
+import ListItemText from "@material-ui/core/ListItemText"
+import { makeStyles } from "@material-ui/core/styles"
+import { useSelector, useDispatch } from "react-redux"
+
+import WizardStatusMessageHandler from "../WizardForms/WizardStatusMessageHandler"
+
+import { setDraftObject } from "features/wizardDraftObjectSlice"
+import { deleteObjectFromFolder } from "features/wizardSubmissionFolderSlice"
+import { setSubmissionType } from "features/wizardSubmissionTypeSlice"
+import draftAPIService from "services/draftAPI"
+
+const useStyles = makeStyles(theme => ({
+ objectList: {
+ padding: "0 1rem",
+ width: "100%",
+ },
+ objectListItems: {
+ border: "none",
+ borderRadius: 3,
+ margin: theme.spacing(1, 0),
+ boxShadow: "0px 3px 10px -5px rgba(0,0,0,0.49)",
+ alignItems: "flex-start",
+ padding: ".5rem",
+ },
+ buttonContinue: {
+ color: "#007bff",
+ },
+ buttonDelete: {
+ color: "#dc3545",
+ },
+}))
+
+/**
+ * List drafts by submission type. Enables fetch and deletion of drafts
+ */
+const WizardDraftObjectPicker = () => {
+ const classes = useStyles()
+ const dispatch = useDispatch()
+ const objectType = useSelector(state => state.objectType)
+ const folder = useSelector(state => state.submissionFolder)
+ const currentObjectTypeDrafts = folder.drafts.filter(draft => draft.schema === "draft-" + objectType)
+
+ const [connError, setConnError] = useState(false)
+ const [responseError, setResponseError] = useState({})
+ const [errorPrefix, setErrorPrefix] = useState("")
+
+ const handleObjectContinue = async objectId => {
+ setConnError(false)
+ const response = await draftAPIService.getObjectByAccessionId(objectType, objectId)
+ if (response.ok) {
+ dispatch(setDraftObject(response.data))
+ dispatch(setSubmissionType("form"))
+ } else {
+ setConnError(true)
+ setResponseError(response)
+ setErrorPrefix("Draft fetching error.")
+ }
+ }
+
+ const handleObjectDelete = objectId => {
+ setConnError(false)
+ dispatch(deleteObjectFromFolder("draft", objectId, objectType)).catch(error => {
+ setConnError(true)
+ setResponseError(JSON.parse(error))
+ setErrorPrefix("Can't delete draft")
+ })
+ }
+
+ return (
+
+ {currentObjectTypeDrafts.length > 0 ? (
+
+ {currentObjectTypeDrafts.map(submission => {
+ return (
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+ ) : (
+
No {objectType} drafts.
+ )}
+
+ {connError && (
+
+ )}
+
+ )
+}
+
+export default WizardDraftObjectPicker
diff --git a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js
index 5d694951..af114625 100644
--- a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js
+++ b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js
@@ -16,6 +16,7 @@ import { useDispatch, useSelector } from "react-redux"
import WizardAlert from "./WizardAlert"
import { resetDraftStatus } from "features/draftStatusSlice"
+import { resetDraftObject } from "features/wizardDraftObjectSlice"
import { setObjectType } from "features/wizardObjectTypeSlice"
import { setSubmissionType } from "features/wizardSubmissionTypeSlice"
@@ -116,7 +117,7 @@ const SubmissionTypeList = ({
const submissionTypeMap = {
form: "Fill Form",
xml: "Upload XML File",
- existing: "Choose existing object",
+ existing: "Choose from drafts",
}
const classes = useStyles()
@@ -177,6 +178,7 @@ const WizardObjectIndex = () => {
setClickedSubmissionType(submissionType)
setCancelFormOpen(true)
} else {
+ dispatch(resetDraftObject())
dispatch(resetDraftStatus())
dispatch(setSubmissionType(submissionType))
dispatch(setObjectType(expandedObjectType))
@@ -212,7 +214,11 @@ const WizardObjectIndex = () => {
id="type-header"
>
{typeCapitalized}
-
+
{
setConnError(false)
- dispatch(deleteObjectFromFolder(objectId, objectType)).catch(error => {
+ dispatch(deleteObjectFromFolder("submitted", objectId, objectType)).catch(error => {
setConnError(true)
setResponseError(JSON.parse(error))
setErrorPrefix("Can't delete object")
diff --git a/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js b/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js
index 741d867d..f7a41e05 100644
--- a/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js
+++ b/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js
@@ -18,7 +18,7 @@ import WizardStatusMessageHandler from "./WizardStatusMessageHandler"
import { setDraftStatus, resetDraftStatus } from "features/draftStatusSlice"
import { setDraftObject } from "features/wizardDraftObjectSlice"
import { updateStatus } from "features/wizardStatusMessageSlice"
-import { addObjectToFolder, addObjectToDrafts } from "features/wizardSubmissionFolderSlice"
+import { addObjectToFolder, addObjectToDrafts, deleteObjectFromFolder } from "features/wizardSubmissionFolderSlice"
import draftAPIService from "services/draftAPI"
import objectAPIService from "services/objectAPI"
import schemaAPIService from "services/schemaAPI"
@@ -81,33 +81,45 @@ type FormContentProps = {
}
/*
- * Return react-hook-form based form which is rendered from schema and checked against resolver
+ * Return react-hook-form based form which is rendered from schema and checked against resolver. Set default values when continuing draft
*/
const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: FormContentProps) => {
const classes = useStyles()
- const methods = useForm({ mode: "onBlur", resolver })
const draftStatus = useSelector(state => state.draftStatus)
+ const draftObject = useSelector(state => state.draftObject)
+ const alert = useSelector(state => state.alert)
+ const methods = useForm({ mode: "onBlur", resolver, defaultValues: draftObject })
const dispatch = useDispatch()
const [cleanedValues, setCleanedValues] = useState({})
+ const [currentDraftId, setCurrentDraftId] = useState(draftObject?.accessionId)
const [timer, setTimer] = useState(0)
const increment = useRef(null)
- const alert = useSelector(state => state.alert)
const resetForm = () => {
methods.reset()
}
+ const checkDirty = () => {
+ if (methods.formState.isDirty && draftStatus === "") {
+ dispatch(setDraftStatus("notSaved"))
+ }
+ }
+
useEffect(() => {
- methods.formState.isDirty ? dispatch(setDraftStatus("notSaved")) : dispatch(resetDraftStatus())
+ checkDirty()
}, [methods.formState.isDirty])
const handleChange = () => {
- setCleanedValues(JSONSchemaParser.cleanUpFormValues(methods.getValues()))
- dispatch(setDraftObject(cleanedValues))
+ const values = JSONSchemaParser.cleanUpFormValues(methods.getValues())
+ setCleanedValues(values)
+ dispatch(setDraftObject(Object.assign(values, { draftId: currentDraftId })))
+ checkDirty()
+ }
- if (methods.formState.isDirty && draftStatus === "") {
- dispatch(setDraftStatus("notSaved"))
- }
+ const handleDraftDelete = draftId => {
+ dispatch(deleteObjectFromFolder("draft", draftId, objectType))
+ setCurrentDraftId(() => null)
+ handleChange()
}
/*
@@ -137,33 +149,65 @@ const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: F
}, [])
const saveDraft = async () => {
- const response = await draftAPIService.createFromJSON(objectType, cleanedValues)
- if (response.ok) {
- dispatch(resetDraftStatus())
- dispatch(
- addObjectToDrafts(folderId, {
- accessionId: response.data.accessionId,
- schema: objectType,
- })
- )
- .then(() => {
- dispatch(
- updateStatus({
- successStatus: "success",
- response: response,
- errorPrefix: "",
- })
- )
- })
- .catch(error => {
- dispatch(
- updateStatus({
- successStatus: "error",
- response: error,
- errorPrefix: "Cannot connect to folder API",
- })
- )
- })
+ handleReset()
+ if (currentDraftId || draftObject.accessionId) {
+ const response = await draftAPIService.patchFromJSON(objectType, currentDraftId, cleanedValues)
+ if (response.ok) {
+ dispatch(resetDraftStatus())
+ dispatch(
+ updateStatus({
+ successStatus: "success",
+ response: response,
+ errorPrefix: "",
+ })
+ )
+ } else {
+ dispatch(
+ updateStatus({
+ successStatus: "error",
+ response: response,
+ errorPrefix: "Unexpected error",
+ })
+ )
+ }
+ } else {
+ const response = await draftAPIService.createFromJSON(objectType, cleanedValues)
+ if (response.ok) {
+ setCurrentDraftId(response.data.accessionId)
+ dispatch(resetDraftStatus())
+ dispatch(
+ addObjectToDrafts(folderId, {
+ accessionId: response.data.accessionId,
+ schema: "draft-" + objectType,
+ })
+ )
+ .then(() => {
+ dispatch(
+ updateStatus({
+ successStatus: "success",
+ response: response,
+ errorPrefix: "",
+ })
+ )
+ })
+ .catch(error => {
+ dispatch(
+ updateStatus({
+ successStatus: "error",
+ response: error,
+ errorPrefix: "Cannot connect to folder API",
+ })
+ )
+ })
+ } else {
+ dispatch(
+ updateStatus({
+ successStatus: "error",
+ response: response,
+ errorPrefix: "Unexpected error",
+ })
+ )
+ }
}
}
@@ -204,7 +248,17 @@ const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: F
>
Clear form
-