function RetriggerButton()

in src/components/CompareResults/Retrigger/RetriggerButton.tsx [31:192]


function RetriggerButton({ result, variant }: RetriggerButtonProps) {
  const {
    base_repository_name: baseRepository,
    base_retriggerable_job_ids: baseRetriggerableJobIds,
    new_repository_name: newRepository,
    new_retriggerable_job_ids: newRetriggerableJobIds,
    base_rev: baseRev,
    new_rev: newRev,
    base_repository_name: baseRepo,
    new_repository_name: newRepo,
  } = result;

  const [status, setStatus] = useState('pending' as Status);
  const { enqueueSnackbar } = useSnackbar();

  const getRetriggerConfig = async (
    repository: string,
    jobId: number,
    times: number,
  ) => {
    const tcParams = getTaskclusterParams();

    const jobInfo = await fetchJobInformationFromJobId(repository, jobId);
    const decisionTaskId = await fetchDecisionTaskIdFromPushId(
      repository,
      jobInfo.push_id,
    );

    const config = {
      rootUrl: tcParams.url,
      jobInfo,
      decisionTaskId,
      times,
    };

    return config;
  };

  const onRetriggerButtonClick = () => {
    const credentials = getTaskclusterCredentials();
    if (!credentials) {
      setStatus('signin-modal');
      return;
    }

    setStatus('retrigger-modal');
  };

  const onSignIn = async () => {
    await signInIntoTaskcluster();
    setStatus('retrigger-modal');
  };

  const showNotification = (message: string, actionHref: string) => {
    enqueueSnackbar(message, {
      variant: 'info',
      autoHideDuration: 10000, // The default (6000ms) configured in App.tsx seems a bit low for this notification
      // It's common that 2 notifications are sent (one for base, one for
      // new), so specifying the width makes them look more consistent.
      // This maxWidth is copied from notistack's own style.
      style: { width: '1000px', maxWidth: 'calc(100vw - 40px)' },
      action: (snackbarKey) => (
        <>
          <Button
            href={actionHref}
            target='_blank'
            rel='noreferrer'
            sx={{ marginInline: 2 }}
          >
            {Strings.components.retrigger.notification.treeherderButton}
          </Button>
          <SnackbarCloseButton snackbarKey={snackbarKey} />
        </>
      ),
    });
  };

  const onRetriggerConfirm = async ({
    baseTimes,
    newTimes,
  }: {
    baseTimes: number;
    newTimes: number;
  }) => {
    setStatus('pending');

    const baseRetriggerConfigPromise = getRetriggerConfig(
      baseRepository,
      baseRetriggerableJobIds[0],
      baseTimes,
    );

    const newRetriggerConfigPromise = getRetriggerConfig(
      newRepository,
      newRetriggerableJobIds[0],
      newTimes,
    );

    const [baseRetriggerTaskId, newRetriggerTaskId] = await Promise.all([
      baseRetriggerConfigPromise.then(retrigger),
      newRetriggerConfigPromise.then(retrigger),
    ]);

    // Note that the notification for "new" is dispatched before the
    // notification for "base", so that visually "base" is before "new", because
    // they are displayed backwards.
    if (newRetriggerTaskId) {
      showNotification(
        Strings.components.retrigger.notification.body(
          'new',
          newRetriggerTaskId,
        ),
        getTreeherderURL(newRev, newRepo),
      );
    }

    if (baseRetriggerTaskId) {
      showNotification(
        Strings.components.retrigger.notification.body(
          'base',
          baseRetriggerTaskId,
        ),
        getTreeherderURL(baseRev, baseRepo),
      );
    }
  };

  return (
    <>
      {variant === 'text' ? (
        <Button
          title={Strings.components.revisionRow.title.retriggerJobs}
          color='primary'
          variant='text'
          onClick={() => void onRetriggerButtonClick()}
          startIcon={<RefreshOutlinedIcon />}
        >
          Retrigger test
        </Button>
      ) : (
        <IconButton
          title={Strings.components.revisionRow.title.retriggerJobs}
          color='primary'
          size='small'
          onClick={() => void onRetriggerButtonClick()}
        >
          <RefreshOutlinedIcon />
        </IconButton>
      )}
      <RetriggerSignInModal
        open={status === 'signin-modal'}
        onClose={() => setStatus('pending')}
        onSignIn={onSignIn}
      />
      <RetriggerConfigModal
        open={status === 'retrigger-modal'}
        onClose={() => setStatus('pending')}
        onRetriggerClick={onRetriggerConfirm}
      />
    </>
  );
}