Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Mantine 7 #529

Draft
wants to merge 52 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e8b3579
update mantine to 7.9.0
sickelap May 5, 2024
34bee7c
partially refactor layout
sickelap May 5, 2024
61b7066
add emotion wrapper
sickelap May 22, 2024
56b5b59
add simple shell for login and signup
sickelap May 22, 2024
9d3868e
update navbar
sickelap May 22, 2024
abd6e34
use simple shell for simple pages
sickelap May 22, 2024
b49fe3c
use user details from the cache
sickelap May 22, 2024
04688fa
partially fix top menu
sickelap May 23, 2024
4bd13ef
refactor routes with new app shells
sickelap May 23, 2024
33d5e84
upgrade mantine to 7.10.0
sickelap May 23, 2024
0c24c6e
use gap property
sickelap May 24, 2024
ae6c5d9
refactor labelProps
sickelap May 24, 2024
8badddd
refactor color= to c=
sickelap May 24, 2024
816baa7
refactor position= to justify=
sickelap May 24, 2024
c750ad5
change icon= with leftSection=
sickelap May 25, 2024
614e25c
replace align= with ta= where needed
sickelap May 25, 2024
575084d
replace weight= with fw= where needed
sickelap May 25, 2024
33e6e43
fix select withinPortal
sickelap May 25, 2024
65b9cd2
replace onTabChange with onChange
sickelap May 25, 2024
d755514
refactor sx= into className and style
sickelap May 25, 2024
443c1f2
fix button size prop
sickelap May 25, 2024
77a3df6
change precision= to decimalScale=
sickelap May 25, 2024
7276531
change gap= to spacing= on SimpleGrid
sickelap May 25, 2024
f4bdd87
update breakpoints for SimpleGrid
sickelap May 25, 2024
4d2e62f
add more TODOs
sickelap May 25, 2024
7ee03d7
re-implement site search (broken semantic search)
sickelap May 28, 2024
93710f1
fix semantic search
sickelap May 28, 2024
7560328
fix action icon for peoples album item
sickelap Sep 3, 2024
0ca8fd2
fix eslint errors
sickelap Sep 4, 2024
66bcbcf
mark three-dot menu as done
sickelap Sep 4, 2024
9ac9a5f
add colors to menu icons
sickelap Sep 4, 2024
203524b
search dropdown icon colors are fine
sickelap Sep 4, 2024
b6b026e
mark tree refactor as optional
sickelap Sep 4, 2024
df42388
update packages lock
sickelap Sep 5, 2024
40f557d
fix menu sidebar toggle (wip)
sickelap Sep 5, 2024
eacc32d
update TODO
sickelap Sep 5, 2024
ebd6c6f
fix lightbox not displaying
sickelap Sep 5, 2024
ffe08ff
fix resize of photo list view when toggling sidebar
sickelap Sep 5, 2024
1cbb78a
upgrade mantine to 7.12.2
sickelap Sep 5, 2024
d4fc756
update TODO
sickelap Sep 5, 2024
c4e1eab
hide burger button for anonymous user in user list
sickelap Sep 5, 2024
fd8d38b
fix album list when toggling sidebar
sickelap Sep 5, 2024
848adc3
add more todo
sickelap Sep 5, 2024
6d5a2fc
update TODO
sickelap Sep 7, 2024
a1cd35b
sort TODOs by priority
sickelap Sep 7, 2024
b768773
organize TODOs
sickelap Sep 12, 2024
deca15d
add todo to fix scroll scrubber
sickelap Sep 12, 2024
3232ef9
add todo item
sickelap Sep 12, 2024
e5f0102
add heading to TODO
sickelap Sep 12, 2024
49fbf86
fix scroll-scrubber
sickelap Sep 15, 2024
95839af
deprioritize logout bug
sickelap Sep 15, 2024
8945b54
add bug to fix warnings in console
sickelap Sep 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Tasks related to upgrade to Mantine 7

