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

CSCfi / metadata-submitter-frontend / 20261176525

16 Dec 2025 08:20AM UTC coverage: 58.415% (-0.7%) from 59.151%
20261176525

push

github

Liisa Lado-Villar
Add Dockerfile and nginx config (merge commit)

Merge branch 'feature/dockerfile-for-production' into 'main'
* make nginx.conf more compact

* fix nginx.conf

* refactor nginx config to minimal and to override default

* fix Dockerfile

* Resolve the file paths for production build in Docker container

* add Dockerfile and nginx config

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

Approved-by: Joonatan Mäkinen <jmakine@csc.fi>
Co-authored-by: lhang <lhang@csc.fi>
Merged by Liisa Lado-Villar <145-lilado@users.noreply.gitlab.ci.csc.fi>

636 of 829 branches covered (76.72%)

Branch coverage included in aggregate %.

4 of 38 new or added lines in 4 files covered. (10.53%)

62 existing lines in 2 files now uncovered.

5358 of 9432 relevant lines covered (56.81%)

4.37 hits per line

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

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

3
import HomeIcon from "@mui/icons-material/Home"
1✔
4
import NavigateNextIcon from "@mui/icons-material/NavigateNext"
1✔
5
import Box from "@mui/material/Box"
1✔
6
import Breadcrumbs from "@mui/material/Breadcrumbs"
1✔
7
import Button from "@mui/material/Button"
1✔
8
import Link from "@mui/material/Link"
1✔
9
import Typography from "@mui/material/Typography"
1✔
10
import { upperFirst } from "lodash"
1✔
11
import { useTranslation } from "react-i18next"
1✔
12

13
import WizardStepContentHeader from "../WizardComponents/WizardStepContentHeader"
1✔
14

15
import WizardAlert from "components/SubmissionWizard/WizardComponents/WizardAlert"
1✔
16
import WizardDataBucketTable from "components/SubmissionWizard/WizardComponents/WizardDataBucketTable"
1✔
17
import WizardFilesTable from "components/SubmissionWizard/WizardComponents/WizardFilesTable"
1✔
18
import { setUnsavedForm, resetUnsavedForm } from "features/unsavedFormSlice"
1✔
19
import { addBucketToSubmission } from "features/wizardSubmissionSlice"
1✔
20
import { useAppSelector, useAppDispatch } from "hooks"
1✔
21
import { isFile, getMockBucketFiles } from "utils"
1✔
22

23
/*
24
 * Render buckets and files from SD Connect based on user selection
25
 */
