• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CSCfi / metadata-submitter-frontend / 15132822209

20 May 2025 08:35AM UTC coverage: 47.784% (-0.08%) from 47.859%
15132822209

push

github

Hang Le
Feature/fix formatting (merge commit)

Merge branch 'feature/fix-formatting' into 'main'
* Format all files missed by incorrect format script

* Update precommit for husky v9

* Fix formatting script to include all files

Closes #1033
See merge request https://gitlab.ci.csc.fi/sds-dev/sd-submit/metadata-submitter-frontend/-/merge_requests/1114

Approved-by: Hang Le <lhang@csc.fi>
Co-authored-by: Monika Radaviciute <mradavic@csc.fi>
Merged by Hang Le <lhang@csc.fi>

656 of 963 branches covered (68.12%)

Branch coverage included in aggregate %.

150 of 326 new or added lines in 48 files covered. (46.01%)

5 existing lines in 4 files now uncovered.

6353 of 13705 relevant lines covered (46.36%)

4.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.95
/src/components/SubmissionWizard/WizardSteps/WizardCreateSubmissionStep.tsx
1
import React, { RefObject, useEffect, useState } from "react"
1✔
2

3
import {
4
  Button,
5
  FormControl,
6
  FormControlLabel,
7
  FormLabel,
8
  FormHelperText,
9
  Grid,
10
  Radio,
11
  RadioGroup,
12
  TextField,
13
  Typography,
14
} from "@mui/material"
1✔
15
import { styled } from "@mui/system"
1✔
16
import { useForm, Controller } from "react-hook-form"
1✔
17
import { useTranslation } from "react-i18next"
1✔
18
import { useNavigate } from "react-router"
1✔
19

20
import transformTemplatesToDrafts from "components/SubmissionWizard/WizardHooks/WizardTransformTemplatesToDrafts"
1✔
21
import { ResponseStatus } from "constants/responseStatus"
1✔
22
import { ObjectSubmissionTypes } from "constants/wizardObject"
1✔
23
import { updateStatus } from "features/statusMessageSlice"
1✔
24
import { resetTemplateAccessionIds } from "features/templateAccessionIdsSlice"
1✔
25
import { createSubmission, updateSubmission } from "features/wizardSubmissionSlice"
1✔
26
import { setSubmissionType } from "features/wizardSubmissionTypeSlice"
1✔
27
import { setWorkflowType } from "features/workflowTypeSlice"
1✔
28
import { useAppSelector, useAppDispatch } from "hooks"
1✔
29
import workflowAPIService from "services/workflowAPI"
1✔
30
import type { SubmissionDataFromForm, FormRef } from "types"
31
import { pathWithLocale } from "utils"
1✔
32

33
const Form = styled("form")({
1✔
34
  "& .MuiTextField-root": {
1✔
35
    margin: "1rem 0",
1✔
36
  },
1✔
37
  padding: "4rem",
1✔
38
})
1✔
39

40
/**
41
 * Define React Hook Form for adding new submission. Ref is added to RHF so submission can be triggered outside this component.
42
 */
