Skip to content

Commit

Permalink
fixed the rendering loop within the <Navigate .../> component
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Einars <[email protected]>
  • Loading branch information
polaroidkidd committed Jul 18, 2022
1 parent 75e51c8 commit 9807cc7
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 103 deletions.
108 changes: 53 additions & 55 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AppShell, ColorScheme, ColorSchemeProvider, MantineProvider } from "@ma
import { NotificationsProvider } from "@mantine/notifications";
import React, { useState } from "react";
import { Cookies, CookiesProvider } from "react-cookie";
import { Route, Routes } from "react-router-dom";
import { Route, Routes, useLocation } from "react-router-dom";
import "semantic-ui-css/semantic.min.css";

import "./App.css";
Expand All @@ -14,7 +14,7 @@ import { TopMenuPublic } from "./components/menubars/TopMenuPublic";
import { CountStats } from "./components/statistics";
import { Login } from "./containers/login";
import "./i18n";
import { ProtectedRoute } from "./layouts/PrivateRoute";
import { ProtectedRoutes } from "./layouts/PrivateRoute";
import { SearchView } from "./layouts/SearchView";
import { AlbumAuto } from "./layouts/albums/AlbumAuto";
import { AlbumPeople } from "./layouts/albums/AlbumPeople";
Expand Down Expand Up @@ -43,25 +43,29 @@ import { AdminPage } from "./layouts/settings/AdminPage";
import { Library } from "./layouts/settings/Library";
import { Profile } from "./layouts/settings/Profile";
import { Settings } from "./layouts/settings/Settings";
import { selectIsAuthenticated } from "./store/auth/authSelectors";
import { useAppSelector } from "./store/store";

const noMenubarPaths = ["/signup", "/login"];

