@material-ui/core#StepLabel TypeScript Examples

The following examples show how to use @material-ui/core#StepLabel. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: StepsProgress.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
StepsProgress = ({
  currentStepIndex,
  aborted,
  steps,
}: StepsProgressProps) => {
  // If the activeStep is greater/equal to the number of steps
  // Then the canary is being promoted
  // Increase the step index to mark the 'canary promoted' step as done also
  const activeStepIndex =
    currentStepIndex >= steps.length ? currentStepIndex + 1 : currentStepIndex;

  /*
   *  When the Rollout is aborted set the active step to -1
   *  otherwise it appears to always be on the first step
   */
  return (
    <Stepper activeStep={aborted ? -1 : activeStepIndex} alternativeLabel>
      {steps
        .map((step, i) => (
          <Step key={i}>
            <StepLabel data-testid={`step-${i}`}>
              {createLabelForStep(step)}
            </StepLabel>
          </Step>
        ))
        .concat(
          <Step key="-1">
            <StepLabel data-testid="step--1">Canary promoted</StepLabel>
          </Step>,
        )}
    </Stepper>
  );
}
Example #2
Source File: DeploymentLoader.tsx    From homebase-app with MIT License 6 votes vote down vote up
StyledLabel = styled(StepLabel)(
  ({
    theme,
    focused,
    hasError,
  }: {
    theme: Theme;
    focused: boolean;
    hasError: boolean;
  }) => ({
    "& .MuiStepIcon-root": {
      borderWidth: 3,
    },
    "& .MuiStepIcon-active": {
      borderColor: hasError
        ? theme.palette.error.main
        : focused
        ? "#fff"
        : theme.palette.primary.light,
      fill: "none",
    },
    "& .MuiStepIcon-text": {
      fill: "none",
    },
    "& .MuiStepIcon-completed": {
      borderColor: focused ? "#fff" : theme.palette.secondary.main,
      fill: theme.palette.secondary.main,
    },
  })
)
Example #3
Source File: FormSteps.tsx    From listo with MIT License 6 votes vote down vote up
FormSteps = () => {
  const classes = useStyles({});
  const { projectMeta, risks, categories } = useContext(AppContext);
  const { activeStep, handleGoToStep } = useContext(StepContext);

  if (!projectMeta || !risks || !categories) {
    // TODO: better empty state handling
    return <h1>Loading!</h1>;
  }

  return (
    <React.Fragment>
      <Stepper activeStep={activeStep} className={classes.stepper}>
        {STEPS.map(label => (
          <Step key={label} onClick={() => handleGoToStep(label)}>
            <StepLabel className={classes.stepLabels}>{label}</StepLabel>
          </Step>
        ))}
      </Stepper>
      {activeStep === 0 && <ProjectMetaGathering />}
      {activeStep === 1 && <RiskAssessment />}
      {activeStep === 2 && <ToolingComponent />}
      {activeStep === 3 && <ModuleSelection />}
      {activeStep === 4 && <Summary />}
      <PaginationButtons />
    </React.Fragment>
  );
}
Example #4
Source File: TransactionCreateContainer.tsx    From End-to-End-Web-Testing-with-Cypress with MIT License 5 votes vote down vote up
TransactionCreateContainer: React.FC<Props> = ({ authService, snackbarService }) => {
  const [authState] = useService(authService);
  const [, sendSnackbar] = useService(snackbarService);

  const [createTransactionState, sendCreateTransaction, createTransactionService] = useMachine(
    createTransactionMachine
  );

  // Expose createTransactionService on window for Cypress
  // @ts-ignore
  window.createTransactionService = createTransactionService;

  const [usersState, sendUsers] = useMachine(usersMachine);

  useEffect(() => {
    sendUsers({ type: "FETCH" });
  }, [sendUsers]);

  const sender = authState?.context?.user;
  const setReceiver = (receiver: User) => {
    sendCreateTransaction("SET_USERS", { sender, receiver });
  };
  const createTransaction = (payload: TransactionPayload) => {
    sendCreateTransaction("CREATE", payload);
  };
  const userListSearch = debounce(200, (payload: any) => sendUsers("FETCH", payload));

  const showSnackbar = (payload: SnackbarContext) => sendSnackbar("SHOW", payload);

  let activeStep;
  if (createTransactionState.matches("stepTwo")) {
    activeStep = 1;
  } else if (createTransactionState.matches("stepThree")) {
    activeStep = 3;
  } else {
    activeStep = 0;
  }

  return (
    <>
      <Stepper activeStep={activeStep}>
        <Step key={"stepOne"}>
          <StepLabel>Select Contact</StepLabel>
        </Step>
        <Step key={"stepTwo"}>
          <StepLabel>Payment</StepLabel>
        </Step>
        <Step key={"stepThree"}>
          <StepLabel>Complete</StepLabel>
        </Step>
      </Stepper>
      {createTransactionState.matches("stepOne") && (
        <TransactionCreateStepOne
          setReceiver={setReceiver}
          users={usersState.context.results!}
          userListSearch={userListSearch}
        />
      )}
      {sender && createTransactionState.matches("stepTwo") && (
        <TransactionCreateStepTwo
          receiver={createTransactionState.context.receiver}
          sender={sender}
          createTransaction={createTransaction}
          showSnackbar={showSnackbar}
        />
      )}
      {createTransactionState.matches("stepThree") && (
        <TransactionCreateStepThree createTransactionService={createTransactionService} />
      )}
    </>
  );
}
Example #5
Source File: defaults.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
defaultStepper: StepperProvider = {
  analyze: (state, { apis }) => ({
    stepLabel: <StepLabel>Select URL</StepLabel>,
    content: (
      <StepInitAnalyzeUrl
        key="analyze"
        analysisUrl={state.analysisUrl}
        onAnalysis={state.onAnalysis}
        disablePullRequest={!apis.catalogImportApi.preparePullRequest}
      />
    ),
  }),

  prepare: state => ({
    stepLabel: (
      <StepLabel optional={<Typography variant="caption">Optional</Typography>}>
        Import Actions
      </StepLabel>
    ),
    content: <BackButton onClick={state.onGoBack} />,
  }),

  review: state => ({
    stepLabel: <StepLabel>Review</StepLabel>,
    content: (
      <StepReviewLocation
        prepareResult={state.prepareResult}
        onReview={state.onReview}
        onGoBack={state.onGoBack}
      />
    ),
  }),

  finish: state => ({
    stepLabel: <StepLabel>Finish</StepLabel>,
    content: (
      <StepFinishImportLocation
        prepareResult={state.prepareResult}
        onReset={state.onReset}
      />
    ),
  }),
}
Example #6
Source File: index.tsx    From youtube-2020-june-material-ui-themes with MIT License 5 votes vote down vote up
export function FormikStepper({
  children,
  ...props
}: FormikConfig<FormikValues>) {
  const childrenArray = React.Children.toArray(children) as React.ReactElement<
    FormikStepProps
  >[];
  const [step, setStep] = useState(0);
  const currentChild = childrenArray[step];
  const [completed, setCompleted] = useState(false);

  function isLastStep() {
    return step === childrenArray.length - 1;
  }

  return (
    <Formik
      {...props}
      validationSchema={currentChild.props.validationSchema}
      onSubmit={async (values, helpers) => {
        if (isLastStep()) {
          await props.onSubmit(values, helpers);
          setCompleted(true);
        } else {
          setStep(s => s + 1);
        }
      }}
    >
      {({ isSubmitting }) => (
        <Form autoComplete="off">
          <Stepper alternativeLabel activeStep={step}>
            {childrenArray.map((child, index) => (
              <Step
                key={child.props.label}
                completed={step > index || completed}
              >
                <StepLabel>{child.props.label}</StepLabel>
              </Step>
            ))}
          </Stepper>

          {currentChild}

          <Grid container spacing={2}>
            {step > 0 ? (
              <Grid item>
                <Button
                  disabled={isSubmitting}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(s => s - 1)}
                >
                  Back
                </Button>
              </Grid>
            ) : null}
            <Grid item xs={12}>
              <Button
                startIcon={
                  isSubmitting ? <CircularProgress size="1rem" /> : null
                }
                disabled={isSubmitting}
                type="submit"
                fullWidth
              >
                {isSubmitting ? "Submitting" : isLastStep() ? "Submit" : "NeXt"}
              </Button>
            </Grid>
          </Grid>
        </Form>
      )}
    </Formik>
  );
}
Example #7
Source File: index.tsx    From youtube-2020-june-multi-step-form-formik with MIT License 5 votes vote down vote up
export function FormikStepper({ children, ...props }: FormikConfig<FormikValues>) {
  const childrenArray = React.Children.toArray(children) as React.ReactElement<FormikStepProps>[];
  const [step, setStep] = useState(0);
  const currentChild = childrenArray[step];
  const [completed, setCompleted] = useState(false);

  function isLastStep() {
    return step === childrenArray.length - 1;
  }

  return (
    <Formik
      {...props}
      validationSchema={currentChild.props.validationSchema}
      onSubmit={async (values, helpers) => {
        if (isLastStep()) {
          await props.onSubmit(values, helpers);
          setCompleted(true);
        } else {
          setStep((s) => s + 1);

          // the next line was not covered in the youtube video
          //
          // If you have multiple fields on the same step
          // we will see they show the validation error all at the same time after the first step!
          //
          // If you want to keep that behaviour, then, comment the next line :)
          // If you want the second/third/fourth/etc steps with the same behaviour
          //    as the first step regarding validation errors, then the next line is for you! =)
          //
          // In the example of the video, it doesn't make any difference, because we only
          //    have one field with validation in the second step :)
          helpers.setTouched({});
        }
      }}
    >
      {({ isSubmitting }) => (
        <Form autoComplete="off">
          <Stepper alternativeLabel activeStep={step}>
            {childrenArray.map((child, index) => (
              <Step key={child.props.label} completed={step > index || completed}>
                <StepLabel>{child.props.label}</StepLabel>
              </Step>
            ))}
          </Stepper>

          {currentChild}

          <Grid container spacing={2}>
            {step > 0 ? (
              <Grid item>
                <Button
                  disabled={isSubmitting}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep((s) => s - 1)}
                >
                  Back
                </Button>
              </Grid>
            ) : null}
            <Grid item>
              <Button
                startIcon={isSubmitting ? <CircularProgress size="1rem" /> : null}
                disabled={isSubmitting}
                variant="contained"
                color="primary"
                type="submit"
              >
                {isSubmitting ? 'Submitting' : isLastStep() ? 'Submit' : 'Next'}
              </Button>
            </Grid>
          </Grid>
        </Form>
      )}
    </Formik>
  );
}
Example #8
Source File: index.tsx    From back-home-safe with GNU General Public License v3.0 5 votes vote down vote up
Tutorial = ({
  setFinishedTutorial,
}: {
  setFinishedTutorial: (value: boolean) => void;
}) => {
  const { t } = useTranslation("tutorial");
  const { initPassword } = useData();

  const [activeStep, setActiveStep] = useState(0);
  const [password, setPassword] = useState("");

  const {
    activeStepComponent: { component, nextButtonText },
    isLastStep,
    allStep,
  } = useMemo(() => {
    const allStep = stepsSettings({ password, setPassword, t });

    return {
      allStep,
      activeStepComponent: allStep[activeStep] || {},
      isLastStep: activeStep === allStep.length - 1,
    };
  }, [activeStep, password, setPassword, t]);

  const handleNext = () => {
    if (isLastStep) {
      !isEmpty(password) && initPassword(password);
      setFinishedTutorial(true);
    } else {
      setActiveStep((prevActiveStep) => prevActiveStep + 1);
    }
  };

  const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };

  return (
    <PageWrapper>
      <Stepper activeStep={activeStep} alternativeLabel>
        {allStep.map(({ key, name }) => (
          <Step key={key}>
            <StepLabel>{name}</StepLabel>
          </Step>
        ))}
      </Stepper>
      <ContentWrapper>{component}</ContentWrapper>
      <ButtonGroup>
        <Button disabled={activeStep === 0} onClick={handleBack}>
          {t("global:button.last_page")}
        </Button>
        <Button variant="contained" color="secondary" onClick={handleNext}>
          {nextButtonText
            ? nextButtonText
            : isLastStep
            ? t("global:button.complete")
            : t("global:button.next_page")}
        </Button>
      </ButtonGroup>
    </PageWrapper>
  );
}
Example #9
Source File: QuickStartView.tsx    From SeeQR with MIT License 5 votes vote down vote up
StyledStepLabel = styled(StepLabel)`
  width: 14vw;
  & .MuiStepLabel-label {
    font-size: clamp(1rem, 1.28vw, 1.5rem);
  }
`
Example #10
Source File: styles.tsx    From twilio-voice-notification-app with Apache License 2.0 5 votes vote down vote up
StyledStepLabel = styled(StepLabel)({
  '& .MuiStepLabel-completed': {
    fontWeight: 'normal',
  },
})
Example #11
Source File: ExperimentForm.tsx    From abacus with GNU General Public License v2.0 4 votes vote down vote up
ExperimentForm = ({
  indexedMetrics,
  indexedSegments,
  initialExperiment,
  onSubmit,
  completionBag,
  formSubmissionError,
}: {
  indexedMetrics: Record<number, Metric>
  indexedSegments: Record<number, Segment>
  initialExperiment: ExperimentFormData
  completionBag: ExperimentFormCompletionBag
  onSubmit: (formData: unknown) => Promise<void>
  formSubmissionError?: Error
}): JSX.Element => {
  const classes = useStyles()

  const rootRef = useRef<HTMLDivElement>(null)

  const [currentStageId, setActiveStageId] = useState<StageId>(StageId.Beginning)
  const currentStageIndex = stages.findIndex((stage) => stage.id === currentStageId)

  const [completeStages, setCompleteStages] = useState<StageId[]>([])
  const [errorStages, setErrorStages] = useState<StageId[]>([])

  useEffect(() => {
    rootRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'start' })
  }, [currentStageId])

  // Preventing accidental non-react-router navigate-aways:
  const preventSubmissionRef = useRef<boolean>(false)
  useEffect(() => {
    // istanbul ignore next; trivial
    // Sure we can test that these lines run but what is really important is how they
    // behave in browsers, which IMO is too complicated to write tests for in this case.
    const eventListener = (event: BeforeUnloadEvent) => {
      if (preventSubmissionRef.current) {
        event.preventDefault()
        // Chrome requires returnValue to be set
        event.returnValue = ''
      }
    }
    window.addEventListener('beforeunload', eventListener)
    return () => {
      window.removeEventListener('beforeunload', eventListener)
    }
  }, [])

  return (
    <Formik
      initialValues={{ experiment: initialExperiment }}
      onSubmit={onSubmit}
      validationSchema={yup.object({ experiment: experimentFullNewSchema })}
    >
      {(formikProps) => {
        const getStageErrors = async (stage: Stage) => {
          return _.pick(await formikProps.validateForm(), stage.validatableFields)
        }

        const isStageValid = async (stage: Stage): Promise<boolean> => {
          const errors = await formikProps.validateForm()
          return !stage.validatableFields.some((field) => _.get(errors, field))
        }

        const updateStageState = async (stage: Stage) => {
          if (stage.id === StageId.Submit) {
            return
          }

          if (await isStageValid(stage)) {
            setErrorStages((prevValue) => _.difference(prevValue, [stage.id]))
            setCompleteStages((prevValue) => _.union(prevValue, [stage.id]))
          } else {
            setErrorStages((prevValue) => _.union(prevValue, [stage.id]))
            setCompleteStages((prevValue) => _.difference(prevValue, [stage.id]))
          }
        }

        const changeStage = (stageId: StageId) => {
          setActiveStageId(stageId)
          void updateStageState(stages[currentStageIndex])

          if (errorStages.includes(stageId)) {
            void getStageErrors(stages[stageId]).then((stageErrors) =>
              formikProps.setTouched(setNestedObjectValues(stageErrors, true)),
            )
          }
          if (stageId === StageId.Submit) {
            stages.map(updateStageState)
          }
        }

        const prevStage = () => {
          const prevStage = stages[currentStageIndex - 1]
          prevStage && changeStage(prevStage.id)
        }
        const nextStage = () => {
          const nextStage = stages[currentStageIndex + 1]
          nextStage && changeStage(nextStage.id)
        }

        preventSubmissionRef.current = formikProps.dirty && !formikProps.isSubmitting

        return (
          <div className={classes.root}>
            {/* This is required for React Router navigate-away prevention */}
            <Prompt
              when={preventSubmissionRef.current}
              message='You have unsaved data, are you sure you want to leave?'
            />
            <Paper className={classes.navigation}>
              <Stepper nonLinear activeStep={currentStageId} orientation='horizontal'>
                {stages.map((stage) => (
                  <Step key={stage.id} completed={stage.id !== currentStageId && completeStages.includes(stage.id)}>
                    <StepButton onClick={() => changeStage(stage.id)}>
                      <StepLabel error={stage.id !== currentStageId && errorStages.includes(stage.id)}>
                        {stage.title}
                      </StepLabel>
                    </StepButton>
                  </Step>
                ))}
              </Stepper>
            </Paper>
            <div ref={rootRef}>
              {/* Explanation: This should be fine as we aren't hiding behaviour that can't be accessed otherwise. */}
              {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
              <form className={classes.form} onSubmit={formikProps.handleSubmit} noValidate>
                {/* Prevent implicit submission of the form on enter. */}
                {/* See https://stackoverflow.com/a/51507806 */}
                <button type='submit' disabled style={{ display: 'none' }} aria-hidden='true'></button>
                {currentStageId === StageId.Beginning && (
                  <div className={classes.formPart}>
                    <Paper className={classes.paper}>
                      <Beginning />
                    </Paper>
                    <div className={classes.formPartActions}>
                      <Button onClick={nextStage} variant='contained' color='primary'>
                        Begin
                      </Button>
                    </div>
                  </div>
                )}
                {currentStageId === StageId.BasicInfo && (
                  <div className={classes.formPart}>
                    <Paper className={classes.paper}>
                      <BasicInfo completionBag={completionBag} />
                    </Paper>
                    <div className={classes.formPartActions}>
                      <Button onClick={prevStage}>Previous</Button>
                      <Button onClick={nextStage} variant='contained' color='primary'>
                        Next
                      </Button>
                    </div>
                  </div>
                )}
                {currentStageId === StageId.Audience && (
                  <div className={classes.formPart}>
                    <Paper className={classes.paper}>
                      <Audience {...{ formikProps, indexedSegments, completionBag }} />
                    </Paper>
                    <div className={classes.formPartActions}>
                      <Button onClick={prevStage}>Previous</Button>
                      <Button onClick={nextStage} variant='contained' color='primary'>
                        Next
                      </Button>
                    </div>
                  </div>
                )}
                {currentStageId === StageId.Metrics && (
                  <div className={classes.formPart}>
                    <Paper className={classes.paper}>
                      <Metrics {...{ indexedMetrics, completionBag, formikProps }} />
                    </Paper>
                    <div className={classes.formPartActions}>
                      <Button onClick={prevStage}>Previous</Button>
                      <Button onClick={nextStage} variant='contained' color='primary'>
                        Next
                      </Button>
                    </div>
                  </div>
                )}
                {currentStageId === StageId.Submit && (
                  <div className={classes.formPart}>
                    <Paper className={classes.paper}>
                      <Typography variant='h4' gutterBottom>
                        Confirm and Submit Your Experiment
                      </Typography>
                      <Typography variant='body2' gutterBottom>
                        Now is a good time to{' '}
                        <Link href='https://github.com/Automattic/experimentation-platform/wiki' target='_blank'>
                          check our wiki&apos;s experiment creation checklist
                        </Link>{' '}
                        and confirm everything is in place.
                      </Typography>

                      <Typography variant='body2' gutterBottom>
                        Once you submit your experiment it will be set to staging, where it can be edited up until you
                        set it to running.
                      </Typography>
                      <Typography variant='body2' gutterBottom>
                        <strong> When you are ready, click the Submit button below.</strong>
                      </Typography>
                    </Paper>
                    <GeneralErrorAlert error={formSubmissionError} />
                    <div className={classes.formPartActions}>
                      <Button onClick={prevStage}>Previous</Button>
                      <LoadingButtonContainer isLoading={formikProps.isSubmitting}>
                        <Button
                          type='submit'
                          variant='contained'
                          color='secondary'
                          disabled={formikProps.isSubmitting || errorStages.length > 0}
                        >
                          Submit
                        </Button>
                      </LoadingButtonContainer>
                    </div>
                  </div>
                )}
              </form>
            </div>
          </div>
        )
      }}
    </Formik>
  )
}
Example #12
Source File: defaults.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
/**
 * The default stepper generation function.
 *
 * Override this function to customize the import flow. Each flow should at
 * least override the prepare operation.
 *
 * @param flow - the name of the active flow
 * @param defaults - the default steps
 * @public
 */
