Skip to content

Commit

Permalink
Improved user file access on client components using React Context
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianLeChat committed Jan 5, 2024
1 parent 91e4362 commit 071caa5
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 32 deletions.
20 changes: 20 additions & 0 deletions app/[locale]/components/storage-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Composant de gestion des données de stockage de l'utilisateur.
//

"use client";

import type { FileAttributes } from "@/interfaces/File";
import { createContext, type Dispatch, type SetStateAction } from "react";

export const StorageContext = createContext<{
files: FileAttributes[];
setFiles: Dispatch<SetStateAction<FileAttributes[]>>;
}>( {
// Liste des fichiers utilisateurs.
files: [],

// Définition de la liste des fichiers utilisateurs.
setFiles: () =>
{}
} );
13 changes: 2 additions & 11 deletions app/[locale]/dashboard/components/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,15 @@

import { ColumnDef } from "@tanstack/react-table";
import { formatSize } from "@/utilities/react-table";
import { FileAttributes } from "@/interfaces/File";

import { Badge } from "../../components/ui/badge";
import RowActions from "./row-actions";
import ColumnHeader from "./column-header";
import { Checkbox } from "../../components/ui/checkbox";

// Déclaration du typage d'un fichier.
export type File = {
id: number;
name: string;
type: string;
size: number;
date: string;
status: "public" | "private" | "shared";
};

