Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit saved form & replace saved XML functionality #161

Merged
merged 13 commits into from
Feb 12, 2021
Merged
34 changes: 34 additions & 0 deletions cypress/fixtures/study_test_modified.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<STUDY_SET>
<STUDY alias="GSE10966" center_name="GEO">
<IDENTIFIERS>
<PRIMARY_ID>SRP000539</PRIMARY_ID>
<EXTERNAL_ID label="primary" namespace="BioProject">PRJNA108793</EXTERNAL_ID>
<EXTERNAL_ID namespace="GEO">GSE10966</EXTERNAL_ID>
</IDENTIFIERS>
<DESCRIPTOR>
<STUDY_TITLE>Different title for testing purposes
</STUDY_TITLE>
<STUDY_TYPE existing_study_type="Other" />
<STUDY_ABSTRACT>Part of a set of highly integrated epigenome maps for Arabidopsis thaliana. Keywords:
Illumina high-throughput bisulfite sequencing Overall design: Whole genome shotgun bisulfite sequencing
of wildtype Arabidopsis plants (Columbia-0), and met1, drm1 drm2 cmt3, and ros1 dml2 dml3 null mutants
using the Illumina Genetic Analyzer.
</STUDY_ABSTRACT>
<CENTER_PROJECT_NAME>GSE10966</CENTER_PROJECT_NAME>
</DESCRIPTOR>
<STUDY_LINKS>
<STUDY_LINK>
<XREF_LINK>
<DB>pubmed</DB>
<ID>18423832</ID>
</XREF_LINK>
</STUDY_LINK>
</STUDY_LINKS>
<STUDY_ATTRIBUTES>
<STUDY_ATTRIBUTE>
<TAG>parent_bioproject</TAG>
<VALUE>PRJNA107265</VALUE>
</STUDY_ATTRIBUTE>
</STUDY_ATTRIBUTES>
</STUDY>
</STUDY_SET>
26 changes: 26 additions & 0 deletions cypress/integration/app.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ describe("Basic e2e", function () {
cy.get("button[type=submit]").contains("Submit").click()
cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1)

// Edit saved submission
cy.get("button[type=button]").contains("New form").click()
cy.get("button[type=button]").contains("Edit").click()
cy.get("input[name='descriptor.studyTitle']").should("have.value", "New title")
cy.get("input[name='descriptor.studyTitle']").type(" edited")
cy.get("input[name='descriptor.studyTitle']").should("have.value", "New title edited")
cy.get("button[type=button]").contains("Update").click()
cy.get("div[role=alert]").contains("Object updated")
cy.get("button[type=button]").contains("New form").click()
cy.get("button[type=button]").contains("Edit").click()
cy.get("input[name='descriptor.studyTitle']").should("have.value", "New title edited")

// Upload a Study xml file.
cy.get("div[role=button]").contains("Upload XML File").click()
cy.fixture("study_test.xml").then(fileContent => {
Expand All @@ -51,6 +63,20 @@ describe("Basic e2e", function () {
// Saved objects list should have newly added item from Study object
cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 2)

// Replace XML
cy.get("button[type=button]").contains("Replace").click()
cy.get(".MuiCardHeader-action").contains("Replace")
cy.fixture("study_test_modified.xml").then(fileContent => {
cy.get('input[type="file"]').attachFile({
fileContent: fileContent.toString(),
fileName: "testFile_replace.xml",
mimeType: "text/xml",
force: true,
})
})
cy.get("form").submit()
cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 2)

// Fill an Analysis form and submit object
cy.get("div[role=button]").contains("Analysis").click()
cy.get("div[role=button]")
Expand Down
157 changes: 111 additions & 46 deletions src/components/NewDraftWizard/WizardComponents/WizardAlert.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import { useDispatch, useSelector } from "react-redux"

import { resetDraftStatus } from "features/draftStatusSlice"
import { setAlert, resetAlert } from "features/wizardAlertSlice"
import { resetDraftObject } from "features/wizardDraftObjectSlice"
import { resetCurrentObject } from "features/wizardCurrentObjectSlice"
import { updateStatus } from "features/wizardStatusMessageSlice"
import { addObjectToDrafts } from "features/wizardSubmissionFolderSlice"
import draftAPIService from "services/draftAPI"
import objectAPIService from "services/objectAPI"

// Simple template for error messages
const ErrorMessage = message => {
return <Alert severity="error">{message}</Alert>
return <Alert severity="error">{message.message}</Alert>
}

/*
Expand All @@ -37,7 +38,7 @@ const CancelFormDialog = ({
currentSubmissionType: string,
}) => {
const submissionFolder = useSelector(state => state.submissionFolder)
const draftObject = useSelector(state => state.draftObject)
const currentObject = useSelector(state => state.currentObject)
const objectType = useSelector(state => state.objectType)
const [error, setError] = useState(false)
const [errorMessage, setErrorMessage] = useState("")
Expand All @@ -47,8 +48,13 @@ const CancelFormDialog = ({
const saveDraft = async () => {
setError(false)
const err = "Connection error, cannot save draft."
if (draftObject.draftId) {
const response = await draftAPIService.patchFromJSON(objectType, draftObject.draftId, draftObject)

if ((currentObject.accessionId || currentObject.objectId) && currentObject.type === "draft") {
const response = await draftAPIService.patchFromJSON(
objectType,
currentObject.accessionId || currentObject.objectId,
currentObject.cleanedValues
)
if (response.ok) {
dispatch(resetDraftStatus())
dispatch(
Expand All @@ -58,14 +64,14 @@ const CancelFormDialog = ({
errorPrefix: "",
})
)
dispatch(resetDraftObject())
dispatch(resetCurrentObject())
handleDialog(true)
} else {
setError(true)
setErrorMessage(err)
}
} else {
const response = await draftAPIService.createFromJSON(objectType, draftObject)
const response = await draftAPIService.createFromJSON(objectType, currentObject)
if (response.ok) {
dispatch(
updateStatus({
Expand All @@ -81,7 +87,7 @@ const CancelFormDialog = ({
schema: "draft-" + objectType,
})
)
dispatch(resetDraftObject())
dispatch(resetCurrentObject())
handleDialog(true)
} else {
setError(true)
Expand All @@ -90,53 +96,112 @@ const CancelFormDialog = ({
}
}

const updateForm = async () => {
const err = "Connection error, cannot update object"
const response = await objectAPIService.patchFromJSON(
objectType,
currentObject.accessionId,
currentObject.cleanedValues
)
if (response.ok) {
dispatch(resetDraftStatus())
dispatch(
updateStatus({
successStatus: "success",
response: response,
errorPrefix: "",
})
)
dispatch(resetCurrentObject())
handleDialog(true)
} else {
setError(true)
setErrorMessage(err)
}
}

let [dialogTitle, dialogContent] = ["", ""]
let dialogActions
const formContent = "If you save form as a draft, you can continue filling it later."
const xmlContent = "If you save xml as a draft, you can upload it later."
const objectContent = "If you save object as a draft, you can upload it later."

switch (parentLocation) {
case "submission": {
switch (alertType) {
case "form": {
dialogTitle = "Would you like to save draft version of this form"
dialogContent = formContent
break
}
case "xml": {
dialogTitle = "Would you like to save draft version of this xml upload"
dialogContent = xmlContent
break
}
case "existing": {
dialogTitle = "Would you like to save draft version of this existing object upload"
dialogContent = objectContent
break
}
default: {
dialogTitle = "default"
dialogContent = "default content"
if (currentObject?.type === "saved") {
dialogTitle = "Would you like to save edited form data?"
dialogContent = "Unsaved changes will be lost. If you save form as a draft, you can continue filling it later."
dialogActions = (
<DialogActions>
<Button variant="contained" onClick={() => handleDialog(false)} color="secondary">
Cancel
</Button>
<Button variant="contained" onClick={() => handleDialog(true)} color="primary">
Do not save
</Button>
<Button
variant="contained"
onClick={() => {
saveDraft()
}}
color="primary"
>
Save as a draft
</Button>
<Button
variant="contained"
onClick={() => {
updateForm()
}}
color="primary"
>
Update
</Button>
</DialogActions>
)
} else {
switch (alertType) {
case "form": {
dialogTitle = "Would you like to save draft version of this form"
dialogContent = formContent
break
}
case "xml": {
dialogTitle = "Would you like to save draft version of this xml upload"
dialogContent = xmlContent
break
}
case "existing": {
dialogTitle = "Would you like to save draft version of this existing object upload"
dialogContent = objectContent
break
}
default: {
dialogTitle = "default"
dialogContent = "default content"
}
}
dialogActions = (
<DialogActions>
<Button variant="contained" onClick={() => handleDialog(false)} color="secondary">
Cancel
</Button>
<Button variant="contained" onClick={() => handleDialog(true)} color="primary">
Do not save
</Button>
<Button
variant="contained"
onClick={() => {
saveDraft()
}}
color="primary"
>
Save
</Button>
</DialogActions>
)
}
dialogActions = (
<DialogActions>
<Button variant="contained" onClick={() => handleDialog(false)} color="secondary">
Cancel
</Button>
<Button variant="contained" onClick={() => handleDialog(true)} color="primary">
Do not save
</Button>
<Button
variant="contained"
onClick={() => {
saveDraft()
}}
color="primary"
>
Save
</Button>
</DialogActions>
)

break
}
case "footer": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useSelector, useDispatch } from "react-redux"
import WizardStatusMessageHandler from "../WizardForms/WizardStatusMessageHandler"

import { resetFocus } from "features/focusSlice"
import { setDraftObject } from "features/wizardDraftObjectSlice"
import { setCurrentObject } from "features/wizardCurrentObjectSlice"
import { deleteObjectFromFolder } from "features/wizardSubmissionFolderSlice"
import { setSubmissionType } from "features/wizardSubmissionTypeSlice"
import draftAPIService from "services/draftAPI"
Expand Down Expand Up @@ -78,7 +78,7 @@ const WizardDraftObjectPicker = () => {
setConnError(false)
const response = await draftAPIService.getObjectByAccessionId(objectType, objectId)
if (response.ok) {
dispatch(setDraftObject(response.data))
dispatch(setCurrentObject({ ...response.data, type: "draft" }))
dispatch(setSubmissionType("form"))
} else {
setConnError(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import WizardAlert from "./WizardAlert"

import { resetDraftStatus } from "features/draftStatusSlice"
import { setFocus } from "features/focusSlice"
import { resetDraftObject } from "features/wizardDraftObjectSlice"
import { resetCurrentObject } from "features/wizardCurrentObjectSlice"
import { setObjectType } from "features/wizardObjectTypeSlice"
import { setSubmissionType } from "features/wizardSubmissionTypeSlice"

Expand Down Expand Up @@ -247,7 +247,7 @@ const WizardObjectIndex = () => {
setClickedSubmissionType(submissionType)
setCancelFormOpen(true)
} else {
dispatch(resetDraftObject())
dispatch(resetCurrentObject())
dispatch(resetDraftStatus())
dispatch(setSubmissionType(submissionType))
dispatch(setObjectType(expandedObjectType))
Expand All @@ -262,6 +262,7 @@ const WizardObjectIndex = () => {
dispatch(resetDraftStatus())
dispatch(setSubmissionType(clickedSubmissionType))
dispatch(setObjectType(expandedObjectType))
dispatch(resetCurrentObject())
}
}

Expand Down
Loading