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

Send additional details to *arr integrations #1081

Merged
merged 31 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1caa9ca
chore(frontend): do not allow showing/hiding details
IgnisDa Oct 23, 2024
1ecb6ff
refactor(backend): change order of attributes
IgnisDa Oct 23, 2024
b6fba64
feat(backend): send movie/show titles
IgnisDa Oct 23, 2024
550d9c1
ci: Run CI
IgnisDa Oct 23, 2024
1be73ae
chore(frontend): remove upper margin
IgnisDa Oct 23, 2024
443a509
chore(frontend): revert all exercise changes
IgnisDa Oct 25, 2024
61cc818
ci: Run CI
IgnisDa Oct 25, 2024
43edaf4
Merge branch 'main' into issue-1080
IgnisDa Oct 25, 2024
ae7b17a
refactor(services/integration): change order of args
IgnisDa Oct 26, 2024
928c8b2
fix(services/integration): send only requests for shows and movies
IgnisDa Oct 26, 2024
fa6cbbf
refactor(services/integration): change name of attribute and func args
IgnisDa Oct 26, 2024
c8ec8f8
feat(services/integration): send only requests for shows and movies f…
IgnisDa Oct 26, 2024
6e3c0e2
ci: Run CI
IgnisDa Oct 26, 2024
819cb3e
refactor(backend): use guard `let-else` statements
IgnisDa Oct 26, 2024
95267bd
refactor(backend): more if let Some
IgnisDa Oct 26, 2024
7a4efb2
refactor(frontend): move checkbox into common area
IgnisDa Oct 26, 2024
13242d1
fix(frontend): position of invert btn
IgnisDa Oct 26, 2024
9c5079d
chore(frontend): use inbuilt function
IgnisDa Oct 26, 2024
3dc9f81
ci: Run CI
IgnisDa Oct 26, 2024
d20da1a
feat(backend): return more core details
IgnisDa Oct 27, 2024
63c7a86
chore(frontend): do not parse env variables in the frontend
IgnisDa Oct 27, 2024
6e8bc65
refactor(frontend): extract variable
IgnisDa Oct 27, 2024
52f5dfe
chore(frontend): order of attributes
IgnisDa Oct 27, 2024
34bad82
feat(backend): collapse two queries into one
IgnisDa Oct 25, 2024
76802ec
chore(frontend): adapt to new gql schema
IgnisDa Oct 25, 2024
5e238ff
chore(gql): return whether user is disabled
IgnisDa Oct 27, 2024
5a7a526
feat(frontend): do not allow logging in when account disabled
IgnisDa Oct 27, 2024
d3f933b
chore(frontend): order of attributes
IgnisDa Oct 27, 2024
9dbc1fa
ci: Run CI
IgnisDa Oct 27, 2024
9e2c113
refactor(backend): use `let-else` wherever applicable
IgnisDa Oct 27, 2024
4b451e3
refactor(backend): more let else
IgnisDa Oct 27, 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
3 changes: 2 additions & 1 deletion Cargo.lock

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

