Skip to content

Commit

Permalink
Allow updating custom metadata (#1149)
Browse files Browse the repository at this point in the history
* feat(backend): add mutation to update a custom metadata

* feat(migrations): add column to metadata for created by user id

* feat(migrations): update new column for existing metadata items

* feat(models/database): add new column to tables

* feat(backend): respect new column

* feat(services/miscellaneous): add validation before allowing to update custom metadata

* feat(services/miscellaneous): add validation before updating custom metadata

* feat(backend): send details about created by user id for metadata details

* feat(frontend): add button to edit metadata

* feat(frontend): change name of page

* chore(frontend): add action to schema

* chore(frontend): change name of page

* fix(services/miscellaneous): delete old images

* fix(services/miscellaneous): delete old videos

* fix(services/miscellaneous): set correct id for updating custom metadata

* feat(frontend): allow updating metadata

* ci: Run CI

* feat(frontend): add loading when image is uploading

* fix(services/fitness): do not discard user exercise settings during workout revision

* chore(backend): require entire setting when updating exercise settings

* feat(frontend): update exercise settings from the frontend

* refactor(frontend): change variable names

* feat(backend): accept entire user preferences when updating it

* feat(frontend): update preferences from the client side

* ci: Run CI

* refactor(frontend): change name of action

* perf(frontend): display season episodes in separate modal

* perf(frontend): display show seasons using virtualized list

* build(frontend): mantine modal deps

* feat(frontend): add mantine modals provider

* refactor(frontend): change name of file

* refactor(frontend): remove nested if

* fix(frontend): do not hard reload when navigating to log workout

* feat(frontend): open confirmation modal using mantine

* chore(frontend): remove react confirm code

* ci: Run CI

* refactor(frontend): move form inside component

* feat(frontend): ask for confirmation before deploying job

* refactor(frontend): remove useless if checks for confirmations

* feat(backend): add mutation to refresh user recommendation key

* feat(services/user): change recommendations if cache key is present

* feat(frontend): allow refreshing recommendations

* ci: Run CI

* fix(frontend): make all section titles the same size on mobile screens

* feat(backend): add crate for lock service

* feat(services/lock): add implementation to lock service

* feat(backend): remove lock service

* feat(backend): acquire lock correctly

* chore(utils/common): remove useless imports

* refactor(backend): remove stuff

* feat(backend): extract async function to sleep in tokio

* fix(utils/dependent): do not sleep while updating

* refactor(frontend): different modal for season episodes
  • Loading branch information
IgnisDa authored Dec 26, 2024
1 parent 22036d4 commit 8442c5c
Show file tree
Hide file tree
Showing 63 changed files with 2,804 additions and 2,358 deletions.
9 changes: 5 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ serde_with = { version = "=3.11.0", features = ["chrono_0_4"] }
serde-xml-rs = "=0.6.0"
slug = "=0.1.6"
sonarr-api-rs = "=3.0.0"
sqlx = { version = "=0.8.2", default-features = false, features = ["postgres"] }
strum = { version = "=0.26.3", features = ["derive"] }
struson = { version = "=0.6.0", features = ["serde"] }
reqwest = { version = "=0.12.9", features = ["json", "stream"] }
Expand Down
60 changes: 29 additions & 31 deletions apps/frontend/app/components/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
convertDecimalToThreePointSmiley,
dayjsLib,
getSurroundingElements,
openConfirmationModal,
reviewYellow,
} from "~/lib/generals";
import {
Expand All @@ -88,7 +89,6 @@ import {
import { useReviewEntity } from "~/lib/state/media";
import type { action } from "~/routes/actions";
import classes from "~/styles/common.module.css";
import { confirmWrapper } from "./confirmation";
import {
ExerciseDisplayItem,
WorkoutDisplayItem,
Expand Down Expand Up @@ -541,24 +541,24 @@ export const ReviewItemDisplay = (props: {
<IconEdit size={16} />
</ActionIcon>
<ActionIcon
onClick={async () => {
const conf = await confirmWrapper({
confirmation:
"Are you sure you want to delete this review? This action cannot be undone.",
});
if (conf)
deleteReviewFetcher.submit(
{
shouldDelete: "true",
reviewId: props.review.id || null,
},
{
method: "post",
action: $path("/actions", {
intent: "performReviewAction",
}),
},
);
onClick={() => {
openConfirmationModal(
"Are you sure you want to delete this review? This action cannot be undone.",
() => {
deleteReviewFetcher.submit(
{
shouldDelete: "true",
reviewId: props.review.id || null,
},
{
method: "post",
action: $path("/actions", {
intent: "performReviewAction",
}),
},
);
},
);
}}
color="red"
>
Expand Down Expand Up @@ -732,14 +732,13 @@ export const ReviewItemDisplay = (props: {
<ActionIcon
color="red"
type="submit"
onClick={async (e) => {
onClick={(e) => {
const form = e.currentTarget.form;
e.preventDefault();
const conf = await confirmWrapper({
confirmation:
"Are you sure you want to delete this comment?",
});
if (conf && form) submit(form);
openConfirmationModal(
"Are you sure you want to delete this comment?",
() => submit(form),
);
}}
>
<IconTrash size={16} />
Expand Down Expand Up @@ -886,14 +885,13 @@ export const DisplayCollection = (props: {
/>
<ActionIcon
size={16}
onClick={async (e) => {
onClick={(e) => {
const form = e.currentTarget.form;
e.preventDefault();
const conf = await confirmWrapper({
confirmation:
"Are you sure you want to remove this media from this collection?",
});
if (conf && form) submit(form);
openConfirmationModal(
"Are you sure you want to remove this media from this collection?",
() => submit(form),
);
}}
>
<IconX />
Expand Down
59 changes: 0 additions & 59 deletions apps/frontend/app/components/confirmation.tsx

This file was deleted.

16 changes: 7 additions & 9 deletions apps/frontend/app/components/media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ import {
DisplayThreePointReview,
MEDIA_DETAILS_HEIGHT,
} from "~/components/common";
import { confirmWrapper } from "~/components/confirmation";
import {
clientGqlService,
getPartialMetadataDetailsQuery,
openConfirmationModal,
queryFactory,
reviewYellow,
} from "~/lib/generals";
Expand Down Expand Up @@ -397,14 +397,12 @@ export const ToggleMediaMonitorMenuItem = (props: {
const form = e.currentTarget.form;
if (form) {
e.preventDefault();
if (isMonitored) {
const conf = await confirmWrapper({
confirmation: "Are you sure you want to stop monitoring?",
});
if (conf) submit(form);
} else {
submit(form);
}
if (isMonitored)
openConfirmationModal(
"Are you sure you want to stop monitoring?",
() => submit(form),
);
else submit(form);
}
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
createQueryKeys,
mergeQueryKeys,
} from "@lukemorales/query-key-factory";
import type { MantineColor } from "@mantine/core";
import { type MantineColor, Text } from "@mantine/core";
import { modals } from "@mantine/modals";
import {
MediaLot,
MediaSource,
Expand Down Expand Up @@ -306,10 +307,10 @@ export const getStringAsciiValue = (input: string) => {
return total;
};

export const selectRandomElement = <T>(array: T[], input: string): T => {
export function selectRandomElement<T>(array: T[], input: string): T {
// taken from https://stackoverflow.com/questions/44975435/using-mod-operator-in-javascript-to-wrap-around#comment76926119_44975435
return array[(getStringAsciiValue(input) + array.length) % array.length];
};
}

export const getMetadataIcon = (lot: MediaLot) =>
match(lot)
Expand Down Expand Up @@ -338,16 +339,16 @@ export const clientGqlService = new GraphQLClient(
},
);

export const getSurroundingElements = <T>(
export function getSurroundingElements<T>(
array: Array<T>,
elementIndex: number,
): Array<number> => {
): Array<number> {
if (array.length === 1) return [0];
const lastIndex = array.length - 1;
if (elementIndex === 0) return [lastIndex, elementIndex, elementIndex + 1];
if (elementIndex === lastIndex) return [elementIndex - 1, elementIndex, 0];
return [elementIndex - 1, elementIndex, elementIndex + 1];
};
}

const mediaQueryKeys = createQueryKeys("media", {
metadataPartialDetails: (metadataId: string) => ({
Expand Down Expand Up @@ -488,3 +489,11 @@ export const MediaColors: EntityColor = {
REVIEW: "green.5",
USER_MEASUREMENT: "indigo",
};

export const openConfirmationModal = (title: string, onConfirm: () => void) =>
modals.openConfirmModal({
title: "Confirmation",
onConfirm: onConfirm,
children: <Text size="sm">{title}</Text>,
labels: { confirm: "Confirm", cancel: "Cancel" },
});
25 changes: 6 additions & 19 deletions apps/frontend/app/lib/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useComputedColorScheme, useMantineTheme } from "@mantine/core";
import { useForceUpdate, useListState } from "@mantine/hooks";
import { useForceUpdate } from "@mantine/hooks";
import {
useNavigate,
useRevalidator,
useRouteLoaderData,
useSearchParams,
Expand Down Expand Up @@ -86,20 +87,22 @@ export const useAppSearchParam = (cookieKey: string) => {

export const useConfirmSubmit = () => {
const submit = useSubmit();
const fn = (e: FormEvent<HTMLFormElement> | HTMLFormElement) => {
const fn = (e: FormEvent<HTMLFormElement> | HTMLFormElement | null) => {
if (!e) return;
if (e.preventDefault) e.preventDefault();
submit(e.currentTarget || e, { navigate: false });
};
return fn;
};

export const useGetWorkoutStarter = () => {
const navigate = useNavigate();
const revalidator = useRevalidator();
const [_, setCurrentWorkout] = useCurrentWorkout();

const fn = (wkt: InProgressWorkout, action: FitnessAction) => {
setCurrentWorkout(wkt);
window.location.href = $path("/fitness/:action", { action });
navigate($path("/fitness/:action", { action }), { flushSync: true });
revalidator.revalidate();
};
return fn;
Expand Down Expand Up @@ -187,22 +190,6 @@ export const useGetWatchProviders = (mediaLot: MediaLot) => {
return watchProviders;
};

export const useComplexJsonUpdate = () => {
const [toUpdatePreferences, updateUserPreferencesHandler] = useListState<
[string, string]
>([]);

const reset = () => updateUserPreferencesHandler.setState([]);

const appendPref = (property: string, value: string) => {
const index = toUpdatePreferences.findIndex((p) => p[0] === property);
if (index !== -1) updateUserPreferencesHandler.remove(index);
updateUserPreferencesHandler.append([property, value]);
};

return { reset, appendPref, toUpdatePreferences };
};

export const useIsFitnessActionActive = () => {
const [currentWorkout] = useCurrentWorkout();
const action = currentWorkout?.currentActionOrCompleted;
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/app/lib/state/fitness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const useGetSetAtIndex = (exerciseIdx: number, setIdx: number) => {
export const getDefaultWorkout = (
fitnessEntity: FitnessAction,
): InProgressWorkout => {
const date = dayjsLib().add(4, "second");
const date = dayjsLib().add(3, "second");
return {
images: [],
videos: [],
Expand Down
Loading

0 comments on commit 8442c5c

Please sign in to comment.