- high: fix faces dashboard
- medium: fix logout to redirect to login page
- medium: fix public user list and public photos for authenticated user
- medium: highlight sidebar menu when children menu page is active
- medium: remove the use of useMediaquery
- medium: photolist action menu styling, move actions to the right
- low: fix photo list dropdown filter click area
- low: rework mobile top menu for usability (upload, search, etc.)
- low: fix warnings (in console) related to defaultProps (photo list view, etc.)

- optional: refactor site search with combobox
- optional: migrate from Emotion to css modules (performance improvement)
- optional: refactor tree with latest mantine tree (and remove existing one)
- optional: move color theme switch to top menu for convenience
9 changes: 6 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fixupConfigRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import prettier from "eslint-plugin-prettier";
Expand All @@ -15,9 +16,9 @@ const compat = new FlatCompat({

export default [
{
ignores: ["**/.eslintrc.js", "**/prettier.config.js", "**/proxy.js", "node_modules/*"],
ignores: ["**/eslint.config.mjs", "**/prettier.config.cjs", "**/proxy.js", "node_modules/*"],
},
...compat.extends("airbnb", "airbnb-typescript", "airbnb/hooks", "prettier"),
...fixupConfigRules(compat.extends("airbnb", "airbnb-typescript", "airbnb/hooks", "prettier")),
{
plugins: {
prettier,
Expand All @@ -35,12 +36,14 @@ export default [

parserOptions: {
project: "./tsconfig.eslint.json",
tsconfigRootDir: "/home/niaz/librephotos/librephotos-frontend",
tsconfigRootDir: __dirname,
},
},

rules: {
"import/prefer-default-export": "off",
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"import/no-cycle": "off",
"react/jsx-props-no-spreading": "off",
"react-hooks/exhaustive-deps": "off",
Expand Down
25 changes: 17 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"lint-staged": {
"*.{ts,tsx,js,jsx}": [
"yarn prettier --config ./prettier.config.cjs --write",
"yarn eslint --cache --quiet -c ./.eslint.config.mjs"
"yarn eslint --cache --quiet -c ./eslint.config.mjs"
],
"*.{json,css,scss,md}": [
"yarn prettier --config ./prettier.config.cjs --write"
Expand All @@ -34,14 +34,22 @@
"not op_mini all"
],
"dependencies": {
"@dnd-kit/core": "6.1.0",
"@dnd-kit/sortable": "8.0.0",
"@dnd-kit/utilities": "3.2.2",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.4",
"@mantine/core": "6.0.22",
"@mantine/dates": "6.0.22",
"@mantine/form": "6.0.22",
"@mantine/hooks": "6.0.22",
"@mantine/notifications": "6.0.22",
"@mantine/tiptap": "6.0.22",
"@reduxjs/toolkit": "2.2.6",
"@emotion/serialize": "^1.1.4",
"@emotion/utils": "^1.2.1",
"@mantine/core": "^7.12.2",
"@mantine/dates": "^7.12.2",
"@mantine/emotion": "^7.12.2",
"@mantine/form": "^7.12.2",
"@mantine/hooks": "^7.12.2",
"@mantine/notifications": "^7.12.2",
"@mantine/tiptap": "^7.12.2",
"@popperjs/core": "2.11.8",
"@reduxjs/toolkit": "1.9.7",
"@tabler/icons-react": "^3.0.0",
"@tiptap/core": "^2.3.2",
"@tiptap/extension-document": "^2.3.2",
Expand Down Expand Up @@ -109,6 +117,7 @@
},
"devDependencies": {
"@babel/eslint-parser": "7.24.8",
"@eslint/compat": "^1.1.1",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.7.0",
"@trivago/prettier-plugin-sort-imports": "4.3.0",
Expand Down
169 changes: 60 additions & 109 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import type { ColorScheme } from "@mantine/core";
import { AppShell, ColorSchemeProvider, MantineProvider } from "@mantine/core";
import { ColorSchemeScript, MantineProvider } from "@mantine/core";
import { MantineEmotionProvider } from "@mantine/emotion";
import { Notifications } from "@mantine/notifications";
import React, { useCallback, useMemo, useState } from "react";
import { Cookies, CookiesProvider } from "react-cookie";
import { Route, Routes, useLocation } from "react-router-dom";
import React from "react";
import { Route, Routes } from "react-router-dom";

import "./App.css";
import { FooterMenu } from "./components/menubars/Footer";
import { SideMenuNarrow } from "./components/menubars/SideMenuNarrow";
import { TopMenu } from "./components/menubars/TopMenu";
import { TopMenuPublic } from "./components/menubars/TopMenuPublic";
import { CountStats } from "./components/statistics";
import { Login } from "./containers/login";
import "./i18n";
import { ProtectedRoutes } from "./layouts/PrivateRoute";
import { AppShellProtected } from "./layouts/AppShellProtected";
import { AppShellPublicWithHeader } from "./layouts/AppShellPublicWithHeader";
import { AppShellPublicWithoutHeader } from "./layouts/AppShellPublicWithoutHeader";
import { SearchView } from "./layouts/SearchView";
import { AlbumAuto } from "./layouts/albums/AlbumAuto";
import { AlbumAutoGalleryView } from "./layouts/albums/AlbumAutoGalleryView";
Expand Down Expand Up @@ -47,113 +44,67 @@ import { Profile } from "./layouts/settings/Profile";
import { Settings } from "./layouts/settings/Settings";
import { SharedByMe } from "./layouts/sharing/SharedByMe";
import { SharedWithMe } from "./layouts/sharing/SharedWithMe";
import { selectIsAuthenticated } from "./store/auth/authSelectors";
import { useAppSelector } from "./store/store";

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

export function App() {
const cookies = useMemo(() => 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 = useCallback(
value => {
const nextColorScheme = value || (colorScheme === "dark" ? "light" : "dark");
cookies.set("mantine-color-scheme", nextColorScheme, { maxAge: 60 * 60 * 24 * 356 });
setColorScheme(nextColorScheme);
},
[colorScheme, cookies]
);

const { pathname } = useLocation();

const showMenubar = !!(pathname && !noMenubarPaths.includes(pathname));

const getNavBar = (isMenubarVisible: boolean, isSidebarVisible: boolean, isAuthenticated: boolean) => {
if (isMenubarVisible && isSidebarVisible && isAuthenticated) {
return <SideMenuNarrow />;
}
return <div />;
};

const getHeader = (isMenubarVisible: boolean) => {
if (!isMenubarVisible) {
return <div />;
}
return isAuth ? <TopMenu /> : <TopMenuPublic />;
};

const getFooter = (isAuthenticated: boolean) => (isAuthenticated ? <FooterMenu /> : <div />);

return (
<CookiesProvider>
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
<MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
<>
<ColorSchemeScript defaultColorScheme="auto" />
<MantineProvider defaultColorScheme="auto">
<MantineEmotionProvider>
<Notifications autoClose={3000} zIndex={1001} />
<AppShell
fixed
padding={0}
navbar={getNavBar(showMenubar, showSidebar, isAuth)}
header={getHeader(showMenubar)}
footer={getFooter(isAuth)}
styles={theme => ({
main: {
backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.colors.gray[0],
},
})}
>
<Routes>
<Routes>
<Route element={<AppShellPublicWithoutHeader />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignupPage />} />
</Route>

<Route element={<AppShellPublicWithHeader />}>
<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="photos" element={<OnlyPhotos />} />
<Route path="videos" element={<OnlyVideos />} />
<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/:query" element={<SearchView />} />
<Route path="person/:albumID" element={<AlbumPersonGallery />} />
<Route path="place/:albumID" element={<AlbumPlaceGallery />} />
<Route path="thing/:albumID" element={<AlbumThingGallery />} />
<Route path="event/:albumID" element={<AlbumAutoGalleryView />} />
<Route path="explorer" element={<Explorer />} />
<Route path="albumviewer" element={<AlbumViewer />} />
<Route path="useralbum/:albumID" element={<AlbumUserGallery />} />
<Route path="shared/tome/:which" element={<SharedWithMe />} />
<Route path="shared/fromme/:which" element={<SharedByMe />} />
<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>
</MantineProvider>
</ColorSchemeProvider>
</CookiesProvider>
</Route>

<Route element={<AppShellProtected />}>
<Route index element={<TimestampPhotos />} />
<Route path="things" element={<AlbumThing />} />
<Route path="recent" element={<RecentlyAddedPhotos />} />
<Route path="favorites" element={<FavoritePhotos />} />
<Route path="photos" element={<OnlyPhotos />} />
<Route path="videos" element={<OnlyVideos />} />
<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/:query" element={<SearchView />} />
<Route path="person/:albumID" element={<AlbumPersonGallery />} />
<Route path="place/:albumID" element={<AlbumPlaceGallery />} />
<Route path="thing/:albumID" element={<AlbumThingGallery />} />
<Route path="event/:albumID" element={<AlbumAutoGalleryView />} />
<Route path="explorer" element={<Explorer />} />
<Route path="albumviewer" element={<AlbumViewer />} />
<Route path="useralbum/:albumID" element={<AlbumUserGallery />} />
<Route path="shared/tome/:which" element={<SharedWithMe />} />
<Route path="shared/fromme/:which" element={<SharedByMe />} />
<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>
</MantineEmotionProvider>
</MantineProvider>
</>
);
}
1 change: 1 addition & 0 deletions src/api_client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ export const api = createApi({

export const {
useFetchUserListQuery,
useFetchUserSelfDetailsQuery,
useFetchPredefinedRulesQuery,
useFetchIncompleteFacesQuery,
useLoginMutation,
Expand Down
14 changes: 8 additions & 6 deletions src/components/CustomSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Autocomplete, Avatar, Group, Text, createStyles } from "@mantine/core";
import type { AutocompleteItem } from "@mantine/core";
import { Autocomplete, Avatar, Group, Text } from "@mantine/core";
// import type { AutocompleteItem } from "@mantine/core";
import { createStyles } from "@mantine/emotion";
import { useInterval, useViewportSize } from "@mantine/hooks";
import {
IconAlbum as Album,
Expand Down Expand Up @@ -65,7 +66,7 @@ const SearchSuggestionItem = forwardRef<HTMLDivElement, SearchSuggestion>(
({ icon = <Search />, value, ...rest }: SearchSuggestion, ref) => (
/* eslint-disable react/jsx-props-no-spreading */
<div ref={ref} {...rest}>
<Group noWrap>
<Group wrap="nowrap">
{cloneElement(icon as React.ReactElement, { size: 20 })}
<Text>{value}</Text>
</Group>
Expand All @@ -89,7 +90,7 @@ export function CustomSearch() {
const { width } = useViewportSize();
const dispatch = useAppDispatch();
const [value, setValue] = useState("");
const [searchSuggestions, setSearchSuggestions] = useState<Array<AutocompleteItem>>([]);
const [searchSuggestions, setSearchSuggestions] = useState<Array<any>>([]);
const [searchPlaceholder, setSearchPlaceholder] = useState("");
const searchBarWidth = width - width / 2.2;
const { data: searchExamples } = useSearchExamplesQuery();
Expand Down Expand Up @@ -138,7 +139,8 @@ export function CustomSearch() {
[placeAlbums, searchExamples, thingAlbums, userAlbums, people]
);

function search(item: AutocompleteItem) {
// TODO: replace any with custom autocomplete item type
function search(item: any) {
switch (item.type) {
case undefined:
case SuggestionType.EXAMPLE:
Expand Down Expand Up @@ -180,7 +182,7 @@ export function CustomSearch() {
<Autocomplete
width={searchBarWidth}
data={searchSuggestions}
icon={<Search size={14} className={classes.icon} />}
leftSection={<Search size={14} className={classes.icon} />}
placeholder={searchPlaceholder}
itemComponent={SearchSuggestionItem}
limit={10}
Expand Down
Loading