43
const CreateSubmissionForm = ({
1✔
44
  createSubmissionFormRef,
2✔
45
}: {
46
  createSubmissionFormRef: FormRef
47
}) => {
2✔
48
  const dispatch = useAppDispatch()
2✔
49
  const projectId = useAppSelector(state => state.projectId)
2✔
50
  const submission = useAppSelector(state => state.submission)
2✔
51
  const templates = useAppSelector(state => state.templates)
2✔
52
  const templateAccessionIds = useAppSelector(state => state.templateAccessionIds)
2✔
53

54
  const { t } = useTranslation()
2✔
55

56
  const [workflows, setWorkflows] = useState([""])
2✔
57

58
  useEffect(() => {
2✔
59
    let isMounted = true
1✔
60
    const getAllWorkflows = async () => {
1✔
61
      if (isMounted) {
1✔
62
        let cachedWorkflows = sessionStorage.getItem(`cached_workflows`)
1✔
63

64
        if (!cachedWorkflows) {
1!
65
          try {
×
66
            const response = await workflowAPIService.getAllWorkflows()
×
67
            if (response.ok) {
×
68
              cachedWorkflows = JSON.stringify(response.data)
×
69
              sessionStorage.setItem(`cached_workflows`, cachedWorkflows)
×
70
            }
×
71
          } catch (error) {
×
72
            dispatch(
×
73
              updateStatus({
×
74
                status: ResponseStatus.error,
×
75
                response: error,
×
76
                helperText: "snackbarMessages.error.helperText.fetchWorkflowsError",
×
NEW
77
              })
×
78
            )
×
79
          }
×
80
        }
×
81

82
        const parsedWorkflows = JSON.parse(cachedWorkflows as string)
1✔
83

84
        setWorkflows(Object.keys(parsedWorkflows))
1✔
85
      }
1✔
86
    }
1✔
87

88
    getAllWorkflows()
1✔
89
    return () => {
1✔
90
      isMounted = false
1✔
91
    }
1✔
92
  }, [])
2✔
93

94
  const {
2✔
95
    handleSubmit,
2✔
96
    control,
2✔
97
    formState: { isSubmitting, isSubmitted },
2✔
98
  } = useForm()
2✔
99

100
  const navigate = useNavigate()
2✔
101

102
  const onSubmit = async (data: SubmissionDataFromForm) => {
2✔
103
    if (selectedWorkflowType === "") {
×
104
      return
×
105
    }
×
106
    // Transform the format of templates to drafts with proper values to be added to current submission or new submission
107
    const selectedDraftsArray =
×
108
      templates && submission?.submissionId
×
109
        ? await transformTemplatesToDrafts(
×
110
            templateAccessionIds,
×
111
            templates,
×
112
            submission.submissionId,
×
NEW
113
            dispatch
×
114
          )
×
115
        : []
×
116

117
    if (submission && submission?.submissionId) {
×
118
      dispatch(updateSubmission(submission.submissionId, Object.assign({ ...data, submission })))
×
119
        .then(() => {
×
120
          dispatch(
×
121
            updateStatus({
×
122
              status: ResponseStatus.success,
×
123
              helperText: "snackbarMessages.success.submission.updated",
×
NEW
124
            })
×
125
          )
×
126
        })
×
127
        .catch((error: string) => {
×
128
          dispatch(updateStatus({ status: ResponseStatus.error, response: JSON.parse(error) }))
×
129
        })
×
130
    } else {
×
131
      // Create a new submission with selected templates as drafts
132
      dispatch(setWorkflowType(data.workflowType))
×
133
      dispatch(createSubmission(projectId, data, selectedDraftsArray))
×
134
        .then(response => {
×
135
          const submissionId = response.data.submissionId
×
136
          navigate({ pathname: pathWithLocale(`submission/${submissionId}`), search: "step=2" })
×
137
          dispatch(setSubmissionType(ObjectSubmissionTypes.form))
×
138
          dispatch(resetTemplateAccessionIds())
×
139
        })
×
140
        .catch((error: string) => {
×
141
          dispatch(updateStatus({ status: ResponseStatus.error, response: JSON.parse(error) }))
×
142
        })
×
143
    }
×
144
  }
×
145

146
  const workflowType = useAppSelector(state => state.workflowType)
2✔
147
  const [selectedWorkflowType, setSelectedWorkflowType] = useState(workflowType)
2✔
148

149
  return (
2✔
150
    <Form
2✔
151
      onSubmit={handleSubmit(async data => onSubmit(data as SubmissionDataFromForm))}
2✔
152
      ref={createSubmissionFormRef as RefObject<HTMLFormElement>}
2✔
153
    >
154
      <Typography variant="h4" gutterBottom component="div" color="secondary" fontWeight="700">
2✔
155
        {t("newSubmission.nameSubmission")}
2✔
156
      </Typography>
2✔
157
      <Controller
2✔
158
        control={control}
2✔
159
        name="name"
2✔
160
        defaultValue={submission ? submission.name : ""}
2!
161
        render={({ field, fieldState: { error } }) => (
2✔
162
          <TextField
2✔
163
            {...field}
2✔
164
            label={`${t("newSubmission.submissionName")} *`}
2✔
165
            variant="outlined"
2✔
166
            fullWidth
2✔
167
            error={!!error}
2✔
168
            helperText={error ? t("newSubmission.errors.missingName") : null}
2!
169
            disabled={isSubmitting}
2✔
170
            inputProps={{ "data-testid": "submissionName" }}
2✔
171
          />
172
        )}
173
        rules={{ required: true, validate: { name: value => value.length > 0 } }}
2✔
174
      />
175
      <Controller
2✔
176
        control={control}
2✔
177
        name="description"
2✔
178
        defaultValue={submission ? submission.description : ""}
2!
179
        render={({ field, fieldState: { error } }) => (
2✔
180
          <TextField
2✔
181
            {...field}
2✔
182
            label={`${t("newSubmission.submissionDescription")} *`}
2✔
183
            variant="outlined"
2✔
184
            fullWidth
2✔
185
            multiline
2✔
186
            rows={5}
2✔
187
            error={!!error}
2✔
188
            helperText={error ? t("newSubmission.errors.missingDescription") : null}
2!
189
            disabled={isSubmitting}
2✔
190
            inputProps={{ "data-testid": "submissionDescription" }}
2✔
191
          />
192
        )}
193
        rules={{ required: true, validate: { description: value => value.length > 0 } }}
2✔
194
      />
195

196
      <Grid sx={{ mt: 2 }} container spacing={2}>
2✔
197
        <Grid>
2✔
198
          <FormLabel
2✔
199
            id="submission-type-selection-label"
2✔
200
            required
2✔
201
            error={selectedWorkflowType === "" && isSubmitted}
2!
202
            sx={theme => ({
2✔
203
              background: theme.palette.background.default,
2✔
204
              borderRadius: theme.spacing(0.4),
2✔
205
              height: "100%",
2✔
206
              display: "flex",
2✔
207
              alignItems: "center",
2✔
208
              padding: theme.spacing(0, 3, 0, 1.5),
2✔
209
              fontWeight: 600,
2✔
210
              color: theme.palette.secondary.main,
2✔
211
            })}
2✔
212
          >
213
            {t("newSubmission.typeOfSubmission")}
2✔
214
          </FormLabel>
2✔
215
        </Grid>
2✔
216
        <Grid size={{ xs: 6 }}>
2✔
217
          <FormControl>
2✔
218
            <Controller
2✔
219
              control={control}
2✔
220
              name="workflowType"
2✔
221
              defaultValue={selectedWorkflowType}
2✔
222
              render={({ field }) => {
2✔
223
                const handleChangeWorkflow = (e: React.ChangeEvent<HTMLInputElement>) => {
2✔
224
                  field.onChange(e.target.value)
×
225
                  setSelectedWorkflowType(e.target.value)
×
226
                }
×
227

228
                return (
2✔
229
                  <RadioGroup
2✔
230
                    {...field}
2✔
231
                    name="submission-type-selection"
2✔
232
                    aria-labelledby="submission-type-selection-label"
2✔
233
                    onChange={handleChangeWorkflow}
2✔
234
                  >
235
                    {workflows.map(workflow => (
2✔
236
                      <FormControlLabel
2✔
237
                        key={workflow}
2✔
238
                        value={workflow}
2✔
239
                        control={<Radio />}
2✔
240
                        label={workflow}
2✔
241
                        data-testid={workflow}
2✔
242
                        disabled={submission.submissionId !== ""}
2✔
243
                      />
244
                    ))}
2✔
245
                  </RadioGroup>
2✔
246
                )
247
              }}
2✔
248
            />
249
            {selectedWorkflowType === "" && isSubmitted && (
2!
250
              <FormHelperText error data-testid="missing-workflow-error">
×
251
                {t("newSubmission.errors.missingWorkflow")}
×
252
              </FormHelperText>
×
253
            )}
254
          </FormControl>
2✔
255
        </Grid>
2✔
256
      </Grid>
2✔
257

258
      <Button
2✔
259
        sx={{ mt: "2rem", p: "1rem 5rem" }}
2✔
260
        size="large"
2✔
261
        variant="contained"
2✔
262
        type="submit"
2✔
263
        aria-label="Save submission details"
2✔
264
        data-testid="create-submission"
2✔
265
      >
266
        {t("save")}
2✔
267
      </Button>
2✔
268
    </Form>
2✔
269
  )
270
}
2✔
271

272
/**
273
 * Show form to create submission as first step of new draft wizard
274
 */
275

276
const WizardCreateSubmissionStep = ({
1✔
277
  createSubmissionFormRef,
1✔
278
}: {
279
  createSubmissionFormRef: FormRef
280
}) => (
1✔
281
  <>
1✔
282
    <CreateSubmissionForm createSubmissionFormRef={createSubmissionFormRef} />
1✔
283
  </>
1✔
284
)
285

286
export default WizardCreateSubmissionStep
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc