Merge branch 'main' into avm99963-monorail

Merged commit 4137ed7879acadbf891e8c471108acb874dae886.

GitOrigin-RevId: b6100ffc5b1da355a35f37b13fcaaf746ee8b307
diff --git a/static_src/react/IssueWizard.tsx b/static_src/react/IssueWizard.tsx
index de5e8fb..ecb6664 100644
--- a/static_src/react/IssueWizard.tsx
+++ b/static_src/react/IssueWizard.tsx
@@ -6,62 +6,162 @@
 import * as React from 'react'
 import ReactDOM from 'react-dom';
 import styles from './IssueWizard.css';
-import DotMobileStepper from './issue-wizard/DotMobileStepper.tsx';
 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.
  */
-export function IssueWizard(): ReactElement {
-  const [checkExisting, setCheckExisting] = React.useState(false);
-  const [userType, setUserType] = React.useState('End User');
+ 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: '',
+      stepsToReproduce: ISSUE_REPRODUCE_PLACEHOLDER,
       describeProblem: '',
-      additionalComments: ''
+      chromeVersion: getChromeVersion(),
+      osName: getOs(),
+      channel: OS_CHANNEL_LIST[0].name,
     });
+  const [enableFeedback, setEnableFeedback] = React.useState(false);
+  const questionByCategory = GetQuestionsByCategory(ISSUE_WIZARD_QUESTIONS);
 
-  let nextEnabled;
+  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){
+  if (activeStep === 0) {
     page = <LandingStep
-        checkExisting={checkExisting}
-        setCheckExisting={setCheckExisting}
-        userType={userType}
-        setUserType={setUserType}
+        userPersona={userPersona}
+        setUserPersona={setUserPersona}
         category={category}
-        setCategory={setCategory}
+        setCategory={updateCategory}
+        setActiveStep={moveStep}
         />;
-    nextEnabled = checkExisting && userType && (category != '');
-  } else if (activeStep === 1){
-    page = <DetailsStep textValues={textValues} setTextValues={setTextValues} category={category}/>;
-    nextEnabled = (textValues.oneLineSummary.trim() !== '') &&
-                  (textValues.stepsToReproduce.trim() !== '') &&
-                  (textValues.describeProblem.trim() !== '');
+      } 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}
-        <DotMobileStepper nextEnabled={nextEnabled} activeStep={activeStep} setActiveStep={setActiveStep}/>
+        <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 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): void {
-  ReactDOM.render(<IssueWizard />, mount);
+export function renderWizard(mount: HTMLElement, loginUrl: string, userDisplayName: string): void {
+  ReactDOM.render(<IssueWizard loginUrl={loginUrl} userDisplayName={userDisplayName}/>, mount);
 }