next/router#Router TypeScript Examples

The following examples show how to use next/router#Router. 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: _app.tsx    From terraform-visual with MIT License 6 votes vote down vote up
C = ({ Component, pageProps }: any) => {
  const title = 'Terraform Visual'

  useEffect(() => {
    ReactGa.set({ page: window.location.pathname })
    ReactGa.pageview(window.location.pathname)

    Router.events.on('routeChangeComplete', () => {
      ReactGa.set({ page: window.location.pathname })
      ReactGa.pageview(window.location.pathname)
    })
  }, [])

  return (
    <>
      <Head>
        <title>{title}</title>
        <meta property="og:title" content={title} key="title" />
        <meta
          name="google-site-verification"
          content="uP7DvoPqGNsHxvkVhK8aI0zizIHipI0LhZUueqfbG8Y"
        />
      </Head>

      <TerraofmrPlanProvider>
        <Navbar.C />

        <div className={styles.container}>
          <Component {...pageProps} />
        </div>
      </TerraofmrPlanProvider>
    </>
  )
}
Example #2
Source File: _app.page.test.tsx    From crowdsource-dataplatform with MIT License 5 votes vote down vote up
describe('App', () => {
  jestFetchMock.enableMocks();

  const setup = () => {
    router.pathname = '/tts-initiative/dashboard';
    const mockIpAddress = '111.111.11.111';

    fetchMock
      .doMockOnceIf('https://www.cloudflare.com/cdn-cgi/trace')
      .mockResponseOnce(`ip=${mockIpAddress}`);

    fetchMock.doMockIf(`/location-info?ip=${mockIpAddress}`).mockResponse(JSON.stringify({}));

    const Component = () => <div>Hello World</div>;

    return render(<App Component={Component} pageProps={{}} router={(router as unknown) as Router} />);
  };

  verifyAxeTest(setup());

  it('should render the Layout component', () => {
    setup();

    expect(screen.getByTestId('Layout')).toBeInTheDocument();
  });

  it('should render the passed component', () => {
    setup();

    expect(screen.getByText('Hello World')).toBeInTheDocument();
  });

  it('should render the Feedback component', () => {
    setup();

    expect(screen.getByText('Feedback')).toBeInTheDocument();
  });

  it('should render and close the language notification modal component', async () => {
    setup();

    const newValue = 'new value';
    const oldValue = 'old value';
    const localStorageKey = 'contributionLanguage';

    act(() => {
      const storageEvent = new StorageEvent('storage', {
        key: localStorageKey,
        newValue: newValue,
        oldValue: oldValue,
      });

      window.dispatchEvent(storageEvent);
    });

    expect(screen.getByTestId('Modal')).toBeInTheDocument();
  });
});
Example #3
Source File: _app.tsx    From Figurify with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeStart', () => NProgress.start());
Example #4
Source File: _app.tsx    From Figurify with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeComplete', () => NProgress.done());
Example #5
Source File: _app.tsx    From Figurify with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeError', () => NProgress.done());
Example #6
Source File: _app.tsx    From website with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeStart', () => NProgress.start());
Example #7
Source File: _app.tsx    From website with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeComplete', () => NProgress.done());
Example #8
Source File: _app.tsx    From website with Apache License 2.0 5 votes vote down vote up
Router.events.on('routeChangeError', () => NProgress.done());
Example #9
Source File: _app.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
Router.events.on('routeChangeStart', NProgress.start)
Example #10
Source File: _app.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
Router.events.on('routeChangeComplete', NProgress.done)
Example #11
Source File: _app.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
Router.events.on('routeChangeError', NProgress.done)
Example #12
Source File: redirects.ts    From Cromwell with MIT License 4 votes vote down vote up
usePatchForRedirects = () => {
    // Patch next/router for rewrites
    const router = useRouter?.();
    const canLogDebugInfo = false;
    const logInfo = (...args) => canLogDebugInfo && console.log(...args);

    if (router && !(router as any).cromwellPatch) {
        (router as any).cromwellPatch = true;

        const handleChange = (url, as, options): [url: any, as?: any, options?: any] => {
            logInfo('router.push', url, as, options);
            if (typeof url === 'string') {
                const redirect = findRedirect(url);
                if (redirect?.type === 'rewrite' && redirect.from) {
                    logInfo('router.push rewrite', redirect);
                    if (!options) options = {};
                    (options as any).rewriteTo = url;
                    (options as any).rewriteFrom = redirect.from;

                    if (as && as === url) as = redirect.from;
                    url = redirect.from;
                }
            }
            return [url, as, options];
        }

        const routerPush = router.push;
        router.push = (url, as, options) => {
            return routerPush(...handleChange(url, as, options));
        }

        const routerReplace = router.replace;
        router.replace = (url, as, options) => {
            return routerReplace(...handleChange(url, as, options));
        }

        if (SingletonRouter?.router) {
            (SingletonRouter.router as any).change = (changeType, url, as, options) => {
                logInfo('SingletonRouter args', changeType, url, as, options);
                const { rewriteFrom, rewriteTo, rewrote, ...normalOptions } = options ?? {};

                if (!rewrote) {
                    const nextUrl = rewriteTo ?? as ?? url;
                    const redirect = findRedirect(nextUrl);

                    if (redirect?.type === 'rewrite' && redirect.from) {
                        logInfo('SingletonRouter rewrite', rewriteFrom, rewriteTo);
                        normalOptions.rewriteTo = nextUrl;
                        normalOptions.rewrote = true;

                        if (changeType === 'pushState') {
                            routerPush(redirect.from, undefined, normalOptions);
                        } else {
                            routerReplace(redirect.from, undefined, normalOptions);
                        }

                        return new Promise((resolve) => resolve(false));
                    }
                }
                return (Router.prototype as any).change.apply(SingletonRouter.router, [changeType, url, as, options]);
            }
        }
    }

    if (!isServer()) {
        (window as any).routerPush = (...args) => router.push(args[0], args[1], args[2]);
        (window as any).nextRouter = getStore().nodeModules?.modules?.['next/router'];
    }


    // Patch window.history to handle rewrites
    if (!isServer() && !(window as any).cromwellHistoryPatch) {
        (window as any).cromwellHistoryPatch = true;

        const handleChange = (data: any, title: string, url?: string | null | undefined):
            [data: any, title: string, url?: string | null | undefined] => {
            const rewriteTo = data?.options?.rewriteTo;
            if (rewriteTo) {
                logInfo('history.pushState/replaceState rewrite', rewriteTo);
                if (data?.as && data.as === url) data.as = rewriteTo;
                if (data?.url && data.url === url) data.url = rewriteTo;
                url = rewriteTo;
            }
            return [data, title, url];
        }

        const pushState = history.pushState;
        history.pushState = (...params) => {
            logInfo('history.pushState params', params)
            pushState.apply(history, handleChange(...params));
        };

        const replaceState = history.replaceState;
        history.replaceState = (...params) => {
            logInfo('history.replaceState params', params)
            replaceState.apply(history, handleChange(...params));
        };
    }

    // Handle redirects
    if (!isServer()) {
        useLayoutEffect(() => {
            const redirect = findRedirect(window.location.pathname, window.location.search);
            if (redirect?.type === 'redirect' && redirect.to) {
                logInfo('useLayoutEffect redirect', redirect, router?.route)
                router?.replace(redirect.to);
            }
        });
    }
}
Example #13
Source File: StudentQueue.tsx    From office-hours with GNU General Public License v3.0 4 votes vote down vote up
export default function StudentQueue({
  qid,
  cid,
}: StudentQueueProps): ReactElement {
  const { queue } = useQueue(qid);
  const { questions, mutateQuestions } = useQuestions(qid);
  const { studentQuestion, studentQuestionIndex } = useStudentQuestion(qid);
  const [isFirstQuestion, setIsFirstQuestion] = useLocalStorage(
    "isFirstQuestion",
    true
  );
  const [showJoinPopconfirm, setShowJoinPopconfirm] = useState(false);
  const { deleteDraftQuestion } = useDraftQuestion();
  const [isJoining, setIsJoining] = useState(
    questions &&
      studentQuestion &&
      studentQuestion?.status !== OpenQuestionStatus.Queued
  );
  const [popupEditQuestion, setPopupEditQuestion] = useState(false);

  const router = useRouter();
  const editQuestionQueryParam = Boolean(router.query.edit_question as string);

  useEffect(() => {
    if (editQuestionQueryParam && studentQuestion) {
      mutate(`/api/v1/queues/${qid}/questions`);
      setPopupEditQuestion(true);
      router.push(`/course/${cid}/queue/${qid}`);
    }
  }, [editQuestionQueryParam, qid, studentQuestion]);

  const studentQuestionId = studentQuestion?.id;
  const studentQuestionStatus = studentQuestion?.status;
  const leaveQueue = useCallback(async () => {
    await API.questions.update(studentQuestionId, {
      status: ClosedQuestionStatus.ConfirmedDeleted,
    });

    setIsJoining(false);
    await mutateQuestions();
  }, [mutateQuestions, studentQuestionId]);

  const rejoinQueue = useCallback(async () => {
    await API.questions.update(studentQuestionId, {
      status: OpenQuestionStatus.PriorityQueued,
    });
    await mutateQuestions();
  }, [mutateQuestions, studentQuestionId]);

  const finishQuestion = useCallback(
    async (text: string, questionType: QuestionType, groupable: boolean) => {
      const updateStudent = {
        text,
        questionType,
        groupable,
        status:
          studentQuestionStatus === OpenQuestionStatus.Drafting
            ? OpenQuestionStatus.Queued
            : studentQuestionStatus,
      };

      const updatedQuestionFromStudent = await API.questions.update(
        studentQuestionId,
        updateStudent
      );

      const newQuestionsInQueue = questions?.queue?.map((question: Question) =>
        question.id === studentQuestionId
          ? updatedQuestionFromStudent
          : question
      );

      // questions are the old questions and newQuestionsInQueue are questions that've been added since.
      mutateQuestions({
        ...questions,
        yourQuestion: updatedQuestionFromStudent,
        queue: newQuestionsInQueue,
      });
    },
    [studentQuestionStatus, studentQuestionId, questions, mutateQuestions]
  );

  const joinQueueAfterDeletion = useCallback(async () => {
    await API.questions.update(studentQuestion?.id, {
      status: ClosedQuestionStatus.ConfirmedDeleted,
    });
    await mutateQuestions();
    const newQuestion = await API.questions.create({
      text: studentQuestion.text,
      questionType: studentQuestion?.questionType,
      queueId: qid,
      location: studentQuestion?.location,
      force: true,
      groupable: false,
    });
    await API.questions.update(newQuestion.id, {
      status: OpenQuestionStatus.Queued,
    });
    await mutateQuestions();
  }, [mutateQuestions, qid, studentQuestion]);

  const openEditModal = useCallback(async () => {
    mutate(`/api/v1/queues/${qid}/questions`);
    setPopupEditQuestion(true);
  }, [qid]);

  const closeEditModal = useCallback(() => {
    setPopupEditQuestion(false);
    setIsJoining(false);
  }, []);

  const leaveQueueAndClose = useCallback(() => {
    //delete draft when they leave the queue
    deleteDraftQuestion();
    leaveQueue();
    closeEditModal();
  }, [deleteDraftQuestion, leaveQueue, closeEditModal]);

  const joinQueueOpenModal = useCallback(
    async (force: boolean) => {
      try {
        const createdQuestion = await API.questions.create({
          queueId: Number(qid),
          text: "",
          force: force,
          questionType: null,
          groupable: false,
        });
        const newQuestionsInQueue = [...questions?.queue, createdQuestion];
        await mutateQuestions({ ...questions, queue: newQuestionsInQueue });
        setPopupEditQuestion(true);
        return true;
      } catch (e) {
        if (
          e.response?.data?.message?.includes(
            ERROR_MESSAGES.questionController.createQuestion.oneQuestionAtATime
          )
        ) {
          return false;
        }
        return true;
        // TODO: how should we handle error that happens for another reason?
      }
    },
    [mutateQuestions, qid, questions]
  );

  const finishQuestionAndClose = useCallback(
    (
      text: string,
      qt: QuestionType,
      groupable: true,
      router: Router,
      cid: number
    ) => {
      deleteDraftQuestion();
      finishQuestion(text, qt, groupable);
      closeEditModal();
      if (isFirstQuestion) {
        notification.warn({
          style: { cursor: "pointer" },
          message: "Enable Notifications",
          className: "hide-in-percy",
          description:
            "Turn on notifications for when it's almost your turn to get help.",
          placement: "bottomRight",
          duration: 0,
          onClick: () => {
            notification.destroy();
            setIsFirstQuestion(false);
            router.push(`/settings?cid=${cid}`);
          },
        });
      }
    },
    [
      deleteDraftQuestion,
      finishQuestion,
      closeEditModal,
      isFirstQuestion,
      setIsFirstQuestion,
    ]
  );

  useHotkeys(
    "shift+e",
    () => {
      if (studentQuestion) {
        openEditModal();
      }
    },
    [studentQuestion]
  );

  useHotkeys(
    "shift+n",
    () => {
      if (!studentQuestion && queue?.allowQuestions && !queue?.isDisabled) {
        joinQueueOpenModal(false).then((res) => setShowJoinPopconfirm(!res));
      }
    },
    [studentQuestion, queue]
  );

  if (queue && questions) {
    if (!queue.isOpen) {
      return <h1 style={{ marginTop: "50px" }}>The Queue is Closed!</h1>;
    }
    return (
      <>
        <Container>
          <CantFindModal
            visible={studentQuestion?.status === LimboQuestionStatus.CantFind}
            leaveQueue={leaveQueue}
            rejoinQueue={rejoinQueue}
          />
          <StudentRemovedFromQueueModal
            question={studentQuestion}
            leaveQueue={leaveQueue}
            joinQueue={joinQueueAfterDeletion}
          />
          <QueueInfoColumn
            queueId={qid}
            isStaff={false}
            buttons={
              !studentQuestion && (
                <Popconfirm
                  title={
                    <PopConfirmTitle>
                      You already have a question in a queue for this course, so
                      your previous question will be deleted in order to join
                      this queue. Do you want to continue?
                    </PopConfirmTitle>
                  }
                  onConfirm={() => joinQueueOpenModal(true)}
                  okText="Yes"
                  cancelText="No"
                  disabled
                  visible={showJoinPopconfirm}
                  onVisibleChange={setShowJoinPopconfirm}
                >
                  <JoinButton
                    type="primary"
                    disabled={!queue?.allowQuestions || queue?.isDisabled}
                    data-cy="join-queue-button"
                    onClick={async () =>
                      setShowJoinPopconfirm(!(await joinQueueOpenModal(false)))
                    }
                  >
                    Join Queue
                  </JoinButton>
                </Popconfirm>
              )
            }
          />
          <VerticalDivider />
          <QueueListContainer>
            {studentQuestion && (
              <>
                <StudentBanner
                  queueId={qid}
                  editQuestion={openEditModal}
                  leaveQueue={leaveQueue}
                />
                <div style={{ marginTop: "40px" }} />
              </>
            )}
            <QueueQuestions
              questions={questions?.queue}
              studentQuestion={studentQuestion}
            />
          </QueueListContainer>
        </Container>

        <QuestionForm
          visible={
            (questions && !studentQuestion && isJoining) ||
            // && studentQuestion.status !== QuestionStatusKeys.Drafting)
            popupEditQuestion
          }
          question={studentQuestion}
          leaveQueue={leaveQueueAndClose}
          finishQuestion={finishQuestionAndClose}
          position={studentQuestionIndex + 1}
          cancel={closeEditModal}
        />
      </>
    );
  } else {
    return <div />;
  }
}