26
const WizardDataBucketStep = () => {
1✔
27
  const dispatch = useAppDispatch()
×
28
  const submission = useAppSelector(state => state.submission)
×
29
  const bucket = submission.bucket || ""
×
30

31
  const { t } = useTranslation()
×
32

NEW
33
  const [files, setFiles] = useState<
×
34
    { id: string; path: string; name: string; bytes: number }[] | []
NEW
35
  >([])
×
36

37
  const [selectedBucket, setSelectedBucket] = useState<string>("")
×
38
  const [breadcrumbs, setBreadcrumbs] = useState<string[]>([])
×
39
  const [currentFilePath, setCurrentFilePath] = useState<string>("")
×
40
  const [alert, setAlert] = useState<boolean>(false)
×
41

NEW
42
  useEffect(() => {
×
NEW
43
    getMockBucketFiles().then(mockFiles => setFiles(mockFiles))
×
NEW
44
  }, [])
×
45

46
  const handleAlert = (state: boolean) => {
×
47
    if (state) handleLinkBucket()
×
48
    setAlert(false)
×
49
  }
×
50

51
  const handleLinkBucket = async () => {
×
52
    dispatch(resetUnsavedForm())
×
53
    dispatch(addBucketToSubmission(submission.submissionId, selectedBucket))
×
54
  }
×
55

56
  const handleBucketChange = (event: React.ChangeEvent<HTMLInputElement>) => {
×
57
    setSelectedBucket(event.target.value)
×
58
    dispatch(setUnsavedForm())
×
59
  }
×
60

61
  const handleFilesView = (bucketName: string) => {
×
62
    const currentPath = files
×
63
      .filter(file => file.path.split("/")[1] === bucketName)[0]
×
64
      .path.split("/")
×
65
      .slice(0, 2)
×
66
      .join("/")
×
67
    setCurrentFilePath(currentPath)
×
68
    setBreadcrumbs([t("dataBucket.allBuckets"), bucketName])
×
69
  }
×
70

71
  const handleAddToBreadcrumbs = (folderName: string) => {
×
72
    setBreadcrumbs(prevState => [...prevState, folderName])
×
73
  }
×
74

75
  const handleClickBreadcrumb = (breadcrumb: string, index: number) => {
×
76
    /* Remove all breadcrumbs if "All buckets" is clicked.
77
     * Otherwise, remove the following breadcrumbs if one breadcrumb is clicked/selected.
78
     */
79
    if (index === 0) setBreadcrumbs([])
×
80
    else setBreadcrumbs(breadcrumbs.slice(0, index + 1))
×
81

82
    /* Check if the last element of current filePath equals to selected breadcrumb,
83
     * if not, replacing current filePath with a new one that ends with the breadcrumb.
84
     */
85
    const splitFilePath = currentFilePath.split("/")
×
86
    if (breadcrumb && breadcrumb !== splitFilePath[splitFilePath.length - 1]) {
×
87
      const breadcrumbIndex = splitFilePath.indexOf(breadcrumb)
×
88
      const newFilePath = splitFilePath.slice(0, breadcrumbIndex + 1).join("/")
×
89
      setCurrentFilePath(newFilePath)
×
90
    }
×
91
  }
×
92

93
  const handleClickFileRow = (path: string, name: string) => {
×
94
    if (!isFile(files, path)) {
×
95
      /* Keep setting new filePath if current filePath's length < original filePath's length.
96
       * It means that the current file is still nested under folder
97
       */
98
      setCurrentFilePath(path)
×
99
      handleAddToBreadcrumbs(name)
×
100
    }
×
101
  }
×
102

103
  const linkBucketButton = (
×
104
    <Button
×
105
      disabled={!selectedBucket || !!bucket}
×
106
      variant="contained"
×
107
      aria-label={t("ariaLabels.linkBucket")}
×
108
      size="small"
×
109
      type="submit"
×
110
      onClick={() => setAlert(true)}
×
111
      data-testid="link-data-bucket"
×
112
    >
113
      {t("dataBucket.linkBucket")}
×
114
    </Button>
×
115
  )
116

117
  const renderHeading = () => (
×
118
    <Typography variant="h5" fontWeight="700" color="secondary">
×
119
      {bucket ? t("dataBucket.linkedBucket") : t("dataBucket.linkFromSDConnect")}
×
120
    </Typography>
×
121
  )
122

123
  const renderBreadcrumbs = () =>
×
124
    !!breadcrumbs.length && (
×
125
      <Breadcrumbs
×
126
        separator={<NavigateNextIcon fontSize="large" />}
×
127
        aria-label={t("ariaLabels.folderBreadcrumb")}
×
128
        data-testid="folder-breadcrumb"
×
129
      >
130
        {breadcrumbs.map((el, index) => (
×
131
          <Link
×
132
            key={index}
×
133
            underline="none"
×
134
            color="primary"
×
135
            href="#"
×
136
            onClick={() => handleClickBreadcrumb(el, index)}
×
137
            data-testid={el}
×
138
          >
139
            {index === 0 && (
×
140
              <HomeIcon
×
141
                color="primary"
×
142
                fontSize="large"
×
143
                sx={{ mr: "0.5rem", verticalAlign: "middle" }}
×
144
              />
145
            )}
146
            {index === 0 ? t("dataBucket.allBuckets") : upperFirst(el)}
×
147
          </Link>
×
148
        ))}
×
149
      </Breadcrumbs>
×
150
    )
151

152
  const renderBucketTable = () =>
×
153
    !breadcrumbs.length && (
×
154
      <WizardDataBucketTable
×
155
        selectedBucket={selectedBucket}
×
156
        bucket={bucket}
×
157
        handleBucketChange={handleBucketChange}
×
158
        handleFilesView={handleFilesView}
×
159
      />
160
    )
161

162
  const renderFileTable = () =>
×
163
    !!breadcrumbs.length && (
×
164
      <WizardFilesTable
×
165
        currentFilePath={currentFilePath}
×
166
        files={files}
×
167
        handleClickFileRow={handleClickFileRow}
×
168
      />
169
    )
170

171
  return (
×
172
    <Box>
×
173
      <WizardStepContentHeader action={linkBucketButton} />
×
174
      <Box display="flex" flexDirection="column" p="5rem" gap={4}>
×
175
        {renderHeading()}
×
176
        {renderBreadcrumbs()}
×
177
        {renderBucketTable()}
×
178
        {renderFileTable()}
×
179
      </Box>
×
180
      {alert && <WizardAlert onAlert={handleAlert} parentLocation="submission" alertType="link" />}
×
181
    </Box>
×
182
  )
183
}
×
184

185
export default WizardDataBucketStep
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