fix: small fixes

This commit is contained in:
Juan Di Toro 2024-03-22 18:53:39 +01:00
parent e1ca45f1f1
commit c9de506c56
5 changed files with 331 additions and 274 deletions

View File

@ -1,51 +1,62 @@
import { useMutation } from "@tanstack/react-query"; import { useNotification } from "@refinedev/core";
import { useContext } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useCallback, useContext } from "react";
import { PinningProcess } from "~/data/pinning"; import { PinningProcess } from "~/data/pinning";
import { PinningContext } from "~/providers/PinningProvider"; import { PinningContext } from "~/providers/PinningProvider";
// TODO: Adapt to real API
export const usePinning = () => { export const usePinning = () => {
const queryClient = useQueryClient();
const context = useContext(PinningContext); const context = useContext(PinningContext);
const { open } = useNotification();
const { mutate } = useMutation({ const { mutate: pinMutation } = useMutation({
mutationKey: ["pin-progress"], mutationKey: ["pin-mutation"],
mutationFn: async (variables: { cid: string, type: "pin" | "unpin" }) => { mutationFn: async (variables: { cid: string }) => {
const { cid, type } = variables; const { cid } = variables;
switch (type) {
case "pin": {
const response = await PinningProcess.pin(cid); const response = await PinningProcess.pin(cid);
if (!response.success) { if (!response.success) {
open?.({ open?.({
type: "destructive", type: "error",
message: "Erorr pinning " + cid, message: `Error pinning ${cid}`,
description: response.message, description: response.message,
}); });
} }
break;
} queryClient.invalidateQueries({ queryKey: ["pin-progress"] });
case "unpin": { },
});
const { mutate: unpinMutation } = useMutation({
mutationKey: ["unpin-mutation"],
mutationFn: async (variables: { cid: string }) => {
const { cid } = variables;
const response = await PinningProcess.unpin(cid); const response = await PinningProcess.unpin(cid);
if (!response.success) { if (!response.success) {
open?.({ open?.({
type: "destructive", type: "error",
message: "Erorr removing " + cid, message: `Error removing ${cid}`,
description: response.message, description: response.message,
}); });
} }
queryClient.invalidateQueries({ queryKey: ["pin-progress"] });
break; },
}
}
context.queryClient.invalidateQueries({ queryKey: ["pin-progress"] })
}
}); });
const bulkPin = useCallback(
(cids: string[]) => {
for (const cid of cids) {
pinMutation({ cid });
}
},
[pinMutation],
);
return { return {
...context.query, ...context.query,
mutate pin: pinMutation,
unpin: unpinMutation,
bulkPin,
}; };
}; };

View File

