Skip to content

Commit

Permalink
Merge pull request #406 from Shelf-nu/394-chore-upgrade-remix-to-2xx
Browse files Browse the repository at this point in the history
chore: upgrade remix to 2xx
  • Loading branch information
DonKoko authored Oct 4, 2023
2 parents 44fc2f7 + ac766f6 commit 8e6ef97
Show file tree
Hide file tree
Showing 110 changed files with 11,343 additions and 28,356 deletions.
7 changes: 5 additions & 2 deletions app/components/assets/asset-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect } from "react";
import type { Asset } from "@prisma/client";

import { useFetcher } from "@remix-run/react";
import type { action } from "~/routes/api+/asset.refresh-main-image";
import { tw } from "~/utils";

export const AssetImage = ({
Expand All @@ -18,10 +19,12 @@ export const AssetImage = ({
className?: string;
rest?: HTMLImageElement;
}) => {
const fetcher = useFetcher();
const fetcher = useFetcher<typeof action>();
const { assetId, mainImage, mainImageExpiration, alt } = asset;
const url =
mainImage || fetcher?.data?.mainImage || "/images/asset-placeholder.jpg";
mainImage ||
fetcher?.data?.asset?.mainImage ||
"/images/asset-placeholder.jpg";

useEffect(() => {
if (mainImage && mainImageExpiration) {
Expand Down
8 changes: 5 additions & 3 deletions app/components/assets/custom-fields-inputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export default function AssetCustomFields({
schema: z.ZodObject<any, any, any>;
}) {
/** Get the custom fields from the loader */
const { customFields } = useLoaderData();
const { asset } = useLoaderData<typeof loader>() || {};

const { customFields, asset } = useLoaderData<typeof loader>();

const customFieldsValues =
(asset?.customFields as unknown as ShelfAssetCustomFieldValueType[]) || [];
Expand Down Expand Up @@ -181,7 +181,7 @@ export default function AssetCustomFields({
</Link>
</div>
{customFields.length > 0 ? (
customFields.map((field: CustomField) => {
customFields.map((field) => {
const value = customFieldsValues?.find(
(cfv) => cfv.customFieldId === field.id
)?.value;
Expand All @@ -195,6 +195,8 @@ export default function AssetCustomFields({
required={field.required}
>
{typeof fieldTypeToCompMap[field.type] === "function" ? (
// @ts-ignore
// @TODO we have to find a solution for this
fieldTypeToCompMap[field.type]!(field)
) : (
<Input
Expand Down
29 changes: 15 additions & 14 deletions app/components/assets/form.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type { Asset, CustomField, Qr } from "@prisma/client";
import type { Asset, Qr } from "@prisma/client";
import { Form, Link, useLoaderData, useNavigation } from "@remix-run/react";
import { useAtom, useAtomValue } from "jotai";
import type { Tag } from "react-tag-autocomplete";
import { useZorm } from "react-zorm";
import { z } from "zod";
import { updateTitleAtom } from "~/atoms/assets.new";
import { fileErrorAtom, validateFileAtom } from "~/atoms/file";
import type { loader } from "~/routes/_layout+/assets.$assetId_.edit";
import { isFormProcessing } from "~/utils";

import { mergedSchema } from "~/utils/custom-fields";
import type { CustomFieldZodSchema } from "~/utils/custom-field-schema";
import { mergedSchema } from "~/utils/custom-field-schema";
import { zodFieldIsRequired } from "~/utils/zod";
import AssetCustomFields from "./custom-fields-inputs";

Expand Down Expand Up @@ -52,21 +54,20 @@ export const AssetForm = ({
}: Props) => {
const navigation = useNavigation();

const { customFields } = useLoaderData();
const customFields = useLoaderData<typeof loader>().customFields.map(
(cf) =>
cf.active && {
id: cf.id,
name: cf.name,
helpText: cf?.helpText || "",
required: cf.required,
type: cf.type.toLowerCase() as "text" | "number" | "date" | "boolean",
}
) as CustomFieldZodSchema[];

const FormSchema = mergedSchema({
baseSchema: NewAssetFormSchema,
customFields: customFields.map(
(cf: CustomField) =>
cf.active && {
id: cf.id,
name: cf.name,
helpText: cf?.helpText || "",
required: cf.required,
type: cf.type.toLowerCase() as "text" | "number" | "date" | "boolean",
options: cf.options,
}
),
customFields,
});

const zo = useZorm("NewQuestionWizardScreen", FormSchema);
Expand Down
10 changes: 7 additions & 3 deletions app/components/assets/import-content.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ChangeEvent } from "react";
import { useRef, useState } from "react";
import { useFetcher } from "@remix-run/react";
import type { action } from "~/routes/_layout+/assets.import";
import { isFormProcessing } from "~/utils";
import Input from "../forms/input";
import { Button } from "../shared";
Expand Down Expand Up @@ -111,9 +112,12 @@ export const ImportContent = () => (
const FileForm = ({ intent }: { intent: string }) => {
const [agreed, setAgreed] = useState<"I AGREE" | "">("");
const formRef = useRef<HTMLFormElement>(null);
const fetcher = useFetcher();
const disabled = isFormProcessing(fetcher.state) || agreed !== "I AGREE";
const isSuccessful = fetcher.data?.success;
const fetcher = useFetcher<typeof action>();

const { data, state } = fetcher;
// const isSuccessFull = state === "idle" && data != null && !data?.error;
const disabled = isFormProcessing(state) || agreed !== "I AGREE";
const isSuccessful = data?.success;

/** We use a controlled field for the file, because of the confirmation dialog we have.
* That way we can disabled the confirmation dialog button until a file is selected
Expand Down
8 changes: 3 additions & 5 deletions app/components/assets/notes/actions-dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { Note } from "@prisma/client";

import { HorizontalDotsIcon } from "~/components/icons";
import {
DropdownMenu,
Expand All @@ -9,10 +7,10 @@ import {
import { DeleteNote } from "./delete-note";

interface Props {
note: Note;
noteId: string;
}

export const ActionsDopdown = ({ note }: Props) => (
export const ActionsDopdown = ({ noteId }: Props) => (
<DropdownMenu modal={false}>
<DropdownMenuTrigger>
<HorizontalDotsIcon />
Expand All @@ -22,7 +20,7 @@ export const ActionsDopdown = ({ note }: Props) => (
className="order w-[180px] rounded-md bg-white p-1.5 text-right"
>
<div className="relative flex select-none items-center rounded p-2 text-left text-[13px] leading-none outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-gradient-to-br hover:bg-gray-100">
<DeleteNote note={note} />
<DeleteNote noteId={noteId} />
</div>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
5 changes: 2 additions & 3 deletions app/components/assets/notes/delete-note.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { Note } from "@prisma/client";
import { useFetcher, useParams } from "@remix-run/react";
import { TrashIcon } from "~/components/icons";
import { Button } from "~/components/shared/button";
Expand All @@ -14,7 +13,7 @@ import {
AlertDialogTrigger,
} from "~/components/shared/modal";

export const DeleteNote = ({ note }: { note: Note }) => {
export const DeleteNote = ({ noteId }: { noteId: string }) => {
const fetcher = useFetcher();
const params = useParams();
return (
Expand Down Expand Up @@ -53,7 +52,7 @@ export const DeleteNote = ({ note }: { note: Note }) => {
method="delete"
action={`/assets/${params.assetId}/note`}
>
<input type="hidden" name="noteId" value={note.id} />
<input type="hidden" name="noteId" value={noteId} />
<Button
className="border-error-600 bg-error-600 hover:border-error-800 hover:bg-error-800"
type="submit"
Expand Down
14 changes: 4 additions & 10 deletions app/components/assets/notes/note.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { MarkdownViewer } from "~/components/markdown";
import { Switch } from "~/components/shared/switch";
import { Tag } from "~/components/shared/tag";
import { useUserData } from "~/hooks";
import type { WithDateFields } from "~/modules/types";
import { timeAgo } from "~/utils/time-ago";
import { ActionsDopdown } from "./actions-dropdown";

export type NoteWithDate = NoteType & {
export type NoteWithDate = WithDateFields<NoteType, string> & {
dateDisplay: string;
};

Expand All @@ -27,14 +28,7 @@ export const Note = ({ note }: { note: NoteWithDate }) => {
);
};

const Update = ({
note,
}: {
note: NoteWithDate & {
dateDisplay: string;
};
when?: boolean;
}) => (
const Update = ({ note }: { note: NoteWithDate; when?: boolean }) => (
<div className="flex px-3.5 py-3">
<div className="message flex flex-1 items-start gap-2">
<Tag>{note.dateDisplay}</Tag> <MarkdownViewer content={note.content} />
Expand All @@ -58,7 +52,7 @@ export const Comment = ({
</span>{" "}
<span className="text-gray-600">{timeAgo(note.createdAt)}</span>
</div>
<ActionsDopdown note={note} />
<ActionsDopdown noteId={note.id} />
</header>
<div className="message px-3.5 py-3">
<MarkdownViewer content={note.content} />
Expand Down
5 changes: 3 additions & 2 deletions app/components/assets/notes/notes.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useLoaderData, useFetcher } from "@remix-run/react";
import { MarkdownViewer } from "~/components/markdown/markdown-viewer";
import { useUserData } from "~/hooks";
import type { loader } from "~/routes/_layout+/assets.$assetId";
import { isFormProcessing } from "~/utils";
import { NewNote } from "./new";
import type { NoteWithDate } from "./note";
import { Note } from "./note";

export const Notes = () => {
const { asset } = useLoaderData();
const { asset } = useLoaderData<typeof loader>();
/* Using user data here for the Note component generated for frontend only as per the optimistic UI approach */
const user = useUserData();
const hasNotes = asset?.notes.length > 0;
Expand Down Expand Up @@ -40,7 +41,7 @@ export const Notes = () => {
</div>
</li>
) : null}
{asset.notes.map((note: NoteWithDate) => (
{(asset.notes as NoteWithDate[]).map((note) => (
<Note key={note.id} note={note} />
))}
</ul>
Expand Down
3 changes: 1 addition & 2 deletions app/components/category/category-select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useMemo } from "react";
import type { Category } from "@prisma/client";
import { CategorySelectNoCategories } from "./category-select-no-categories";
import { FilterInput } from "./filter-input";
import { useCategorySearch } from "./useCategorySearch";
Expand Down Expand Up @@ -63,7 +62,7 @@ export const CategorySelect = ({ defaultValue }: { defaultValue?: string }) => {
</div>

<div className="border-b border-b-gray-300 py-2 ">
{refinedCategories.map((c: Category) => (
{refinedCategories.map((c) => (
<SelectItem value={c.id} key={c.id}>
<Badge color={c.color} noBg withDot={false}>
{c.name}
Expand Down
6 changes: 4 additions & 2 deletions app/components/category/useCategorySearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export const useCategorySearch = () => {
const isSearchingCategories = useAtomValue(isSearchingAtom);

/** Get the categories from the loader */
const categories = useLoaderData().categories;
const { categories } = useLoaderData<{
categories: Category[];
}>();

const refinedCategories = useMemo(
() =>
atom(
categories.filter((cat: Category) =>
categories.filter((cat) =>
cat.name.toLowerCase().includes(categorySearch.toLowerCase())
)
),
Expand Down
8 changes: 5 additions & 3 deletions app/components/category/useTagSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export const useTagSearch = () => {
const [tagSearch, setTagSearch] = useAtom(searchAtom);
const isSearchingTags = useAtomValue(isSearchingAtom);

/** Get the categories from the loader */
const { tags } = useLoaderData();
/** Get the tags from the loader */
const { tags } = useLoaderData<{
tags: Category[];
}>();

const refinedTags = useMemo(
() =>
atom(
tags.filter((cat: Category) =>
tags.filter((cat) =>
cat.name.toLowerCase().includes(tagSearch.toLowerCase())
)
),
Expand Down
4 changes: 2 additions & 2 deletions app/components/layout/breadcrumbs/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { RouteMatch } from "@remix-run/react";
import type { UIMatch } from "@remix-run/react";
import { ChevronRight } from "~/components/icons/library";

export function Breadcrumb({
match,
isLastItem,
}: {
match: RouteMatch;
match: UIMatch<any, any>;
isLastItem: boolean;
}) {
let breadcrumb = match?.handle?.breadcrumb(match);
Expand Down
10 changes: 8 additions & 2 deletions app/components/layout/breadcrumbs/breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { useMatches } from "@remix-run/react";
import { Breadcrumb } from "./breadcrumb";

// Define an interface that extends RouteHandle with the 'breadcrumb' property
interface HandleWithBreadcrumb {
breadcrumb?: any; // Change 'any' to the actual type of 'breadcrumb' if known
}

export function Breadcrumbs() {
const matches = useMatches();

// skip routes that don't have a breadcrumb
// Filter matches to include only those with 'breadcrumb' property
const breadcrumbs = matches.filter(
(match) => match.handle && match.handle.breadcrumb
(match) => (match.handle as HandleWithBreadcrumb)?.breadcrumb !== undefined
);

return (
<div className="mb-5">
<div className="breadcrumbs">
Expand Down
5 changes: 4 additions & 1 deletion app/components/layout/contextual-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ export default function ContextualModal() {
const matches = useMatches();
/** Get the last item which refers to the current route */
const currentRoute = matches[matches.length - 1];
const showModal = currentRoute?.data?.showModal;
const data = currentRoute?.data as {
showModal?: boolean;
};
const showModal = data.showModal || false;

return (
<AnimatePresence>
Expand Down
5 changes: 4 additions & 1 deletion app/components/layout/contextual-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export default function ContextualSidebar() {

/** We need the prev route, as we use it for navigating back/closing the sidebar */
const prevRoute = matches[matches.length - 2];
const showSidebar = currentRoute?.data?.showSidebar;
const data = currentRoute?.data as {
showSidebar?: boolean;
};
const showSidebar = data.showSidebar || false;

return (
<AnimatePresence>
Expand Down
6 changes: 4 additions & 2 deletions app/components/layout/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ export default function Header({
children?: React.ReactNode;
subHeading?: React.ReactNode;
}) {
const data = useLoaderData();
const header = data?.header as HeaderData;
const data = useLoaderData<{
header?: HeaderData;
}>();
const header = data?.header;

return header ? (
<header>
Expand Down
2 changes: 1 addition & 1 deletion app/components/layout/sidebar/bottom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { LogoutButton } from "~/modules/auth";
import { toggleMobileNavAtom } from "./atoms";

interface Props {
user: User;
user: Pick<User, "username" | "email">;
}

export default function SidebarBottom({ user }: Props) {
Expand Down
6 changes: 1 addition & 5 deletions app/components/layout/sidebar/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,7 @@ export default function Sidebar() {
</div>

<div className="mt-auto">
<SidebarBottom
user={{
...user,
}}
/>
<SidebarBottom user={user} />
</div>
</aside>
</>
Expand Down
Loading

0 comments on commit 8e6ef97

Please sign in to comment.