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

CBIIT / crdc-datahub-ui / 18789341118

24 Oct 2025 06:57PM UTC coverage: 78.178% (+15.5%) from 62.703%
18789341118

push

github

web-flow
Merge pull request #888 from CBIIT/3.4.0

3.4.0 Release

4977 of 5488 branches covered (90.69%)

Branch coverage included in aggregate %.

8210 of 9264 new or added lines in 257 files covered. (88.62%)

6307 existing lines in 120 files now uncovered.

30203 of 39512 relevant lines covered (76.44%)

213.36 hits per line

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

90.67
/src/components/Questionnaire/ApproveFormDialog.tsx
1
import { LoadingButton } from "@mui/lab";
1✔
2
import {
1✔
3
  Button,
4
  Checkbox,
5
  CheckboxProps,
6
  DialogProps,
7
  FormControlLabel,
8
  OutlinedInputProps,
9
  styled,
10
} from "@mui/material";
11
import { isEqual } from "lodash";
1✔
12
import { FC, memo } from "react";
1✔
13
import { Controller, useForm } from "react-hook-form";
1✔
14

15
import CheckboxCheckedIconSvg from "../../assets/icons/checkbox_checked.svg?url";
1✔
16
import Dialog from "../GenericDialog";
1✔
17
import StyledHelperText from "../StyledFormComponents/StyledHelperText";
1✔
18
import BaseOutlinedInput from "../StyledFormComponents/StyledOutlinedInput";
1✔
19

20
const UncheckedIcon = styled("div")<{ readOnly?: boolean }>(({ readOnly }) => ({
1✔
21
  outline: "2px solid #1D91AB",
544✔
22
  outlineOffset: -2,
544✔
23
  width: "24px",
544✔
24
  height: "24px",
544✔
25
  backgroundColor: readOnly ? "#E5EEF4" : "initial",
544✔
26
  color: "#083A50",
544✔
27
  cursor: readOnly ? "not-allowed" : "pointer",
544✔
28
}));
1✔
29

30
const CheckedIcon = styled("div")<{ readOnly?: boolean }>(({ readOnly }) => ({
1✔
31
  backgroundImage: `url("${CheckboxCheckedIconSvg}")`,
3✔
32
  backgroundSize: "auto",
3✔
33
  backgroundRepeat: "no-repeat",
3✔
34
  width: "24px",
3✔
35
  height: "24px",
3✔
36
  backgroundColor: readOnly ? "#E5EEF4" : "initial",
3!
37
  color: "#1D91AB",
3✔
38
  cursor: readOnly ? "not-allowed" : "pointer",
3!
39
}));
1✔
40

41
const StyledDialog = styled(Dialog)({
1✔
42
  "& .MuiDialog-paper": {
1✔
43
    maxWidth: "none",
1✔
44
    borderRadius: "8px",
1✔
45
    width: "567px !important",
1✔
46
  },
1✔
47
});
1✔
48

49
const StyledCheckbox = styled(Checkbox)({
1✔
50
  "&.MuiCheckbox-root": {
1✔
51
    padding: "10px",
1✔
52
  },
1✔
53
  "& .MuiSvgIcon-root": {
1✔
54
    fontSize: "24px",
1✔
55
  },
1✔
56
  "&.Mui-disabled": {
1✔
57
    cursor: "not-allowed",
1✔
58
  },
1✔
59
});
1✔
60

61
const StyledOutlinedInput = styled(BaseOutlinedInput, {
1✔
62
  shouldForwardProp: (prop) => prop !== "resize" && prop !== "rowHeight",
1✔
63
})<OutlinedInputProps & { resize: boolean; rowHeight?: number }>(
1✔
64
  ({ resize, rowHeight = 25, rows, minRows, maxRows }) => ({
1✔
65
    marginTop: "24px",
546✔
66
    "&.MuiInputBase-multiline": {
546✔
67
      padding: "12px",
546✔
68
    },
546✔
69
    "& .MuiInputBase-inputMultiline": {
546✔
70
      resize: resize ? "vertical" : "none",
546!
71
      minHeight: resize && rowHeight ? `${(+rows || +minRows || 1) * rowHeight}px` : 0,
546!
72
      maxHeight: resize && maxRows && rowHeight ? `${+maxRows * rowHeight}px` : "none",
546!
73
      overflow: "auto",
546✔
74
    },
546✔
75
    "&.MuiInputBase-multiline .MuiInputBase-input": {
546✔
76
      lineHeight: `${rowHeight}px`,
546✔
77
      padding: 0,
546✔
78
    },
546✔
79
  })
546✔
80
);
1✔
81

82
export type FormInput = {
83
  pendingModelChange: boolean;
84
  reviewComment: string;
85
};
86

