From 9f60330f4c4f2f6be756630e2beb28f18d9d79a5 Mon Sep 17 00:00:00 2001 From: Genadijus Paleckis Date: Tue, 14 Nov 2023 14:26:33 +0000 Subject: [PATCH] more refactoring for albums to use RTK (#410) * place albums RTK * add keys and update type * fix explorer * delete all auto albums RTK * cleanup unused code * add rtk endpoints for album sharing * cleanup duplication --- src/actions/albumsActions.ts | 148 +------------------ src/api_client/albums/auto.ts | 47 +++++- src/api_client/albums/places.ts | 17 ++- src/api_client/albums/user.ts | 22 ++- src/layouts/albums/AlbumAutoGalleryView.tsx | 8 +- src/layouts/albums/AlbumPlace.tsx | 6 +- src/layouts/albums/AlbumPlaceGallery.tsx | 26 +--- src/layouts/albums/Explorer.tsx | 149 ++++++++++---------- src/layouts/settings/AdminPage.tsx | 148 +++++++++---------- src/layouts/settings/Library.tsx | 19 +-- src/util/util.ts | 5 +- 11 files changed, 258 insertions(+), 337 deletions(-) diff --git a/src/actions/albumsActions.ts b/src/actions/albumsActions.ts index 75240cef..9de9f7e4 100644 --- a/src/actions/albumsActions.ts +++ b/src/actions/albumsActions.ts @@ -1,108 +1,18 @@ -import { showNotification } from "@mantine/notifications"; import _ from "lodash"; import type { Dispatch } from "react"; -import { z } from "zod"; import { Server } from "../api_client/apiClient"; -import i18n from "../i18n"; import { PhotosetType } from "../reducers/photosReducer"; import type { AppDispatch } from "../store/store"; import { addTempElementsToGroups, getPhotosFlatFromGroupedByDate } from "../util/util"; -import type { AutoAlbumInfo, UserAlbumDetails, UserAlbumInfo } from "./albumActions.types"; -import { - FetchAutoAlbumsListResponseSchema, - FetchDateAlbumsListResponseSchema, - FetchUserAlbumsListResponseSchema, - FetchUserAlbumsSharedResponseSchema, - PlaceAlbumSchema, - UserAlbumInfoSchema, - UserAlbumSchema, -} from "./albumActions.types"; -import type { DatePhotosGroup, IncompleteDatePhotosGroup } from "./photosActions.types"; +import type { UserAlbumInfo } from "./albumActions.types"; +import { FetchDateAlbumsListResponseSchema, FetchUserAlbumsSharedResponseSchema } from "./albumActions.types"; +import type { IncompleteDatePhotosGroup } from "./photosActions.types"; import { IncompleteDatePhotosGroupSchema } from "./photosActions.types"; -export function fetchUserAlbumsList() { - return function cb(dispatch: Dispatch) { - dispatch({ type: "FETCH_USER_ALBUMS_LIST" }); - Server.get("albums/user/list/") - .then(response => { - const data = FetchUserAlbumsListResponseSchema.parse(response.data); - const userAlbumInfoList: UserAlbumInfo[] = data.results; - dispatch({ - type: "FETCH_USER_ALBUMS_LIST_FULFILLED", - payload: userAlbumInfoList, - }); - }) - .catch(err => { - dispatch({ type: "FETCH_USER_ALBUMS_LIST_REJECTED", payload: err }); - }); - }; -} - -export const FETCH_USER_ALBUM = "FETCH_USER_ALBUM"; export const FETCH_USER_ALBUM_FULFILLED = "FETCH_USER_ALBUM_FULFILLED"; export const FETCH_USER_ALBUM_REJECTED = "FETCH_USER_ALBUM_REJECTED"; -export function fetchUserAlbum(album_id: number) { - return function cb(dispatch: Dispatch) { - dispatch({ type: FETCH_USER_ALBUM }); - Server.get(`albums/user/${album_id}/`) - .then(response => { - const data = UserAlbumSchema.parse(response.data); - const photosGroupedByDate: DatePhotosGroup[] = data.grouped_photos; - const albumDetails: UserAlbumDetails = data; - dispatch({ - type: FETCH_USER_ALBUM_FULFILLED, - payload: { - photosGroupedByDate, - photosFlat: getPhotosFlatFromGroupedByDate(photosGroupedByDate), - albumDetails, - }, - }); - }) - .catch(err => { - dispatch({ type: FETCH_USER_ALBUM_REJECTED, payload: err }); - }); - }; -} - -const PlaceAlbumResponseSchema = z.object({ results: PlaceAlbumSchema }); - -export function fetchPlaceAlbum(album_id: string) { - return function cb(dispatch: Dispatch) { - dispatch({ type: "FETCH_PLACE_ALBUMS" }); - Server.get(`albums/place/${album_id}/`) - .then(response => { - const data = PlaceAlbumResponseSchema.parse(response.data); - dispatch({ - type: "FETCH_PLACE_ALBUMS_FULFILLED", - payload: data, - }); - }) - .catch(err => { - dispatch({ type: "FETCH_PLACE_ALBUMS_REJECTED", payload: err }); - }); - }; -} - -export function fetchAutoAlbumsList() { - return function cb(dispatch: Dispatch) { - dispatch({ type: "FETCH_AUTO_ALBUMS_LIST" }); - Server.get("albums/auto/list/") - .then(response => { - const data = FetchAutoAlbumsListResponseSchema.parse(response.data); - const autoAlbumsList: AutoAlbumInfo[] = data.results; - dispatch({ - type: "FETCH_AUTO_ALBUMS_LIST_FULFILLED", - payload: autoAlbumsList, - }); - }) - .catch(err => { - dispatch({ type: "FETCH_AUTO_ALBUMS_LIST_REJECTED", payload: err }); - }); - }; -} - type AlbumDateListOptions = { photosetType: PhotosetType; person_id?: number; @@ -187,58 +97,6 @@ export function fetchAlbumDate(dispatch: AppDispatch, options: AlbumDateOption) }); } -export function deleteAllAutoAlbum() { - return function cb(dispatch: Dispatch) { - dispatch({ type: "DELETE_All_AUTO_ALBUM" }); - Server.post(`/albums/auto/delete_all/`) - .then(() => { - dispatch({ type: "DELETE_ALL_AUTO_ALBUM_FULFILLED" }); - dispatch(fetchAutoAlbumsList()); - showNotification({ - message: i18n.t("toasts.deleteallautoalbums"), - title: i18n.t("toasts.deleteallautoalbumstitle"), - color: "teal", - }); - }) - .catch(err => { - dispatch({ type: "DELETE_ALL_AUTO_ALBUM_REJECTED", payload: err }); - }); - }; -} - -// share user album -export function setUserAlbumShared(album_id: number, target_user_id: string, val_shared: boolean) { - return function cb(dispatch: Dispatch) { - dispatch({ type: "SET_ALBUM_USER_SHARED" }); - Server.post("useralbum/share/", { shared: val_shared, album_id, target_user_id }) - .then(response => { - const userAlbumInfo: UserAlbumInfo = UserAlbumInfoSchema.parse(response.data); - dispatch({ - type: "SET_ALBUM_USER_SHARED_FULFILLED", - payload: userAlbumInfo, - }); - dispatch(fetchUserAlbum(album_id)); - - if (val_shared) { - showNotification({ - message: i18n.t("toasts.sharingalbum"), - title: i18n.t("toasts.sharingalbumtitle"), - color: "teal", - }); - } else { - showNotification({ - message: i18n.t("toasts.unsharingalbum"), - title: i18n.t("toasts.unsharingalbumtitle"), - color: "teal", - }); - } - }) - .catch(err => { - dispatch({ type: "SET_ALBUM_USER_SHARED_FULFILLED", payload: err }); - }); - }; -} - export function fetchUserAlbumsSharedToMe() { return function cb(dispatch: Dispatch) { dispatch({ type: "FETCH_ALBUMS_SHARED_TO_ME" }); diff --git a/src/api_client/albums/auto.ts b/src/api_client/albums/auto.ts index 19558a09..d3e6e815 100644 --- a/src/api_client/albums/auto.ts +++ b/src/api_client/albums/auto.ts @@ -29,6 +29,7 @@ enum Endpoints { fetchAutoAlbum = "fetchAutoAlbum", deleteAutoAlbum = "deleteAutoAlbum", deleteAllAutoAlbums = "deleteAllAutoAlbums", + generateAutoAlbums = "generateAutoAlbums", } export const autoAlbumsApi = api @@ -50,8 +51,36 @@ export const autoAlbumsApi = api }), transformResponse: (response, meta, query) => { showNotification({ - message: i18n.t("toasts.deletealbum", query), - title: i18n.t("toasts.deletealbumtitle"), + message: i18n.t("toasts.deletealbum", query), + title: i18n.t("toasts.deletealbumtitle"), + color: "teal", + }); + }, + }), + [Endpoints.deleteAllAutoAlbums]: builder.mutation({ + query: () => ({ + url: `albums/auto/delete_all/`, + method: "POST", + body: {}, + }), + transformResponse: () => { + showNotification({ + message: i18n.t("toasts.deleteallautoalbums"), + title: i18n.t("toasts.deleteallautoalbumstitle"), + color: "teal", + }); + }, + }), + [Endpoints.generateAutoAlbums]: builder.mutation({ + query: () => ({ + url: `autoalbumgen/`, + method: "POST", + body: {}, + }), + transformResponse: () => { + showNotification({ + message: i18n.t("toasts.generateeventalbums"), + title: i18n.t("toasts.generateeventalbumstitle"), color: "teal", }); }, @@ -70,7 +99,19 @@ export const autoAlbumsApi = api [Endpoints.deleteAutoAlbum]: { invalidatesTags: ["AutoAlbums", "AutoAlbum"], }, + [Endpoints.deleteAllAutoAlbums]: { + invalidatesTags: ["AutoAlbums", "AutoAlbum"], + }, + [Endpoints.generateAutoAlbums]: { + invalidatesTags: ["AutoAlbums", "AutoAlbum"], + }, }, }); -export const { useFetchAutoAlbumsQuery, useLazyFetchAutoAlbumQuery, useDeleteAutoAlbumMutation } = autoAlbumsApi; +export const { + useFetchAutoAlbumsQuery, + useLazyFetchAutoAlbumQuery, + useDeleteAutoAlbumMutation, + useDeleteAllAutoAlbumsMutation, + useGenerateAutoAlbumsMutation, +} = autoAlbumsApi; diff --git a/src/api_client/albums/places.ts b/src/api_client/albums/places.ts index e087a824..f7327b78 100644 --- a/src/api_client/albums/places.ts +++ b/src/api_client/albums/places.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { PhotoHashSchema } from "../../actions/photosActions.types"; +import { DatePhotosGroupSchema, PhotoHashSchema } from "../../actions/photosActions.types"; import { api } from "../api"; const AlbumInfoSchema = z.object({ @@ -25,8 +25,17 @@ const PlacesAlbumsResponseSchema = z.object({ const LocationClustersResponseSchema = z.array(z.array(z.union([z.number(), z.string()]))); export type LocationClusters = z.infer; +const PlaceAlbumSchema = z.object({ + id: z.string(), + title: z.string(), + grouped_photos: DatePhotosGroupSchema.array(), +}); +type PlaceAlbum = z.infer; +const PlaceAlbumResponseSchema = z.object({ results: PlaceAlbumSchema }); + enum Endpoints { fetchPlacesAlbums = "fetchPlacesAlbums", + fetchPlaceAlbum = "fetchPlaceAlbum", fetchLocationClusters = "fetchLocationClusters", } @@ -37,6 +46,10 @@ export const placesAlbumsApi = api query: () => "albums/place/list/", transformResponse: response => PlacesAlbumsResponseSchema.parse(response).results, }), + [Endpoints.fetchPlaceAlbum]: builder.query({ + query: album_id => `albums/place/${album_id}/`, + transformResponse: response => PlaceAlbumResponseSchema.parse(response).results, + }), [Endpoints.fetchLocationClusters]: builder.query({ query: () => "locclust/", transformResponse: response => LocationClustersResponseSchema.parse(response), @@ -52,4 +65,4 @@ export const placesAlbumsApi = api }, }); -export const { useFetchPlacesAlbumsQuery, useFetchLocationClustersQuery } = placesAlbumsApi; +export const { useFetchPlacesAlbumsQuery, useFetchLocationClustersQuery, useFetchPlaceAlbumQuery } = placesAlbumsApi; diff --git a/src/api_client/albums/user.ts b/src/api_client/albums/user.ts index 22ddb29e..e61e4b2f 100644 --- a/src/api_client/albums/user.ts +++ b/src/api_client/albums/user.ts @@ -47,6 +47,8 @@ enum Endpoints { addPhotoToUserAlbum = "addPhotoToUserAlbum", setUserAlbumCover = "setUserAlbumCover", shareUserAlbum = "shareUserAlbum", + fetchAlbumsSharedByMe = "fetchAlbumsSharedByMe", + fetchAlbumsSharedWithMe = "fetchAlbumsSharedWithMe", } type DeleteUserAlbumParams = { @@ -217,10 +219,18 @@ export const userAlbumsApi = api } }, }), + [Endpoints.fetchAlbumsSharedByMe]: builder.query({ + query: () => "albums/user/shared/fromme/", + transformResponse: response => UserAlbumListResponseSchema.parse(response).results, + }), + [Endpoints.fetchAlbumsSharedWithMe]: builder.query({ + query: () => "albums/user/shared/tome/", + transformResponse: response => UserAlbumListResponseSchema.parse(response).results, + }), }), }) - .enhanceEndpoints<"UserAlbums" | "UserAlbum">({ - addTagTypes: ["UserAlbums", "UserAlbum"], + .enhanceEndpoints<"UserAlbums" | "UserAlbum" | "UserAlbumsSharedByMe" | "UserAlbumsSharedWithMe">({ + addTagTypes: ["UserAlbums", "UserAlbum", "UserAlbumsSharedWithMe", "UserAlbumsSharedByMe"], endpoints: { [Endpoints.fetchUserAlbums]: { providesTags: ["UserAlbums"], @@ -248,7 +258,13 @@ export const userAlbumsApi = api }, [Endpoints.shareUserAlbum]: { // TODO(sickelap): invalidate only the album that was shared - invalidatesTags: ["UserAlbums", "UserAlbum"], + invalidatesTags: ["UserAlbums", "UserAlbum", "UserAlbumsSharedByMe"], + }, + [Endpoints.fetchAlbumsSharedByMe]: { + providesTags: ["UserAlbumsSharedByMe"], + }, + [Endpoints.fetchAlbumsSharedWithMe]: { + providesTags: ["UserAlbumsSharedWithMe"], }, }, }); diff --git a/src/layouts/albums/AlbumAutoGalleryView.tsx b/src/layouts/albums/AlbumAutoGalleryView.tsx index 4229359c..bdb5e623 100644 --- a/src/layouts/albums/AlbumAutoGalleryView.tsx +++ b/src/layouts/albums/AlbumAutoGalleryView.tsx @@ -45,7 +45,7 @@ export function AlbumAutoGalleryView() { setEntrySquareSize((width - SIDEBAR_WIDTH - 20) / numEntrySquaresPerRow); }, [width]); - function getPhotoDetails(image_hash) { + function getPhotoDetails(image_hash: string) { dispatch(photoDetailsApi.endpoints.fetchPhotoDetails.initiate(image_hash)); } @@ -119,6 +119,7 @@ export function AlbumAutoGalleryView() { {album.people.slice(0, 5).map(person => ( {location}); + const uniqueLocations = _.uniq(locations).map(location => {location}); return ( -
+