export function defaultGenerateStepper(
  flow: ImportFlows,
  defaults: StepperProvider,
): StepperProvider {
  switch (flow) {
    // the prepare step is skipped but the label of the step is updated
    case 'single-location':
      return {
        ...defaults,
        prepare: () => ({
          stepLabel: (
            <StepLabel
              optional={
                <Typography variant="caption">
                  Discovered Locations: 1
                </Typography>
              }
            >
              Select Locations
            </StepLabel>
          ),
          content: <></>,
        }),
      };

    // let the user select one or more of the discovered locations in the prepare step
    case 'multiple-locations':
      return {
        ...defaults,
        prepare: (state, opts) => {
          if (state.analyzeResult.type !== 'locations') {
            return defaults.prepare(state, opts);
          }

          return {
            stepLabel: (
              <StepLabel
                optional={
                  <Typography variant="caption">
                    Discovered Locations: {state.analyzeResult.locations.length}
                  </Typography>
                }
              >
                Select Locations
              </StepLabel>
            ),
            content: (
              <StepPrepareSelectLocations
                analyzeResult={state.analyzeResult}
                prepareResult={state.prepareResult}
                onPrepare={state.onPrepare}
                onGoBack={state.onGoBack}
              />
            ),
          };
        },
      };

    case 'no-location':
      return {
        ...defaults,
        prepare: (state, opts) => {
          if (state.analyzeResult.type !== 'repository') {
            return defaults.prepare(state, opts);
          }

          return {
            stepLabel: <StepLabel>Create Pull Request</StepLabel>,
            content: (
              <StepPrepareCreatePullRequest
                analyzeResult={state.analyzeResult}
                onPrepare={state.onPrepare}
                onGoBack={state.onGoBack}
                renderFormFields={({
                  values,
                  setValue,
                  formState,
                  groupsLoading,
                  groups,
                  register,
                }) => (
                  <>
                    <Box marginTop={2}>
                      <Typography variant="h6">Pull Request Details</Typography>
                    </Box>

                    <TextField
                      {...asInputRef(
                        register('title', {
                          required: true,
                        }),
                      )}
                      label="Pull Request Title"
                      placeholder="Add Backstage catalog entity descriptor files"
                      margin="normal"
                      variant="outlined"
                      fullWidth
                      error={Boolean(formState.errors.title)}
                      required
                    />

                    <TextField
                      {...asInputRef(
                        register('body', {
                          required: true,
                        }),
                      )}
                      label="Pull Request Body"
                      placeholder="A describing text with Markdown support"
                      margin="normal"
                      variant="outlined"
                      fullWidth
                      error={Boolean(formState.errors.body)}
                      multiline
                      required
                    />

                    <Box marginTop={2}>
                      <Typography variant="h6">Entity Configuration</Typography>
                    </Box>

                    <TextField
                      {...asInputRef(
                        register('componentName', { required: true }),
                      )}
                      label="Name of the created component"
                      placeholder="my-component"
                      margin="normal"
                      variant="outlined"
                      fullWidth
                      error={Boolean(formState.errors.componentName)}
                      required
                    />

                    {!values.useCodeowners && (
                      <AutocompleteTextField
                        name="owner"
                        errors={formState.errors}
                        options={groups || []}
                        loading={groupsLoading}
                        loadingText="Loading groups…"
                        helperText="Select an owner from the list or enter a reference to a Group or a User"
                        errorHelperText="required value"
                        textFieldProps={{
                          label: 'Entity Owner',
                          placeholder: 'my-group',
                        }}
                        rules={{ required: true }}
                        required
                      />
                    )}

                    <FormControlLabel
                      control={
                        <Checkbox
                          {...asInputRef(register('useCodeowners'))}
                          onChange={(_, value) => {
                            if (value) {
                              setValue('owner', '');
                            }
                          }}
                        />
                      }
                      label={
                        <>
                          Use <em>CODEOWNERS</em> file as Entity Owner
                        </>
                      }
                    />
                    <FormHelperText>
                      WARNING: This may fail if no CODEOWNERS file is found at
                      the target location.
                    </FormHelperText>
                  </>
                )}
              />
            ),
          };
        },
      };

    default:
      return defaults;
  }
}
Example #13
Source File: MultistepJsonForm.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
MultistepJsonForm = (props: Props) => {
  const {
    formData,
    onChange,
    onReset,
    onFinish,
    fields,
    widgets,
    finishButtonLabel,
  } = props;
  const [activeStep, setActiveStep] = useState(0);
  const [disableButtons, setDisableButtons] = useState(false);
  const errorApi = useApi(errorApiRef);
  const featureFlagApi = useApi(featureFlagsApiRef);
  const featureFlagKey = 'backstage:featureFlag';
  const filterOutProperties = (step: Step): Step => {
    const filteredStep = cloneDeep(step);
    const removedPropertyKeys: Array<string> = [];
    if (filteredStep.schema.properties) {
      filteredStep.schema.properties = Object.fromEntries(
        Object.entries(filteredStep.schema.properties).filter(
          ([key, value]) => {
            if (value[featureFlagKey]) {
              if (featureFlagApi.isActive(value[featureFlagKey])) {
                return true;
              }
              removedPropertyKeys.push(key);
              return false;
            }
            return true;
          },
        ),
      );

      // remove the feature flag property key from required if they are not active
      filteredStep.schema.required = Array.isArray(filteredStep.schema.required)
        ? filteredStep.schema.required?.filter(
            r => !removedPropertyKeys.includes(r as string),
          )
        : filteredStep.schema.required;
    }
    return filteredStep;
  };

  const steps = props.steps
    .filter(step => {
      const featureFlag = step.schema[featureFlagKey];
      return (
        typeof featureFlag !== 'string' || featureFlagApi.isActive(featureFlag)
      );
    })
    .map(filterOutProperties);

  const handleReset = () => {
    setActiveStep(0);
    onReset();
  };
  const handleNext = () => {
    setActiveStep(Math.min(activeStep + 1, steps.length));
  };
  const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0));
  const handleCreate = async () => {
    if (!onFinish) {
      return;
    }

    setDisableButtons(true);
    try {
      await onFinish();
    } catch (err) {
      errorApi.post(err);
    } finally {
      setDisableButtons(false);
    }
  };

  return (
    <>
      <Stepper activeStep={activeStep} orientation="vertical">
        {steps.map(({ title, schema, ...formProps }, index) => {
          return (
            <StepUI key={title}>
              <StepLabel
                aria-label={`Step ${index + 1} ${title}`}
                aria-disabled="false"
                tabIndex={0}
              >
                <Typography variant="h6" component="h3">
                  {title}
                </Typography>
              </StepLabel>
              <StepContent key={title}>
                <Form
                  showErrorList={false}
                  fields={{ ...fieldOverrides, ...fields }}
                  widgets={widgets}
                  noHtml5Validate
                  formData={formData}
                  formContext={{ formData }}
                  onChange={onChange}
                  onSubmit={e => {
                    if (e.errors.length === 0) handleNext();
                  }}
                  {...formProps}
                  {...transformSchemaToProps(schema)}
                >
                  <Button disabled={activeStep === 0} onClick={handleBack}>
                    Back
                  </Button>
                  <Button variant="contained" color="primary" type="submit">
                    Next step
                  </Button>
                </Form>
              </StepContent>
            </StepUI>
          );
        })}
      </Stepper>
      {activeStep === steps.length && (
        <Content>
          <Paper square elevation={0}>
            <Typography variant="h6">Review and create</Typography>
            <StructuredMetadataTable
              dense
              metadata={getReviewData(formData, steps)}
            />
            <Box mb={4} />
            <Button onClick={handleBack} disabled={disableButtons}>
              Back
            </Button>
            <Button onClick={handleReset} disabled={disableButtons}>
              Reset
            </Button>
            <Button
              variant="contained"
              color="primary"
              onClick={handleCreate}
              disabled={!onFinish || disableButtons}
            >
              {finishButtonLabel ?? 'Create'}
            </Button>
          </Paper>
        </Content>
      )}
    </>
  );
}
Example #14
Source File: index.tsx    From homebase-app with MIT License 4 votes vote down vote up
DAOCreate: React.FC = () => {
  const creator = useContext(CreatorContext);

  const { back, next } = creator.state;
  const step = useStepNumber();
  const progress = useMemo(() => step * 25, [step]);
  const history = useHistory();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("sm"));

  const goToFAQ = (): void => {
    history.push("/faq");
  };

  useEffect(() => {
    mixpanel.unregister("daoAddress");
    mixpanel.unregister("daoType");

    mixpanel.track("Visited Creator");
  }, []);

  return (
    <PageContainer container direction="row">
      {!isMobile && (
        <ProgressContainer
          item
          xs={3}
          container
          justify="center"
          alignItems="center"
          direction="column"
        >
          <Grid
            item
            container
            direction="column"
            alignItems="center"
            xs={3}
            style={{ maxWidth: "unset" }}
          >
            <Grid item>
              <Box
                style={
                  location.pathname === "/creator"
                    ? custom(theme).logo
                    : undefined
                }
                onClick={() => history.push("/explorer")}
                margin="auto"
                marginTop="22px"
              >
                <Grid
                  container
                  alignItems="center"
                  wrap="nowrap"
                  justify="center"
                >
                  <Grid item>
                    <LogoItem src={HomeButton} />
                  </Grid>
                  <Grid item>
                    <Box paddingLeft="10px">
                      <LogoText color="textSecondary">Homebase</LogoText>
                    </Box>
                  </Grid>
                </Grid>
              </Box>
            </Grid>
          </Grid>
          <Grid item container direction="column" alignItems="center" xs>
            <ProgressBar
              progress={progress}
              radius={62}
              strokeWidth={4}
              strokeColor={theme.palette.secondary.main}
              trackStrokeWidth={2}
              trackStrokeColor={theme.palette.primary.light}
            >
              <Box className="indicator">
                <IndicatorValue>
                  {progress === 0.5 ? 0 : step * 25}%
                </IndicatorValue>
              </Box>
            </ProgressBar>
            <Box>
              <FAQClickToAction onClick={goToFAQ}>
                New to DAOs? Read our FAQ
              </FAQClickToAction>
            </Box>
            <StyledStepper activeStep={step} orientation="vertical">
              {STEPS.map(({ title }: StepInfo, index: number) => (
                <Step key={title}>
                  <StepLabel icon={index + 1}>{title}</StepLabel>
                </Step>
              ))}
            </StyledStepper>
          </Grid>
        </ProgressContainer>
      )}

      <StepContentHeigth item xs={12} md={9} container justify="center">
        <Grid
          container
          direction="column"
          alignItems="center"
          style={{ width: "100%" }}
        >
          <Navbar mode="creator" />
          <Grid item style={{ width: "100%" }} xs>
            <StepContentContainer item container justify="center">
              <StepRouter />
            </StepContentContainer>
          </Grid>
        </Grid>
      </StepContentHeigth>
      {step < 5 && <NavigationBar back={back} next={next} />}
    </PageContainer>
  );
}