87
type Props = {
88
  loading?: boolean;
89
  onCancel?: () => void;
90
  onSubmit?: (data: FormInput) => void;
91
} & DialogProps;
92

93
const ApproveFormDialog: FC<Props> = ({ open, loading, onCancel, onSubmit, onClose, ...rest }) => {
1✔
94
  const {
546✔
95
    handleSubmit,
546✔
96
    watch,
546✔
97
    control,
546✔
98
    reset,
546✔
99
    formState: { errors },
546✔
100
  } = useForm<FormInput>({
546✔
101
    mode: "onSubmit",
546✔
102
    reValidateMode: "onSubmit",
546✔
103
    defaultValues: {
546✔
104
      pendingModelChange: false,
546✔
105
      reviewComment: "",
546✔
106
    },
546✔
107
  });
546✔
108
  const reviewComment = watch("reviewComment");
546✔
109

110
  const handleOnSubmit = (data: FormInput) => {
546✔
111
    onSubmit?.(data);
4✔
112
    reset();
4✔
113
  };
4✔
114

115
  const handleOnCancel = () => {
546✔
116
    reset();
1✔
117
    onCancel?.();
1✔
118
  };
1✔
119

120
  return (
546✔
121
    <StyledDialog
546✔
122
      open={open}
546✔
123
      onClose={onClose}
546✔
124
      scroll="body"
546✔
125
      title="Approve Submission Request"
546✔
126
      data-testid="approve-form-dialog"
546✔
127
      actions={
546✔
128
        <>
546✔
129
          <Button onClick={handleOnCancel} disabled={loading}>
546✔
130
            Cancel
131
          </Button>
546✔
132
          <LoadingButton
546✔
133
            onClick={handleSubmit(handleOnSubmit)}
546✔
134
            loading={loading}
546✔
135
            disabled={!reviewComment || loading}
546✔
136
            autoFocus
546✔
137
            data-testid="confirm-to-approve-button"
546✔
138
          >
139
            Confirm to Approve
140
          </LoadingButton>
546✔
141
        </>
546✔
142
      }
143
      {...rest}
546✔
144
    >
145
      <Controller
546✔
146
        name="reviewComment"
546✔
147
        control={control}
546✔
148
        rules={{
546✔
149
          validate: {
546✔
150
            required: (v: string) => v.trim() !== "" || "This field is required",
546!
151
            maxLength: (v: string) => v.trim().length <= 500 || "Maximum of 500 characters allowed",
546!
152
          },
546✔
153
        }}
546✔
154
        render={({ field }) => (
546✔
155
          <StyledOutlinedInput
546✔
156
            {...field}
546✔
157
            inputProps={{
546✔
158
              maxLength: 500,
546✔
159
              style: { height: "auto !important" },
546✔
160
              "aria-label": "Review comment input",
546✔
161
            }}
546✔
162
            name="reviewComment"
546✔
163
            placeholder="500 characters allowed"
546✔
164
            minRows={5}
546✔
165
            maxRows={15}
546✔
166
            data-testid="review-comment"
546✔
167
            sx={{ paddingY: "16px" }}
546✔
168
            required
546✔
169
            multiline
546✔
170
            resize
546✔
171
          />
172
        )}
546✔
173
      />
174
      {errors?.reviewComment?.message?.length > 0 && (
546!
NEW
175
        <StyledHelperText data-testid="review-comment-dialog-error">
×
NEW
176
          {errors.reviewComment.message}
×
NEW
177
        </StyledHelperText>
×
178
      )}
179

180
      <Controller
546✔
181
        name="pendingModelChange"
546✔
182
        control={control}
546✔
183
        render={({ field }) => (
546✔
184
          <FormControlLabel
547✔
185
            control={
547✔
186
              <StyledCheckbox
547✔
187
                {...field}
547✔
188
                checkedIcon={<CheckedIcon readOnly={loading} />}
547✔
189
                icon={<UncheckedIcon readOnly={loading} />}
547✔
190
                disabled={loading}
547✔
191
                inputProps={
547✔
192
                  { "data-testid": "pendingModelChange-checkbox" } as CheckboxProps["inputProps"]
547✔
193
                }
547✔
194
              />
195
            }
196
            label="Require Data Model changes"
547✔
197
          />
198
        )}
546✔
199
      />
200
      {errors?.pendingModelChange?.message?.length > 0 && (
546!
NEW
201
        <StyledHelperText data-testid="pending-model-change-dialog-error">
×
NEW
202
          {errors.pendingModelChange.message}
×
NEW
203
        </StyledHelperText>
×
204
      )}
205
    </StyledDialog>
546✔
206
  );
207
};
546✔
208

209
export default memo<Props>(ApproveFormDialog, isEqual);
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