@ -1,11 +1,11 @@
import { import {
QueryClient, type QueryClient,
UseQueryResult, type UseQueryResult,
useQuery, useQuery,
useQueryClient, useQueryClient,
} from "@tanstack/react-query"; } from "@tanstack/react-query";
import { createContext, useContext } from "react"; import { createContext, useContext } from "react";
import { PinningProcess, PinningStatus } from "~/data/pinning"; import { PinningProcess, type PinningStatus } from "~/data/pinning";
export interface IPinningData { export interface IPinningData {
cid: string; cid: string;

View File

@ -1,10 +1,16 @@
import {Links, Meta, Outlet, Scripts, ScrollRestoration,} from "@remix-run/react"; import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import stylesheet from "./tailwind.css?url"; import stylesheet from "./tailwind.css?url";
import type { LinksFunction } from "@remix-run/node"; import type { LinksFunction } from "@remix-run/node";
// Supports weights 200-800 // Supports weights 200-800
import '@fontsource-variable/manrope'; import "@fontsource-variable/manrope";
import { Refine } from "@refinedev/core"; import { Refine } from "@refinedev/core";
import routerProvider from "@refinedev/remix-router"; import routerProvider from "@refinedev/remix-router";
import { notificationProvider } from "~/data/notification-provider"; import { notificationProvider } from "~/data/notification-provider";
@ -52,21 +58,18 @@ function App() {
notificationProvider={notificationProvider} notificationProvider={notificationProvider}
dataProvider={{ dataProvider={{
default: providers.default, default: providers.default,
files: providers.files files: providers.files,
}} }}
resources={resources} resources={resources}
options={{disableTelemetry: true}} options={{ disableTelemetry: true }}>
>
<SdkContextProvider sdk={sdk}>
<Outlet /> <Outlet />
</SdkContextProvider>
</Refine> </Refine>
</QueryClientProvider> </QueryClientProvider>
); );
} }
export default function Root() { export default function Root() {
const sdk = Sdk.create(import.meta.env.VITE_PORTAL_URL) const sdk = Sdk.create(import.meta.env.VITE_PORTAL_URL);
return ( return (
<SdkContextProvider sdk={sdk}> <SdkContextProvider sdk={sdk}>
<App /> <App />

View File

@ -85,9 +85,13 @@ export default function MyAccount() {
<ManagementCard> <ManagementCard>
<ManagementCardAvatar <ManagementCardAvatar
button={ button={
<DialogTrigger asChild className="absolute bottom-0 right-0 z-50"> <DialogTrigger
asChild
className="absolute bottom-0 right-0 z-50">
<Button <Button
onClick={() => setModal({ ...openModal, changeAvatar: true })} onClick={() =>
setModal({ ...openModal, changeAvatar: true })
}
variant="outline" variant="outline"
className=" flex items-center w-10 h-10 p-0 border-white rounded-full justiyf-center hover:bg-secondary-2"> className=" flex items-center w-10 h-10 p-0 border-white rounded-full justiyf-center hover:bg-secondary-2">
<EditIcon /> <EditIcon />
@ -105,7 +109,9 @@ export default function MyAccount() {
<DialogTrigger asChild> <DialogTrigger asChild>
<Button <Button
className="h-12 gap-x-2" className="h-12 gap-x-2"
onClick={() => setModal({ ...openModal, changeEmail: true })}> onClick={() =>
setModal({ ...openModal, changeEmail: true })
}>
<AddIcon /> <AddIcon />
Change Email Address Change Email Address
</Button> </Button>
@ -147,7 +153,9 @@ export default function MyAccount() {
</ManagementCardFooter> </ManagementCardFooter>
</ManagementCard> </ManagementCard>
<ManagementCard> <ManagementCard>
<ManagementCardTitle>Two-Factor Authentication</ManagementCardTitle> <ManagementCardTitle>
Two-Factor Authentication
</ManagementCardTitle>
<ManagementCardContent> <ManagementCardContent>
Improve security by enabling 2FA. Improve security by enabling 2FA.
</ManagementCardContent> </ManagementCardContent>
@ -313,7 +321,8 @@ const ChangePasswordSchema = z
}); });
const ChangePasswordForm = () => { const ChangePasswordForm = () => {
const { mutate: updatePassword } = useUpdatePassword<UpdatePasswordFormRequest>(); const { mutate: updatePassword } =
useUpdatePassword<UpdatePasswordFormRequest>();
const [form, fields] = useForm({ const [form, fields] = useForm({
id: "login", id: "login",
constraint: getZodConstraint(ChangePasswordSchema), constraint: getZodConstraint(ChangePasswordSchema),

View File

@ -14,6 +14,10 @@ import {
DialogTrigger, DialogTrigger,
} from "~/components/ui/dialog"; } from "~/components/ui/dialog";
import { Field } from "~/components/forms"; import { Field } from "~/components/forms";
import { z } from "zod";
import { getFormProps, useForm } from "@conform-to/react";
import { getZodConstraint, parseWithZod } from "@conform-to/zod";
import { usePinning } from "~/hooks/usePinning";
export default function FileManager() { export default function FileManager() {
return ( return (
@ -72,25 +76,55 @@ export default function FileManager() {
dataProviderName="files" dataProviderName="files"
/> />
<DialogContent> <DialogContent>
<DialogHeader> <PinFilesForm />
<DialogTitle>Pin Content</DialogTitle>
</DialogHeader>
<form action="" className="w-full flex flex-col gap-y-4">
<Field
inputProps={{
name: "cids",
placeholder: "Comma separated CIDs",
}}
labelProps={{ htmlFor: "cids", children: "Content to Pin" }}
/>
<Button type="submit" className="w-full">
Pin Content
</Button>
</form>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</GeneralLayout> </GeneralLayout>
</Authenticated> </Authenticated>
); );
} }
const PinFilesSchema = z.object({
cids: z.string().transform((value) => value.split(",")),
});
const PinFilesForm = () => {
const { bulkPin } = usePinning();
const [form, fields] = useForm({
id: "pin-files",
constraint: getZodConstraint(PinFilesSchema),
onValidate({ formData }) {
return parseWithZod(formData, { schema: PinFilesSchema });
},
shouldValidate: "onSubmit",
onSubmit(e, { submission }) {
if (submission?.status === "success") {
const value = submission.value;
bulkPin(value.cids);
}
},
});
return (
<>
<DialogHeader>
<DialogTitle>Pin Content</DialogTitle>
</DialogHeader>
<form {...getFormProps(form)} className="w-full flex flex-col gap-y-4">
<Field
inputProps={{
name: fields.cids.name,
placeholder: "Comma separated CIDs",
}}
labelProps={{ htmlFor: "cids", children: "Content to Pin" }}
errors={fields.cids.errors}
/>
<Button type="submit" className="w-full">
Pin Content
</Button>
</form>
</>
);
};