blob: ecb666463ba5cb8e107e988b1add291fb9635dbe [file] [log] [blame]
// Copyright 2019 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 {ReactElement} from 'react';
import * as React from 'react'
import ReactDOM from 'react-dom';
import styles from './IssueWizard.css';
import LandingStep from './issue-wizard/LandingStep.tsx';
import DetailsStep from './issue-wizard/DetailsStep.tsx'
import {IssueWizardPersona} from './issue-wizard/IssueWizardTypes.tsx';
import CustomQuestionsStep from './issue-wizard/CustomQuestionsStep.tsx';
import {getOs, getChromeVersion, buildIssueDescription} from './issue-wizard/IssueWizardUtils.tsx'
import Header from './issue-wizard/Header.tsx'
import {GetQuestionsByCategory, buildIssueLabels, getCompValByCategory, getLabelsByCategory} from './issue-wizard/IssueWizardUtils.tsx';
import {ISSUE_WIZARD_QUESTIONS, ISSUE_REPRODUCE_PLACEHOLDER, OS_CHANNEL_LIST} from './issue-wizard/IssueWizardConfig.ts';
import {prpcClient} from 'prpc-client-instance.js';
import {expandDescriptions} from './issue-wizard/IssueWizardDescriptionsUtils.tsx';
import SubmitSuccessStep from './issue-wizard/SubmitSuccessStep.tsx';
import {IssueWizardFeedback} from './issue-wizard/IssueWizardFeedback.tsx';
/**
* Base component for the issue filing wizard, wrapper for other components.
* @return Issue wizard JSX.
*/
type Props = {
loginUrl: string,
userDisplayName: string,
}
export function IssueWizard(props: Props): ReactElement {
const {loginUrl, userDisplayName} = props;
React.useEffect(() => {
if(!userDisplayName) {
window.location.href = loginUrl;
}
},[loginUrl, userDisplayName]);
const [userPersona, setUserPersona] = React.useState(IssueWizardPersona.EndUser);
const [activeStep, setActiveStep] = React.useState(0);
const [category, setCategory] = React.useState('');
const [newIssueID, setnewIssueID] = React.useState('');
const [isRegression, setIsRegression] = React.useState(false);
const [textValues, setTextValues] = React.useState(
{
oneLineSummary: '',
stepsToReproduce: ISSUE_REPRODUCE_PLACEHOLDER,
describeProblem: '',
chromeVersion: getChromeVersion(),
osName: getOs(),
channel: OS_CHANNEL_LIST[0].name,
});
const [enableFeedback, setEnableFeedback] = React.useState(false);
const questionByCategory = GetQuestionsByCategory(ISSUE_WIZARD_QUESTIONS);
const moveStep = (step: number) => {
window.scrollTo(0, 0);
setActiveStep(step);
}
const reset = () => {
setTextValues({
oneLineSummary: '',
stepsToReproduce: ISSUE_REPRODUCE_PLACEHOLDER,
describeProblem: '',
chromeVersion: getChromeVersion(),
osName: getOs(),
channel: OS_CHANNEL_LIST[0].name,
});
setIsRegression(false);
}
const updateCategory = (category: string) => {
setCategory(category);
reset();
}
let page;
if (activeStep === 0) {
page = <LandingStep
userPersona={userPersona}
setUserPersona={setUserPersona}
category={category}
setCategory={updateCategory}
setActiveStep={moveStep}
/>;
} else if (activeStep === 1) {
page = <DetailsStep
textValues={textValues}
setTextValues={setTextValues}
category={category}
setActiveStep={moveStep}
setIsRegression={setIsRegression}
/>;
} else if (activeStep === 2) {
const compValByCategory = getCompValByCategory(ISSUE_WIZARD_QUESTIONS);
const labelsByCategory = getLabelsByCategory(ISSUE_WIZARD_QUESTIONS);
const onSubmitIssue = (comments: string, customQuestionsAnswers: Array<string>, attachments: Array<any>,onSuccess: Function, onFailure: Function) => {
const summary = textValues.oneLineSummary;
const component = compValByCategory.get(category);
const description = buildIssueDescription(
textValues.stepsToReproduce,
textValues.describeProblem,
comments, textValues.osName,
textValues.chromeVersion,
textValues.channel);
const labels = buildIssueLabels(category, textValues.osName, textValues.chromeVersion, labelsByCategory.get(category));
const {expandDescription, expandLabels, compVal} =
expandDescriptions(category, customQuestionsAnswers, isRegression, description, labels, component);
const componentsArray = [];
if (compVal.length > 0) {
componentsArray.push({
component: 'projects/chromium/componentDefs/' + compVal
})
}
const response = prpcClient.call('monorail.v3.Issues', 'MakeIssue', {
parent: 'projects/chromium',
issue: {
summary,
status: {
status: 'Untriaged',
},
components: componentsArray,
labels: expandLabels,
},
description: expandDescription,
uploads: attachments,
});
response.then(onSuccess, onFailure);
}
page =
<CustomQuestionsStep
setActiveStep={moveStep}
questions={questionByCategory.get(category)}
onSubmit={onSubmitIssue}
setnewIssueID={setnewIssueID}
/>;
} else if (activeStep === 3) {
page = <SubmitSuccessStep issueID={newIssueID}/>;
}
return (
<>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins"></link>
<div className={styles.container}>
<Header />
{page}
<div className={styles.feedback} onClick={()=>{setEnableFeedback(true);}}>Report a problem with this wizard</div>
</div>
<IssueWizardFeedback enable={enableFeedback} setEnable={setEnableFeedback}/>
</>
);
}
/**
* Renders the issue filing wizard page.
* @param mount HTMLElement that the React component should be added to.
* @param loginUrl redirect to login page
* @param userDisplayName login user
*/
export function renderWizard(mount: HTMLElement, loginUrl: string, userDisplayName: string): void {
ReactDOM.render(<IssueWizard loginUrl={loginUrl} userDisplayName={userDisplayName}/>, mount);
}