blob: 9e1ef72d5edb8e6ef78996d23ffcceb91c4cb712 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import React from 'react';
import {makeStyles} from '@material-ui/styles';
import {grey} from '@material-ui/core/colors';
import DotMobileStepper from './DotMobileStepper.tsx';
import {CustomQuestion, CustomQuestionType} from './IssueWizardTypes.tsx';
import CustomQuestionInput from './CustomQuestions/CustomQuestionInput.tsx';
import CustomQuestionTextarea from './CustomQuestions/CustomQuestionTextarea.tsx';
import CustomQuestionSelector from './CustomQuestions/CustomQuestionSelector.tsx';
import Alert from '@material-ui/core/Alert';
import AttachmentUploader from './AttachmentUploader.tsx';
import Modal from '@material-ui/core/Modal';
import Box from '@material-ui/core/Box';
import {LABELS_PREFIX} from './IssueWizardConfig.ts';
const userStyles = makeStyles({
greyText: {
color: grey[600],
},
root: {
width: '100%',
},
modalBox: {
position: 'absolute',
top: '40%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
backgroundColor: 'white',
borderRadius: '10px',
padding: '10px',
},
modalTitle: {
fontSize: '20px',
margin: '5px 0px',
},
modalContext: {
fontSize: '15px',
},
});
type Props = {
setActiveStep: Function,
questions: CustomQuestion[],
onSubmit: Function,
setnewIssueID: Function,
};
export default function CustomQuestionsStep(props: Props): React.ReactElement {
const {setActiveStep, questions, onSubmit, setnewIssueID} = props;
const classes = userStyles();
const customQuestions = new Array();
const [additionalComments, setAdditionalComments] = React.useState('');
const [attachments, setAttachments] = React.useState([]);
const [answers, setAnswers] = React.useState(Array(questions.length).fill(''));
const [hasError, setHasError] = React.useState(false);
const [submitEnable, setSubmitEnable] = React.useState(true);
const [isSubmitting, setIsSubmitting] = React.useState(false);
const updateAnswer = (answer: string, index: number) => {
const updatedAnswers = answers;
const answerPrefix = questions[index].answerPrefix !== LABELS_PREFIX ?
'<b>' + questions[index].answerPrefix + '</b> ' : LABELS_PREFIX;
updatedAnswers[index] = answerPrefix + answer;
setAnswers(updatedAnswers);
}
questions.forEach((q, i) => {
switch(q.type) {
case CustomQuestionType.Input:
customQuestions.push(
<CustomQuestionInput
question={q.question}
updateAnswers={(answer: string) => updateAnswer(answer, i)}
/>
);
return;
case CustomQuestionType.Text:
customQuestions.push(
<CustomQuestionTextarea
question={q.question}
tip={q.tip}
updateAnswers={(answer: string) => updateAnswer(answer, i)}
/>
);
return;
case CustomQuestionType.Select:
customQuestions.push(
<CustomQuestionSelector
question={q.question}
tip={q.tip}
options={q.options}
subQuestions={q.subQuestions}
updateAnswers={(answer: string) => updateAnswer(answer, i)}
/>
);
return;
default:
return;
}
});
const loadFiles = () => {
if (!attachments || attachments.length === 0) {
return Promise.resolve([]);
}
const loads = attachments.map(loadLocalFile);
return Promise.all(loads);
}
const loadLocalFile = (f: File) => {
return new Promise((resolve, reject) => {
const r = new FileReader();
r.onloadend = () => {
resolve({filename: f.name, content: btoa(r.result)});
};
r.onerror = () => {
reject(r.error);
};
r.readAsBinaryString(f);
});
}
const onSuccess = (response: Issue) => {
//redirect to issue
setIsSubmitting(false);
const issueId = response.name.split('/')[3];
setnewIssueID(issueId);
setActiveStep(3);
};
const onFailure = () => {
setIsSubmitting(false);
setHasError(true);
}
const onMakeIssue = () => {
setHasError(false);
setIsSubmitting(true);
try {
const uploads = loadFiles();
uploads.then((files) => {
// TODO: add attachments to request
onSubmit(additionalComments, answers, files, onSuccess, onFailure);
}, onFailure)
} catch (e) {
onFailure();
}
}
return (
<>
<h2 className={classes.greyText}>Extra Information about the Issue</h2>
{hasError
? <Alert severity="error" onClose={() => {setHasError(false)}}>Something went wrong, please try again later.</Alert>
: null
}
<div className={classes.root}>
{customQuestions}
<CustomQuestionTextarea
question="Additional comments"
updateAnswers={(answer: string) => setAdditionalComments(answer)}
/>
<h3>Upload any relevant screenshots</h3>
<AttachmentUploader files={attachments} setFiles={setAttachments} setSubmitEnable={setSubmitEnable}/>
</div>
<DotMobileStepper nextEnabled={submitEnable} activeStep={2} setActiveStep={setActiveStep} onSubmit={onMakeIssue}/>
<Modal open={isSubmitting} >
<Box className={classes.modalBox}>
<p className={classes.modalTitle}>Thanks for contributing to Chromium!</p>
<p>Stay put, we're filing your issue!</p>
</Box>
</Modal>
</>
);
}