Skip to content

Commit

Permalink
Put entites in partial state (#1026)
Browse files Browse the repository at this point in the history
* feat(services/misc): job to put entities in partial state

* refactor(services/misc): extract to fn

* refactor(services/misc): change names of func arg

* chore(services/misc): do not deploy job if entity is partial from details

* feat(frontend): send entity details

* feat(frontend): start implementing partial details

* feat(frontend): change position of partial metadata details

Signed-off-by: Diptesh Choudhuri <ignisda2001@gmail.com>

* chore(gql): request additional details

* feat(frontend): deploy job to update entity

* fix(backend): update `is_partial` for metadata group

* fix(frontend): do not send useless attribute

* feat(frontend): do not use query keys from factory

* refactor(frontend): both checks in one line

* feat(backend): add mutation to deploy job to update metadata group

* feat(frontend): use new mutation instead

* chore(frontend): increase duration for refetch

* chore(frontend): remove useless btn

* ci: Run CI

* chore(frontend): remove useless `queryKey` getter

---------

Signed-off-by: Diptesh Choudhuri <ignisda2001@gmail.com>
  • Loading branch information
IgnisDa committed Sep 15, 2024
1 parent 7764990 commit fdeb3b2
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 140 deletions.
4 changes: 4 additions & 0 deletions apps/backend/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ pub async fn perform_application_job(
.update_person_and_notify_users(person_id)
.await
.is_ok(),
ApplicationJob::UpdateMetadataGroup(metadata_group_id) => misc_service
.update_metadata_group(&metadata_group_id)
.await
.is_ok(),
ApplicationJob::UpdateGithubExerciseJob(exercise) => exercise_service
.update_github_exercise(exercise)
.await
Expand Down
111 changes: 111 additions & 0 deletions apps/frontend/app/components/common.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Carousel } from "@mantine/carousel";
import "@mantine/carousel/styles.css";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import {
ActionIcon,
Alert,
Expand All @@ -26,36 +27,47 @@ import {
import { useDebouncedValue, useDidUpdate, useDisclosure } from "@mantine/hooks";
import { Form, Link, useFetcher, useNavigate } from "@remix-run/react";
import {
DeployUpdateMetadataGroupJobDocument,
DeployUpdateMetadataJobDocument,
DeployUpdatePersonJobDocument,
EntityLot,
type MediaLot,
type MediaSource,
MetadataDetailsDocument,
MetadataGroupDetailsDocument,
PersonDetailsDocument,
type ReviewItem,
UserReviewScale,
} from "@ryot/generated/graphql/backend/graphql";
import { changeCase, getInitials, isNumber, snakeCase } from "@ryot/ts-utils";
import {
IconArrowBigUp,
IconCheck,
IconCloudDownload,
IconEdit,
IconExternalLink,
IconFilterOff,
IconMoodEmpty,
IconMoodHappy,
IconMoodSad,
IconRotateClockwise2,
IconSearch,
IconStarFilled,
IconTrash,
IconX,
} from "@tabler/icons-react";
import { useMutation, useQuery } from "@tanstack/react-query";
import Cookies from "js-cookie";
import type { ReactNode } from "react";
import { useState } from "react";
import { $path } from "remix-routes";
import invariant from "tiny-invariant";
import type { DeepPartial } from "ts-essentials";
import { match } from "ts-pattern";
import { withQuery } from "ufo";
import {
ThreePointSmileyRating,
clientGqlService,
convertDecimalToThreePointSmiley,
dayjsLib,
getSurroundingElements,
Expand Down Expand Up @@ -95,6 +107,7 @@ export const ApplicationGrid = (props: {
export const MediaDetailsLayout = (props: {
children: Array<ReactNode | (ReactNode | undefined)>;
images: Array<string | null | undefined>;
entityDetails: { id: string; lot: EntityLot; isPartial?: boolean | null };
externalLink?: {
source: MediaSource;
lot?: MediaLot;
Expand All @@ -103,6 +116,85 @@ export const MediaDetailsLayout = (props: {
}) => {
const [activeImageId, setActiveImageId] = useState(0);
const fallbackImageUrl = useFallbackImageUrl();
const [mutationHasRunOnce, setMutationHasRunOnce] = useState(false);
const [parent] = useAutoAnimate();
const entityDetails = useQuery({
queryKey: ["MediaDetailsLayout", "entityDetails", props.entityDetails.id],
queryFn: async () => {
const [id, isPartial] = await match(props.entityDetails.lot)
.with(EntityLot.Metadata, () =>
clientGqlService
.request(MetadataDetailsDocument, {
metadataId: props.entityDetails.id,
})
.then(
(data) =>
[
data.metadataDetails.id,
data.metadataDetails.isPartial,
] as const,
),
)
.with(EntityLot.Person, () =>
clientGqlService
.request(PersonDetailsDocument, {
personId: props.entityDetails.id,
})
.then(
(data) =>
[
data.personDetails.details.id,
data.personDetails.details.isPartial,
] as const,
),
)
.with(EntityLot.MetadataGroup, () =>
clientGqlService
.request(MetadataGroupDetailsDocument, {
metadataGroupId: props.entityDetails.id,
})
.then(
(data) =>
[
data.metadataGroupDetails.details.id,
data.metadataGroupDetails.details.isPartial,
] as const,
),
)
.run();
return { id, isPartial };
},
refetchInterval: dayjsLib.duration(3, "second").asMilliseconds(),
enabled: props.entityDetails.isPartial === true,
});
const commitEntity = useMutation({
mutationFn: async () => {
invariant(entityDetails.data);
match(props.entityDetails.lot)
.with(EntityLot.Metadata, () =>
clientGqlService.request(DeployUpdateMetadataJobDocument, {
metadataId: entityDetails.data.id,
}),
)
.with(EntityLot.MetadataGroup, () =>
clientGqlService.request(DeployUpdateMetadataGroupJobDocument, {
metadataGroupId: entityDetails.data.id,
}),
)
.with(EntityLot.Person, () =>
clientGqlService.request(DeployUpdatePersonJobDocument, {
personId: entityDetails.data.id,
}),
)
.run();
},
onSuccess: () => setMutationHasRunOnce(true),
});

useDidUpdate(() => {
if (entityDetails.data?.isPartial && !mutationHasRunOnce)
commitEntity.mutate();
}, [entityDetails]);

return (
<Flex direction={{ base: "column", md: "row" }} gap="lg">
Expand Down Expand Up @@ -158,6 +250,25 @@ export const MediaDetailsLayout = (props: {
</Flex>
</Badge>
) : null}
<Box mt="md" ref={parent} id="partial-entity-indicator">
{entityDetails.data?.isPartial ? (
<Flex align="center" gap={4}>
<IconCloudDownload size={20} />
<Text size="xs">
Details of this{" "}
{changeCase(props.entityDetails.lot).toLowerCase()} are being
downloaded
</Text>
</Flex>
) : null}
{[false, null, undefined].includes(entityDetails.data?.isPartial) &&
mutationHasRunOnce ? (
<Flex align="center" gap={4}>
<IconRotateClockwise2 size={20} />
<Text size="xs">Details updated, please refresh the page.</Text>
</Flex>
) : undefined}
</Box>
</Box>
<Stack id="details-container" style={{ flexGrow: 1 }}>
{props.children}
Expand Down
12 changes: 0 additions & 12 deletions apps/frontend/app/components/media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { changeCase, getInitials, isString, snakeCase } from "@ryot/ts-utils";
import {
IconBackpack,
IconBookmarks,
IconCloudDownload,
IconPlayerPlay,
IconRosetteDiscountCheck,
IconStarFilled,
Expand Down Expand Up @@ -462,17 +461,6 @@ export const PersonDisplayItem = (props: {
);
};

export const MediaIsPartial = (props: { mediaType: string }) => {
return (
<Flex align="center" gap={4}>
<IconCloudDownload size={20} />
<Text size="xs">
Details of this {props.mediaType} are being downloaded
</Text>
</Flex>
);
};

export const ToggleMediaMonitorMenuItem = (props: {
entityLot: EntityLot;
inCollections: Array<string>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {
ReviewItemDisplay,
} from "~/components/common";
import {
MediaIsPartial,
MediaScrollArea,
PartialMetadataDisplay,
ToggleMediaMonitorMenuItem,
Expand Down Expand Up @@ -82,6 +81,11 @@ export default function Page() {
<Container>
<MediaDetailsLayout
images={loaderData.metadataGroupDetails.details.displayImages}
entityDetails={{
id: loaderData.metadataGroupId,
lot: EntityLot.MetadataGroup,
isPartial: loaderData.metadataGroupDetails.details.isPartial,
}}
externalLink={{
source: loaderData.metadataGroupDetails.details.source,
lot: loaderData.metadataGroupDetails.details.lot,
Expand Down Expand Up @@ -109,9 +113,6 @@ export default function Page() {
))}
</Group>
) : null}
{loaderData.metadataGroupDetails.details.isPartial ? (
<MediaIsPartial mediaType="group" />
) : null}
<Tabs variant="outline" defaultValue={loaderData.query.defaultTab}>
<Tabs.List mb="xs">
<Tabs.Tab value="media" leftSection={<IconDeviceTv size={16} />}>
Expand Down
57 changes: 6 additions & 51 deletions apps/frontend/app/routes/_dashboard.media.item.$id._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
} from "@remix-run/react";
import {
DeleteSeenItemDocument,
DeployUpdateMetadataJobDocument,
DisassociateMetadataDocument,
EntityLot,
MediaLot,
Expand Down Expand Up @@ -94,19 +93,11 @@ import {
} from "~/components/common";
import { confirmWrapper } from "~/components/confirmation";
import {
MediaIsPartial,
MediaScrollArea,
PartialMetadataDisplay,
ToggleMediaMonitorMenuItem,
} from "~/components/media";
import {
Verb,
dayjsLib,
getVerb,
queryClient,
queryFactory,
reviewYellow,
} from "~/lib/generals";
import { Verb, dayjsLib, getVerb, reviewYellow } from "~/lib/generals";
import {
useApplicationEvents,
useConfirmSubmit,
Expand Down Expand Up @@ -169,20 +160,6 @@ export const action = unstable_defineAction(async ({ request }) => {
}),
});
},
deployUpdateMetadataJob: async () => {
const submission = processSubmission(formData, MetadataIdSchema);
await serverGqlService.authenticatedRequest(
request,
DeployUpdateMetadataJobDocument,
submission,
);
return Response.json({ status: "success", tt: new Date() } as const, {
headers: await createToastHeaders({
type: "success",
message: "Metadata update job deployed successfully",
}),
});
},
mergeMetadata: async () => {
const submission = processSubmission(formData, mergeMetadataSchema);
await serverGqlService.authenticatedRequest(
Expand Down Expand Up @@ -311,6 +288,11 @@ export default function Page() {
<Container>
<MediaDetailsLayout
images={loaderData.metadataDetails.assets.images}
entityDetails={{
id: loaderData.metadataId,
lot: EntityLot.Metadata,
isPartial: loaderData.metadataDetails.isPartial,
}}
externalLink={{
source: loaderData.metadataDetails.source,
lot: loaderData.metadataDetails.lot,
Expand Down Expand Up @@ -347,9 +329,6 @@ export default function Page() {
))}
</Group>
) : null}
{loaderData.metadataDetails.isPartial ? (
<MediaIsPartial mediaType="media" />
) : null}
<Text c="dimmed" fz={{ base: "sm", lg: "md" }}>
{[
loaderData.metadataDetails.publishDate
Expand Down Expand Up @@ -938,30 +917,6 @@ export default function Page() {
formValue={loaderData.metadataId}
entityLot={EntityLot.Metadata}
/>
{loaderData.metadataDetails.source !==
MediaSource.Custom ? (
<Form
replace
method="POST"
action={withQuery("", {
intent: "deployUpdateMetadataJob",
})}
onSubmit={async () => {
await queryClient.invalidateQueries({
queryKey: queryFactory.media.metadataDetails(
loaderData.metadataId,
).queryKey,
});
}}
>
<input
hidden
name="metadataId"
defaultValue={loaderData.metadataId}
/>
<Menu.Item type="submit">Update metadata</Menu.Item>
</Form>
) : null}
<Menu.Item onClick={mergeMetadataModalOpen}>
Merge media
</Menu.Item>
Expand Down
Loading

0 comments on commit fdeb3b2

Please sign in to comment.