export function App() {
const cookies = new Cookies();
const showSidebar = useAppSelector(store => store.ui.showSidebar);
const isAuth = useAppSelector(selectIsAuthenticated);
const [colorScheme, setColorScheme] = useState<ColorScheme>(
cookies.get("mantine-color-scheme") ? cookies.get("mantine-color-scheme") : "light"
);
const toggleColorScheme = value => {

function toggleColorScheme(value) {
const nextColorScheme = value || (colorScheme === "dark" ? "light" : "dark");
cookies.set("mantine-color-scheme", nextColorScheme);
setColorScheme(nextColorScheme);
};
const showSidebar = useAppSelector(store => store.ui.showSidebar);
const location = useAppSelector(store => store.router.location);
const auth = useAppSelector(store => store.auth);
}

const { pathname } = useLocation();

// @ts-ignore
const showMenubar = location.pathname && !noMenubarPaths.includes(location.pathname);
const showMenubar = pathname && !noMenubarPaths.includes(pathname);

return (
<CookiesProvider>
Expand All @@ -71,10 +75,8 @@ export function App() {
<AppShell
fixed
padding={5}
navbar={
showMenubar && showSidebar ? auth.access ? <SideMenuNarrow /> : <SideMenuNarrowPublic /> : <div />
}
header={showMenubar ? auth.access ? <TopMenu /> : <TopMenuPublic /> : <div />}
navbar={showMenubar && showSidebar ? isAuth ? <SideMenuNarrow /> : <SideMenuNarrowPublic /> : <div />}
header={showMenubar ? isAuth ? <TopMenu /> : <TopMenuPublic /> : <div />}
footer={<FooterMenu />}
styles={theme => ({
main: {
Expand All @@ -83,55 +85,51 @@ export function App() {
})}
>
<Routes>
<Route path="/signup" element={<SignupPage />} />

<Route path="/public/:username" element={<UserPublicPage />} />

<Route path="/users" element={<PublicUserList />} />

<Route path="/user/:username" element={<UserPublicPage />} />

<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignupPage />} />
<Route path="public/:username" element={<UserPublicPage />} />
<Route path="users" element={<PublicUserList />} />
<Route path="user/:username" element={<UserPublicPage />} />
<Route element={<ProtectedRoutes />}>
<Route index element={<TimestampPhotos />} />
<Route path="/things" element={<AlbumThing />} />
<Route path="/recent" element={<RecentlyAddedPhotos />} />
<Route path="/favorites" element={<FavoritePhotos />} />
<Route path="/deleted" element={<DeletedPhotos />} />
<Route path="/hidden" element={<HiddenPhotos />} />
<Route path="/notimestamp" element={<NoTimestampPhotosView />} />
<Route path="/useralbums" element={<AlbumUser />} />
<Route path="/places" element={<AlbumPlace />} />
<Route path="/people" element={<AlbumPeople />} />
<Route path="/events" element={<AlbumAuto />} />
<Route path="/statistics" element={<Statistics />} />
<Route path="/settings" element={<Settings />} />
<Route path="/profile" element={<Profile />} />
<Route path="/library" element={<Library />} />
<Route path="/faces" element={<FaceDashboard />} />
<Route path="/search" element={<SearchView />} />
<Route path="/person/:albumID" element={<AlbumPersonGallery />} />
<Route path="things" element={<AlbumThing />} />
<Route path="recent" element={<RecentlyAddedPhotos />} />
<Route path="favorites" element={<FavoritePhotos />} />
<Route path="deleted" element={<DeletedPhotos />} />
<Route path="hidden" element={<HiddenPhotos />} />
<Route path="notimestamp" element={<NoTimestampPhotosView />} />
<Route path="useralbums" element={<AlbumUser />} />
<Route path="places" element={<AlbumPlace />} />
<Route path="people" element={<AlbumPeople />} />
<Route path="events" element={<AlbumAuto />} />
<Route path="statistics" element={<Statistics />} />
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
<Route path="library" element={<Library />} />
<Route path="faces" element={<FaceDashboard />} />
<Route path="search" element={<SearchView />} />
<Route path="person/:albumID" element={<AlbumPersonGallery />} />
{/* TODO Rewrite using react-router-v6 */}
<Route path="/place/:albumID" element={<AlbumPlaceGallery />} />
<Route path="place/:albumID" element={<AlbumPlaceGallery />} />
{/* TODO Rewrite using react-router-v6 */}
<Route path="/thing/:albumID" element={<AlbumThingGallery />} />
<Route path="thing/:albumID" element={<AlbumThingGallery />} />
{/* TODO Rewrite using react-router-v6 */}
{/* <Route path="/event/:albumID" element={<AlbumAutoGalleryView />} /> */}
<Route path="/explorer" element={<Explorer />} />
<Route path="/albumviewer" element={<AlbumViewer />} />
<Route path="/useralbum/:albumID" element={<AlbumUserGallery />} />
{/* <Route path="event/:albumID" element={<AlbumAutoGalleryView />} /> */}
<Route path="explorer" element={<Explorer />} />
<Route path="albumviewer" element={<AlbumViewer />} />
<Route path="useralbum/:albumID" element={<AlbumUserGallery />} />
{/* TODO Rewrite using react-router-v6 */}
{/* <Route path="/shared/tome/:which" element={<SharedToMe />} /> */}
{/* <Route path="shared/tome/:which" element={<SharedToMe />} /> */}
{/* /!* TODO Rewrite using react-router-v6 *!/ */}
{/* /!* <Route path="/shared/fromme/:which" element={<SharedFromMe />} /> *!/ */}
<Route path="/admin" element={<AdminPage />} />
<Route path="/map" element={<PhotoMap />} />
<Route path="/placetree" element={<LocationTree />} />
<Route path="/wordclouds" element={<WordClouds />} />
<Route path="/timeline" element={<Timeline />} />
<Route path="/socialgraph" element={<Graph />} />
<Route path="/facescatter" element={<FaceScatter />} />
<Route path="/countstats" element={<CountStats />} />
{/* /!* <Route path="shared/fromme/:which" element={<SharedFromMe />} /> *!/ */}
<Route path="admin" element={<AdminPage />} />
<Route path="map" element={<PhotoMap />} />
<Route path="placetree" element={<LocationTree />} />
<Route path="wordclouds" element={<WordClouds />} />
<Route path="timeline" element={<Timeline />} />
<Route path="socialgraph" element={<Graph />} />
<Route path="facescatter" element={<FaceScatter />} />
<Route path="countstats" element={<CountStats />} />
</Route>
</Routes>
</AppShell>
Expand Down
4 changes: 2 additions & 2 deletions src/components/facedashboard/FaceComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function FaceComponent(props: Props) {
<Center>
<Tooltip
opened={tooltipOpened && props.activeItem === 1}
label={t("settings.confidencepercentage", {
label={t<string>("settings.confidencepercentage", {
percentage: (props.cell.person_label_probability * 100).toFixed(1),
})}
position="bottom"
Expand Down Expand Up @@ -94,7 +94,7 @@ export function FaceComponent(props: Props) {
<Center>
<Tooltip
opened={tooltipOpened && props.activeItem === 1}
label={t("settings.confidencepercentage", {
label={t<string>("settings.confidencepercentage", {
percentage: (props.cell.person_label_probability * 100).toFixed(1),
})}
position="bottom"
Expand Down
2 changes: 1 addition & 1 deletion src/components/settings/SortableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function SortableItem({ item, addItem, addItemFunction, removeItemFunctio
<li>{t(`rules.${prop[0]}`, { rule: prop[1] })}</li>
) : (
<li>
{prop[0]}: {prop[1]}
{prop[0] as string}: {prop[1] as string}
</li>
)
)}
Expand Down
27 changes: 7 additions & 20 deletions src/containers/login.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { useEffect } from "react";
import { Navigate, useLocation } from "react-router-dom";

import { fetchUserList } from "../actions/utilActions";
import { FirstTimeSetupPage } from "../layouts/login/FirstTimeSetupPage";
import { LoginPage } from "../layouts/login/LoginPage";
import { selectIsAuthenticated } from "../store/auth/authSelectors";
import { useAppDispatch, useAppSelector } from "../store/store";

export interface LocationState {
Expand All @@ -14,31 +12,20 @@ export interface LocationState {
}

export function Login(): JSX.Element {
const isAuthenticated = useAppSelector(selectIsAuthenticated);
const location = useLocation();

const { userList, fetchedUserList } = useAppSelector(state => state.util);
const dispatch = useAppDispatch();

useEffect(() => {
dispatch(fetchUserList());
}, [dispatch]);

// if (isAuthenticated) {
// if (location.state) {
// // return <Navigate to="/" />;
// return <Navigate to="/" state={{ from: location }} />;
// }
// return <Navigate to="/" />;
// }

// if (fetchedUserList && userList.length === 0) {
// return (
// <div className="login-page">
// <FirstTimeSetupPage />
// </div>
// );
// }
if (fetchedUserList && userList.length === 0) {
return (
<div className="login-page">
<FirstTimeSetupPage />
</div>
);
}

return (
<div className="login-page">
Expand Down
11 changes: 4 additions & 7 deletions src/layouts/PrivateRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import React from "react";
import { Navigate, Outlet } from "react-router-dom";
import { Navigate, Outlet, useLocation } from "react-router-dom";

import { selectIsAuthenticated } from "../store/auth/authSelectors";
import { useAppSelector } from "../store/store";

export function ProtectedRoute() {
export function ProtectedRoutes() {
const isAuth = useAppSelector(selectIsAuthenticated);
const { pathname } = useLocation();

if (!isAuth) {
return <Navigate to="/login" replace />;
}

return <Outlet />;
return isAuth ? <Outlet /> : <Navigate to="login" state={{ from: pathname }} replace />;
}
6 changes: 4 additions & 2 deletions src/layouts/albums/AlbumAutoGalleryView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import _ from "lodash";
import moment from "moment";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Calendar, Map2, SettingsAutomation, Users } from "tabler-icons-react";
import { Calendar, Map2, SettingsAutomation, Users } from "tabler-icons-react";

import { fetchAlbumsAutoGalleries } from "../../actions/albumsActions";
import { fetchPhotoDetail } from "../../actions/photosActions";
Expand Down Expand Up @@ -143,7 +143,9 @@ export const AlbumAutoGalleryView = (props: Props) => {
<div>
<Title order={5}>{`Day ${i + 1} - ${moment(v[0]).format("MMMM Do YYYY")}`}</Title>
<Text color="dimmed">
<Breadcrumbs separator="/">{_.uniq(locations).map(e => ({ key: e, content: e }))}</Breadcrumbs>
<Breadcrumbs separator="/">
<>{_.uniq(locations).map(e => ({ key: e, content: e }))}</>
</Breadcrumbs>
</Text>
</div>
</Group>
Expand Down
16 changes: 7 additions & 9 deletions src/layouts/login/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useForm } from "@mantine/form";
import type { FormEvent } from "react";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { Lock, User } from "tabler-icons-react";

import { fetchSiteSettings } from "../../actions/utilActions";
Expand All @@ -31,9 +31,13 @@ export function LoginPage(): JSX.Element {
const dark = colorScheme === "dark";
const dispatch = useAppDispatch();
const { t } = useTranslation();
const location = useLocation();
console.info("location: ", location);
// @ts-ignore
const from = location.state?.from || "/";

const siteSettings = useAppSelector(selectSiteSettings);
const [login, { isSuccess, isLoading }] = useLoginMutation();
const [login, { isLoading }] = useLoginMutation();
const form = useForm({
initialValues: {
username: "",
Expand All @@ -46,19 +50,13 @@ export function LoginPage(): JSX.Element {
fetchSiteSettings(dispatch);
}, [dispatch]);

useEffect(() => {
if (isSuccess) {
navigate("/");
}
}, [navigate, isSuccess]);

function onSubmit(event: FormEvent<HTMLFormElement>): void {
event.preventDefault();
void login({ username: form.values.username.toLowerCase(), password: form.values.password });
}

if (isAuth) {
navigate("/");
navigate(from);
}
return (
<div
Expand Down
13 changes: 6 additions & 7 deletions src/layouts/photos/TimestampPhotos.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import _ from "lodash";
import React, { useCallback, useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Photo } from "tabler-icons-react";

Expand All @@ -8,16 +7,16 @@ import { PhotoListView } from "../../components/photolist/PhotoListView";
import { PhotosState, PhotosetType } from "../../reducers/photosReducer";
import { useAppDispatch, useAppSelector } from "../../store/store";

type fetchedGroup = {
interface IFetchedGroup {
id: string;
page: number;
};
}

export function TimestampPhotos() {
const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const [group, setGroup] = useState({} as fetchedGroup);
const [group, setGroup] = useState({} as IFetchedGroup);
useEffect(() => {
if (group.id && group.page) {
fetchAlbumDate(dispatch, {
Expand All @@ -26,13 +25,13 @@ export function TimestampPhotos() {
photosetType: PhotosetType.TIMESTAMP,
});
}
}, [group.id, group.page]);
}, [dispatch, group.id, group.page]);

useEffect(() => {
if (fetchedPhotosetType !== PhotosetType.TIMESTAMP) {
fetchAlbumDateList(dispatch, { photosetType: PhotosetType.TIMESTAMP });
}
}, [dispatch]); // Only run on first render
}, [dispatch]);

const getAlbums = (visibleGroups: any) => {
visibleGroups.forEach((group: any) => {
Expand Down
3 changes: 3 additions & 0 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import { worker } from "./worker/workerSlice";

const { createReduxHistory, routerMiddleware, routerReducer } = createReduxHistoryContext({
history: createBrowserHistory(),
reduxTravelling: true,
showHistoryAction: true,
savePreviousLocations: 100,
});

export const store = configureStore({
Expand Down

0 comments on commit 9807cc7

Please sign in to comment.