21 changes: 17 additions & 4 deletions apps/frontend/app/components/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Badge,
Box,
Button,
Checkbox,
Collapse,
Divider,
Flex,
Expand All @@ -22,6 +23,7 @@ import {
TextInput,
Title,
Tooltip,
rem,
} from "@mantine/core";
import { useDebouncedValue, useDidUpdate, useDisclosure } from "@mantine/hooks";
import {
Expand Down Expand Up @@ -348,14 +350,21 @@ export const FiltersModal = (props: {
export const CollectionsFilter = (props: {
cookieName: string;
collections?: string[];
invertCollection?: boolean;
}) => {
const collections = useUserCollections();
const [_, { setP }] = useAppSearchParam(props.cookieName);

return (
<MultiSelect
placeholder="Select a collection"
flex={1}
clearable
searchable
rightSectionWidth={rem(100)}
rightSectionPointerEvents="all"
defaultValue={props.collections}
placeholder="Select a collection"
onChange={(v) => setP("collections", v.join(","))}
data={[
{
group: "My collections",
Expand All @@ -365,9 +374,13 @@ export const CollectionsFilter = (props: {
})),
},
]}
onChange={(v) => setP("collections", v.join(","))}
clearable
searchable
rightSection={
<Checkbox
label="Invert"
checked={props.invertCollection}
onChange={(e) => setP("invertCollection", String(e.target.checked))}
/>
}
/>
);
};
Expand Down
3 changes: 0 additions & 3 deletions apps/frontend/app/lib/generals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,6 @@ const usersQueryKeys = createQueryKeys("users", {
details: (token: string) => ({
queryKey: ["userDetails", token],
}),
preferences: (userId: string) => ({
queryKey: ["userPreferences", userId],
}),
});

const mediaQueryKeys = createQueryKeys("media", {
Expand Down
3 changes: 1 addition & 2 deletions apps/frontend/app/lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,8 @@ export const useDashboardLayoutData = () => {
};

export const useCoreDetails = () => useDashboardLayoutData().coreDetails;
export const useUserPreferences = () =>
useDashboardLayoutData().userPreferences;
export const useUserDetails = () => useDashboardLayoutData().userDetails;
export const useUserPreferences = () => useUserDetails().preferences;
export const useUserCollections = () =>
useDashboardLayoutData().userCollections;

Expand Down
83 changes: 32 additions & 51 deletions apps/frontend/app/lib/utilities.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
GetPresignedS3UrlDocument,
PresignedPutS3UrlDocument,
UserCollectionsListDocument,
UserPreferencesDocument,
} from "@ryot/generated/graphql/backend/graphql";
import { UserDetailsDocument } from "@ryot/generated/graphql/backend/graphql";
import { isEmpty } from "@ryot/ts-utils";
Expand Down Expand Up @@ -100,46 +99,37 @@ export const serverGqlService = new AuthenticatedGraphQLClient(
{ headers: { Connection: "keep-alive" } },
);

export const getCookieValue = (request: Request, cookieName: string) => {
return parse(request.headers.get("cookie") || "")[cookieName];
};
export const getCookieValue = (request: Request, cookieName: string) =>
parse(request.headers.get("cookie") || "")[cookieName];

export const getAuthorizationCookie = (request: Request) => {
return getCookieValue(request, AUTH_COOKIE_NAME);
};
export const getAuthorizationCookie = (request: Request) =>
getCookieValue(request, AUTH_COOKIE_NAME);

export const redirectIfNotAuthenticatedOrUpdated = async (request: Request) => {
const { userDetails } = await getCachedUserDetails(request);
const userDetails = await getCachedUserDetails(request);
const getResponseInit = async (toastMessage: string) => ({
status: 302,
headers: combineHeaders(
await createToastHeaders({ type: "error", message: toastMessage }),
getLogoutCookies(),
),
});
if (!userDetails || userDetails.__typename === "UserDetailsError") {
const nextUrl = withoutHost(request.url);
throw redirect($path("/auth", { [redirectToQueryParam]: nextUrl }), {
status: 302,
headers: combineHeaders(
await createToastHeaders({
type: "error",
message: "You must be logged in to view this page",
}),
getLogoutCookies(),
),
});
throw redirect(
$path("/auth", { [redirectToQueryParam]: nextUrl }),
await getResponseInit("You must be logged in to view this page"),
);
}
if (userDetails.isDisabled)
throw redirect(
$path("/auth"),
await getResponseInit("This account has been disabled"),
);

return userDetails;
};

const expectedServerVariables = z.object({
DISABLE_TELEMETRY: z
.string()
.optional()
.transform((v) => v === "true"),
FRONTEND_UMAMI_SCRIPT_URL: z.string().optional(),
FRONTEND_UMAMI_WEBSITE_ID: z.string().optional(),
FRONTEND_UMAMI_DOMAINS: z.string().optional(),
FRONTEND_OIDC_BUTTON_LABEL: z
.string()
.default("Continue with OpenID Connect"),
FRONTEND_DASHBOARD_MESSAGE: z.string().optional(),
});

/**
* Combine multiple header objects into one (uses append so headers are not overridden)
*/
Expand Down Expand Up @@ -169,20 +159,19 @@ export const MetadataSpecificsSchema = z.object({
export const getCachedCoreDetails = async () => {
return await queryClient.ensureQueryData({
queryKey: queryFactory.miscellaneous.coreDetails().queryKey,
queryFn: () => serverGqlService.request(CoreDetailsDocument),
queryFn: () =>
serverGqlService.request(CoreDetailsDocument).then((d) => d.coreDetails),
});
};

export const getCachedUserDetails = async (request: Request) => {
const getCachedUserDetails = async (request: Request) => {
const token = getAuthorizationCookie(request);
return await queryClient.ensureQueryData({
queryKey: queryFactory.users.details(token ?? "").queryKey,
queryFn: () =>
serverGqlService.authenticatedRequest(
request,
UserDetailsDocument,
undefined,
),
serverGqlService
.authenticatedRequest(request, UserDetailsDocument, undefined)
.then((d) => d.userDetails),
});
};

Expand All @@ -198,13 +187,7 @@ export const getCachedExerciseParameters = async () => {

export const getCachedUserPreferences = async (request: Request) => {
const userDetails = await redirectIfNotAuthenticatedOrUpdated(request);
return queryClient.ensureQueryData({
queryKey: queryFactory.users.preferences(userDetails.id).queryKey,
queryFn: () =>
serverGqlService
.authenticatedRequest(request, UserPreferencesDocument, undefined)
.then((data) => data.userPreferences),
});
return userDetails.preferences;
};

export const getCachedUserCollectionsList = async (request: Request) => {
Expand Down Expand Up @@ -294,8 +277,6 @@ export const s3FileUploader = (prefix: string) =>
return undefined;
}, unstable_createMemoryUploadHandler());

export const serverVariables = expectedServerVariables.parse(process.env);

export const toastSessionStorage = createCookieSessionStorage({
cookie: {
sameSite: "lax",
Expand Down Expand Up @@ -363,7 +344,7 @@ export const getCookiesForApplication = async (
token: string,
tokenValidForDays?: number,
) => {
const [{ coreDetails }] = await Promise.all([getCachedCoreDetails()]);
const [coreDetails] = await Promise.all([getCachedCoreDetails()]);
const maxAge =
(tokenValidForDays || coreDetails.tokenValidForDays) * 24 * 60 * 60;
const options = { maxAge, path: "/" } satisfies SerializeOptions;
Expand Down Expand Up @@ -422,9 +403,9 @@ export const redirectToFirstPageIfOnInvalidPage = async (
totalResults: number,
currentPage: number,
) => {
const { coreDetails } = await getCachedCoreDetails();
const coreDetails = await getCachedCoreDetails();
const { searchParams } = new URL(request.url);
const totalPages = Math.ceil(totalResults / coreDetails.pageLimit);
const totalPages = Math.ceil(totalResults / coreDetails.frontend.pageSize);
if (currentPage > totalPages && currentPage !== 1) {
searchParams.set(pageQueryParam, "1");
throw redirect(`?${searchParams.toString()}`);
Expand Down
14 changes: 10 additions & 4 deletions apps/frontend/app/routes/_dashboard._index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from "@ryot/generated/graphql/backend/graphql";
import {
changeCase,
formatDateToNaiveDate,
humanizeDuration,
isBoolean,
isNumber,
Expand Down Expand Up @@ -174,12 +175,15 @@ export default function Page() {
const dashboardLayoutData = useDashboardLayoutData();
const latestUserSummary = loaderData.latestUserSummary;

const dashboardMessage =
dashboardLayoutData.coreDetails.frontend.dashboardMessage;

return (
<Container>
<Stack gap={32}>
{dashboardLayoutData.envData.FRONTEND_DASHBOARD_MESSAGE ? (
{dashboardMessage ? (
<Alert variant="default" icon={<IconInfoCircle />}>
{dashboardLayoutData.envData.FRONTEND_DASHBOARD_MESSAGE}
{dashboardMessage}
</Alert>
) : null}
{userPreferences.general.dashboard.map((de) =>
Expand Down Expand Up @@ -632,8 +636,10 @@ const ActivitySection = () => {
const end = now.endOf("day");
const startDate = getDateFromTimeSpan(timeSpan);
return {
startDate: startDate?.format("YYYY-MM-DD"),
endDate: end.format("YYYY-MM-DD"),
startDate: startDate
? formatDateToNaiveDate(startDate.toDate())
: undefined,
endDate: formatDateToNaiveDate(end.toDate()),
};
}, [timeSpan]);
const { data: dailyUserActivitiesData } = useQuery({
Expand Down
17 changes: 5 additions & 12 deletions apps/frontend/app/routes/_dashboard.media.$action.$lot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
Box,
Button,
Center,
Checkbox,
Container,
Flex,
Group,
Expand Down Expand Up @@ -629,17 +628,11 @@ const FiltersModalForm = () => {
)}
</ActionIcon>
</Flex>
<Flex gap="xs" align="center">
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.mediaList.url.collections}
/>
<Checkbox
label="Invert"
checked={loaderData.mediaList.url.invertCollection}
onChange={(e) => setP("invertCollection", String(e.target.checked))}
/>
</Flex>
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.mediaList.url.collections}
invertCollection={loaderData.mediaList.url.invertCollection}
/>
</>
);
};
17 changes: 5 additions & 12 deletions apps/frontend/app/routes/_dashboard.media.groups.$action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
ActionIcon,
Box,
Center,
Checkbox,
Container,
Flex,
Group,
Expand Down Expand Up @@ -417,17 +416,11 @@ const FiltersModalForm = () => {
)}
</ActionIcon>
</Flex>
<Flex gap="xs" align="center">
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.list.url.collections}
/>
<Checkbox
label="Invert"
checked={loaderData.list.url.invertCollection}
onChange={(e) => setP("invertCollection", String(e.target.checked))}
/>
</Flex>
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.list.url.collections}
invertCollection={loaderData.list.url.invertCollection}
/>
</>
);
};
16 changes: 5 additions & 11 deletions apps/frontend/app/routes/_dashboard.media.people.$action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -439,17 +439,11 @@ const FiltersModalForm = () => {
)}
</ActionIcon>
</Flex>
<Flex gap="xs" align="center">
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.peopleList.url.collections}
/>
<Checkbox
label="Invert"
checked={loaderData.peopleList.url.invertCollection}
onChange={(e) => setP("invertCollection", String(e.target.checked))}
/>
</Flex>
<CollectionsFilter
cookieName={loaderData.cookieName}
collections={loaderData.peopleList.url.collections}
invertCollection={loaderData.peopleList.url.invertCollection}
/>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
);
}
queryClient.removeQueries({
queryKey: queryFactory.users.preferences(userDetails.id).queryKey,
queryKey: queryFactory.users.details(userDetails.id).queryKey,
});
const toastHeaders = await createToastHeaders({
message: "Preferences updated",
Expand Down
Loading