// Déclaration des colonnes du tableau.
export const columns: ColumnDef<File>[] = [
export const columns: ColumnDef<FileAttributes>[] = [
{
// Case de sélection d'une ou plusieurs lignes.
id: "select",
Expand Down
16 changes: 9 additions & 7 deletions app/[locale]/dashboard/components/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"use client";

import { X } from "lucide-react";
import { useState } from "react";
import { ColumnDef,
flexRender,
SortingState,
Expand All @@ -17,6 +16,8 @@ import { ColumnDef,
ColumnFiltersState,
getFilteredRowModel,
getPaginationRowModel } from "@tanstack/react-table";
import { useMemo, useState } from "react";
import type { FileAttributes } from "@/interfaces/File";

import { Input } from "../../components/ui/input";
import { Button } from "../../components/ui/button";
Expand All @@ -26,18 +27,18 @@ import { Table,
TableCell,
TableHead,
TableHeader } from "../../components/ui/table";
import { StorageContext } from "../../components/storage-provider";

import Pagination from "./pagination";
import FileUpload from "./file-upload";
import ColumnToggle from "./column-toggle";
import type { File } from "./columns";

export default function DataTable( {
columns,
data
}: {
columns: ColumnDef<File>[];
data: File[];
columns: ColumnDef<FileAttributes>[];
data: FileAttributes[];
} )
{
// Déclaration des variables d'état.
Expand All @@ -50,6 +51,7 @@ export default function DataTable( {
);

// Définition des tableaux.
const state = useMemo( () => ( { files, setFiles } ), [ files ] );
const table = useReactTable( {
data: files,
state: {
Expand All @@ -71,7 +73,7 @@ export default function DataTable( {

// Affichage du rendu HTML du composant.
return (
<>
<StorageContext.Provider value={state}>
{/* Filtrage et tri des données */}
<div className="flex items-center gap-2 py-4">
{/* Filtrage par nom */}
Expand Down Expand Up @@ -104,7 +106,7 @@ export default function DataTable( {
<ColumnToggle table={table} />

{/* Ajout d'une nouvelle entrée */}
<FileUpload files={files} setFiles={setFiles} />
<FileUpload />
</div>

{/* Affichage des données dans le tableau */}
Expand Down Expand Up @@ -163,6 +165,6 @@ export default function DataTable( {
<aside className="flex items-center justify-end gap-2 py-4 max-sm:flex-col sm:gap-4 lg:gap-8">
<Pagination table={table} />
</aside>
</>
</StorageContext.Provider>
);
}
18 changes: 7 additions & 11 deletions app/[locale]/dashboard/components/file-upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import { formatSize } from "@/utilities/react-table";
import { useFormState } from "react-dom";
import { useState, useEffect, type Dispatch, type SetStateAction } from "react";
import { type FileAttributes } from "@/interfaces/File";
import { useState, useEffect, useContext } from "react";
import { Ban, Loader2, PlusCircleIcon, UploadCloud } from "lucide-react";

import { Input } from "../../components/ui/input";
import { Progress } from "../../components/ui/progress";
import { useToast } from "../../components/ui/use-toast";
import { type File } from "./columns";
import { Form,
FormItem,
FormField,
Expand All @@ -31,15 +31,10 @@ import { Dialog,
DialogTrigger,
DialogContent,
DialogDescription } from "../../components/ui/dialog";
import { StorageContext } from "../../components/storage-provider";
import { Button, buttonVariants } from "../../components/ui/button";

export default function FileUpload( {
files,
setFiles
}: {
files: File[];
setFiles: Dispatch<SetStateAction<File[]>>;
} )
export default function FileUpload()
{
// Déclaration des constantes.
const maxQuota = Number( process.env.NEXT_PUBLIC_MAX_QUOTA ?? 0 );
Expand All @@ -51,6 +46,7 @@ export default function FileUpload( {
};

// Déclaration des variables d'état.
const { files, setFiles } = useContext( StorageContext );
const [ quota, setQuota ] = useState(
files.reduce( ( previous, current ) => previous + current.size, 0 )
);
Expand Down Expand Up @@ -98,12 +94,12 @@ export default function FileUpload( {
{
// Si c'est le cas, on ajoute les fichiers à la liste
// des fichiers déjà existants.
const uploaded: File[] = [];
const uploaded: FileAttributes[] = [];

data.forEach( ( file ) =>
{
// Transformation de la chaîne JSON en objet.
const json = JSON.parse( file ) as File;
const json = JSON.parse( file ) as FileAttributes;

// Mise à jour du quota utilisateur.
setQuota( ( previous ) => previous + json.size );
Expand Down
7 changes: 4 additions & 3 deletions app/[locale]/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { redirect } from "next/navigation";
import { existsSync } from "fs";
import { join, parse } from "path";
import type { Metadata } from "next";
import type { FileAttributes } from "@/interfaces/File";
import { mkdir, readdir, stat } from "fs/promises";
import { unstable_setRequestLocale } from "next-intl/server";

Expand All @@ -18,8 +19,8 @@ import { auth } from "@/utilities/next-auth";
import { generateMetadata } from "../layout";

// Importation des composants.
import { columns } from "./components/columns";
import { Separator } from "../components/ui/separator";
import { type File, columns } from "./components/columns";

const Header = lazy( () => import( "../components/header" ) );
const UserMenu = lazy( () => import( "../components/user-menu" ) );
Expand All @@ -31,7 +32,7 @@ export const metadata: Metadata = {
};

// Récupération des fichiers depuis le système de fichiers.
async function getFiles(): Promise<File[]>
async function getFiles(): Promise<FileAttributes[]>
{
// On vérifie d'abord si la session utilisateur est valide.
const session = await auth();
Expand Down Expand Up @@ -76,7 +77,7 @@ async function getFiles(): Promise<File[]>
size: stats.size,
date: stats.birthtime.toISOString(),
status: result?.status ?? "public"
} as File;
} as FileAttributes;
} )
);
}
Expand Down
22 changes: 22 additions & 0 deletions interfaces/File.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Interface des attributs des fichiers utilisateurs.
//
export interface FileAttributes {
// Identifiant unique du fichier.
id: number;

// Nom original du fichier.
name: string;

// Type MIME du fichier.
type: string;

// Taille du fichier en octets.
size: number;

// Date de création du fichier.
date: string;

// Statut de partage du fichier.
status: "public" | "private" | "shared";
}

0 comments on commit 071caa5

Please sign in to comment.