Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ffb4dcb
Prise en charge du vocabulaire anglais pour la création de posts
Mar 10, 2025
f30b119
Ajout d'une liste déroulante pour la langue d'écriture
Mar 10, 2025
ce19789
Traductions en anglais
Mar 10, 2025
5a5a785
Modification de la db pour intégrer des échanges entre posts anglais …
Mar 10, 2025
5f627d1
Prise en compte de la nouvelle db pour la création d'un post
Mar 10, 2025
50c4c0e
Correction du bouton pour changer de langue pour que changer dans lan…
Mar 10, 2025
09d41d4
Ajout de la prise en charge du contenu en anglais
Mar 11, 2025
f3c7843
Prise en charge de l'anglais pour la création et l'édition de posts
Mar 11, 2025
7b2b4f2
Test stricte sur la valeur de locale
Mar 11, 2025
b440491
Giga changement permettant de gérer les traductions. Mais ça marche p…
Mar 11, 2025
12dfff9
Retablissement de la db initiale en ajoutant cette fois ci un slugtr …
Mar 11, 2025
5dc1f46
db changée mais osef
Mar 11, 2025
f6634db
Mise en place de l'ajout d'un post en vue d'être traduit lors de la c…
Mar 12, 2025
26ee5c4
Prise en charge de la redirection vers le post traduit
Mar 13, 2025
8f9aac7
Menage du spaghetti code que j'avais ajouté
Mar 13, 2025
5dfc006
Api qui ne sert plus à rien du coup (je sais même pas d'où sort get-l…
Mar 13, 2025
29bc8ba
Merge branch 'Telecom-Etude:main' into main
ImTooFastForYou Mar 13, 2025
7a2d0b3
Fixé l'affichage des noms sur les posts
Mar 15, 2025
2c66e01
Fixed format
Mar 15, 2025
785efb4
Fixed types and format
Mar 15, 2025
56b8e5c
Fixed the locale use to avoid usePathname()
Mar 15, 2025
afd3ea4
Fixed useless modification
Mar 15, 2025
6a7bf75
Removed useless imports
Mar 15, 2025
5241150
Fixed useless modification
Mar 15, 2025
f45fabb
"translated" semble plus approprié
Mar 15, 2025
709df19
Code pour update la db. Attention à son utilisation si des posts exis…
Mar 15, 2025
9e183b8
Renamed the file
Mar 19, 2025
d045d75
Used last elements instead of pop/push
Mar 19, 2025
a16bd05
Got rid of useless db
Mar 19, 2025
cbc7742
Modified it to generate the new column and fixed minor issues
Mar 19, 2025
ccd94d7
Made slugtr not mandatory
Mar 19, 2025
e865d2e
Prettier format fixes
Mar 19, 2025
89011a7
Modified PostPresentation to change slugtr to a string | null type
Mar 19, 2025
4d01705
Tests pour m'assurer que les migrations et l'ajout de slugtr marchent…
Mar 24, 2025
efb7571
Removed the ? to make slugtr non undefined
Mar 24, 2025
05d797b
Added a test on locale to make a difference in the slugs.
Mar 24, 2025
121c6c0
Used constants
Mar 26, 2025
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
41 changes: 35 additions & 6 deletions dictionaries/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,41 @@ export const enDictionary: Dictionary = {
httpError: "HTTP Error",
},
admin: {
validate: "Validate blogs",
newblog: "New blog",
edit: "Edit blogs",
form: "Form submissions",
users: "Users management",
account: "My account",
manageaccount: {
validate: "Validate blogs",
newblog: "New blog",
edit: "Edit blogs",
form: "Form submissions",
users: "Users management",
account: "My account",
},
createblog: {
title: "Create a new post",
formentry: "Title",
new: "Create",
edit: "Edit an existing post",
},
editblog: {
rename: {
title: "Title",
rename: "Rename",
modifytitle: "Modification of the post title",
},
labels: {
modifylabels: "Modify the labels",
selectormessage: "Select 6 labels at most",
empty: "No filter correspond to this search",
},
save: {
saving: "Saving in progress",
saved: "Saved",
automaticsave: "Automatic save of posts",
savedescription:
"An automatic backup is constantly being made to prevent data loss. As they can take time, you can make a manual backup before leaving the page with the 'Save' button. Spamming this button is useless, just can lead to crashes.",
savewarning: "WARNING: do not leave the page until the status is marked 'Saved' or you may lose your content...",
save: "Save",
},
},
},
sitemap: {
title: "Site plan",
Expand Down
43 changes: 37 additions & 6 deletions dictionaries/fr.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { empty } from "@prisma/client/runtime/library";

export const frDictionary = {
navigation: {
cookies: {
Expand Down Expand Up @@ -48,12 +50,41 @@ export const frDictionary = {
httpError: "Erreur HTTP",
},
admin: {
validate: "Valider des posts",
newblog: "Nouveau blog",
edit: "Modifier des posts",
form: "Soumissions au form",
users: "Gestion des utilisateurs",
account: "Mon compte",
manageaccount: {
validate: "Valider des posts",
newblog: "Nouveau blog",
edit: "Modifier des posts",
form: "Soumissions au form",
users: "Gestion des utilisateurs",
account: "Mon compte",
},
createblog: {
title: "Création d'un post",
formentry: "Titre",
new: "Créer",
edit: "Editer un post existant",
},
editblog: {
rename: {
title: "Titre",
rename: "Renommer",
modifytitle: "Modification du titre du post",
},
labels: {
modifylabels: "Modifier les labels",
selectormessage: "Selectionner au plus 6 labels",
empty: "Aucun filtre ne correspond à cette recherche",
},
save: {
saving: "Sauvegarde en cours",
saved: "Sauvegardé",
automaticsave: "Sauvegarde automatique des posts",
savedescription:
'Une sauvegarde automatique s\'effectue en permanence pour éviter les pertes de données. Comme elles peuvent prendre du temps, vous pouvez faire une sauvegarde manuelle avant de quitter la page avec le bouton "Sauvegarder". Spammer ce bouton ne sert à rien, juste peut entraîner des crash.',
savewarning: 'ATTENTION: ne quittez pas la page tant que le status n\'est pas marqué en "Sauvegardé" au risque de perdre votre contenu...',
save: "Sauvegarder",
},
},
},
sitemap: {
title: "Plan du site",
Expand Down
34 changes: 34 additions & 0 deletions prisma/migrations/20250310190136_o/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Warnings:

- You are about to drop the column `slug` on the `Post` table. All the data in the column will be lost.
- You are about to drop the column `title` on the `Post` table. All the data in the column will be lost.
- Added the required column `slugen` to the `Post` table without a default value. This is not possible if the table is not empty.
- Added the required column `slugfr` to the `Post` table without a default value. This is not possible if the table is not empty.
- Added the required column `titleen` to the `Post` table without a default value. This is not possible if the table is not empty.
- Added the required column `titlefr` to the `Post` table without a default value. This is not possible if the table is not empty.

*/
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Post" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"titlefr" TEXT NOT NULL,
"titleen" TEXT NOT NULL,
"locale" TEXT NOT NULL,
"slugfr" TEXT NOT NULL,
"slugen" TEXT NOT NULL,
"content" TEXT NOT NULL,
"validated" BOOLEAN NOT NULL DEFAULT false,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_Post" ("content", "createdAt", "id", "locale", "updatedAt", "validated") SELECT "content", "createdAt", "id", "locale", "updatedAt", "validated" FROM "Post";
DROP TABLE "Post";
ALTER TABLE "new_Post" RENAME TO "Post";
CREATE UNIQUE INDEX "Post_id_key" ON "Post"("id");
CREATE UNIQUE INDEX "Post_slugfr_key" ON "Post"("slugfr");
CREATE UNIQUE INDEX "Post_slugen_key" ON "Post"("slugen");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
1 change: 1 addition & 0 deletions prisma/migrations/20250311191209_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- This is an empty migration.
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ model Post {
title String
locale String
slug String @unique
slugtr String @unique
authors User[]
content String
validated Boolean @default(false)
Expand Down
65 changes: 65 additions & 0 deletions prisma/update-db.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

choose better name, like "add-slugtr.ts"
We already know it concerns the db as it is inside the prisma folder 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done !

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

async function updateSlugTr() {
await prisma.post.updateMany({
where: {
locale: "fr",
},
data: {
slugtr: {
set: await prisma.$queryRaw`CONCAT(title, '_not_translated')`,
},
},
});

await prisma.post.updateMany({
where: {
locale: "en",
},
data: {
slugtr: {
set: await prisma.$queryRaw`CONCAT(title, '_not_translated')`,
},
},
});
// Cette partie ne devrait pas être incluse si les posts ont une version en français et en anglais car ces derniers seraient dupliqués.
const posts = await prisma.post.findMany({
include: {
authors: true,
labels: true,
},
});

for (const post of posts) {
const newLocale = post.locale === "fr" ? "en" : "fr";

await prisma.post.create({
data: {
title: post.title + "_not_translated",
locale: newLocale,
slugtr: post.slugtr,
slug: post.slug,
authors: {
connect: post.authors.map(author => ({ id: author.id })),
},
content: "",
validated: false,
labels: {
connect: post.labels.map(label => ({ id: label.id })),
},
},
});
}
}

updateSlugTr()
.then(() => {
console.log("Mise à jour terminée");
prisma.$disconnect();
})
.catch(error => {
console.error("Erreur :", error);
prisma.$disconnect();
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,50 @@ import { useState } from "react";
import { getBlog, renameBlog } from "@/db/blogs";
import { updatePostLabels } from "@/db/labels";
import { Locale } from "@/locales/config";
import { Dictionary, getDictionary } from "@/locales/dictionaries";

function Rename({ title, id, router }: { title: string; id: number; router: AppRouterInstance }) {
function Rename({
title,
id,
router,
t,
locale,
}: {
title: string;
id: number;
router: AppRouterInstance;
t: Dictionary["navigation"]["admin"]["editblog"];
locale: Locale;
}) {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">
<span className="flex items-center space-x-2">
<p>Renommer</p>
<p>{t.rename.rename}</p>
<FaPencil />
</span>
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Modification du titre du post</DialogTitle>
<DialogTitle>{t.rename.modifytitle}</DialogTitle>
<form
className="flex flex-col items-center w-full space-y-10"
onSubmit={e => {
const formData = new FormData(e.target as HTMLFormElement);
const title = formData.get("title") as string;
renameBlog(id, title).finally(() => {
renameBlog(id, title, locale).finally(() => {
router.refresh();
});
}}
>
<Label htmlFor="title" className="w-full">
Titre
{t.rename.title}
</Label>
<Input defaultValue={title} className="w-full" type="text" name="title" id="title" />
<Button variant="call2action" type="submit">
Renommer
{t.rename.rename}
</Button>
</form>
</DialogHeader>
Expand All @@ -54,36 +67,46 @@ function Rename({ title, id, router }: { title: string; id: number; router: AppR
);
}

function AddLabel({ getLabels, addRemoveLabel, dbLabels }: { getLabels: string[]; addRemoveLabel: (x: string) => void; dbLabels: string[] }) {
function AddLabel({
getLabels,
addRemoveLabel,
dbLabels,
t,
}: {
getLabels: string[];
addRemoveLabel: (x: string) => void;
dbLabels: string[];
t: Dictionary["navigation"]["admin"]["editblog"];
}) {
return (
<ManyComboBox
selected={getLabels}
addRemove={addRemoveLabel}
items={dbLabels}
vocab={{
title: "Modifier les labels",
selectorMessage: "Selectionner au plus 6 labels",
empty: "Aucun filtre ne correspond à cette recherche",
title: t.labels.modifylabels,
selectorMessage: t.labels.selectormessage,
empty: t.labels.empty,
}}
limit={6}
/>
);
}

function OpenSave({ saving }: { saving: boolean }) {
function OpenSave({ saving, t }: { saving: boolean; t: Dictionary["navigation"]["admin"]["editblog"] }) {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">
<span className="flex items-center space-x-2">
{saving ? (
<>
<p>Sauvegarde en cours</p>
<p>{t.save.saving}</p>
<AiOutlineLoading3Quarters className="animate-spin" />
</>
) : (
<>
<p>Sauvegardé</p>
<p>{t.save.saved}</p>
<FaCheck />
</>
)}
Expand All @@ -92,16 +115,9 @@ function OpenSave({ saving }: { saving: boolean }) {
</DialogTrigger>
<DialogContent>
<DialogHeader className="space-y-6">
<DialogTitle>Sauvegarde automatique des posts</DialogTitle>
<DialogDescription className="flex items-center flex-col">
Une sauvegarde automatique s&apos;effectue en permanence pour éviter les pertes de données. Comme elles peuvent prendre du temps, vous
pouvez faire une sauvegarde manuelle avant de quitter la page avec le bouton &ldquo;Sauvegarder&rdquo;. Spammer ce bouton ne sert à
rien, juste peut entraîner des crash.
</DialogDescription>
<DialogFooter className="text-destructive">
ATTENTION: ne quittez pas la page tant que le status n&apos;est pas marqué en &ldquo;Sauvegardé&rdquo; au risque de perdre votre
contenu...
</DialogFooter>
<DialogTitle>{t.save.automaticsave}</DialogTitle>
<DialogDescription className="flex items-center flex-col">{t.save.savedescription}</DialogDescription>
<DialogFooter className="text-destructive">{t.save.savewarning}</DialogFooter>
</DialogHeader>
</DialogContent>
</Dialog>
Expand All @@ -120,6 +136,7 @@ interface ActionProps {
}

export function Actions({ setToBeChanged, content, value, title, id, dbLabels, blogLabels, locale }: ActionProps) {
const t = getDictionary(locale).navigation.admin.editblog;
const [getLabels, setLabels] = useState<string[]>(blogLabels);
const addRemoveLabel = (label: string) => {
var newLabels = getLabels;
Expand Down Expand Up @@ -150,15 +167,15 @@ export function Actions({ setToBeChanged, content, value, title, id, dbLabels, b
}}
>
<span className="flex items-center space-x-2">
<p>Sauvergarder</p>
<p>{t.save.save}</p>
<FaSave />
</span>
</Button>
<Rename id={id} title={title} router={router} />
<AddLabel addRemoveLabel={addRemoveLabel} dbLabels={dbLabels} getLabels={getLabels} />
<Rename id={id} title={title} router={router} t={t} locale={locale} />
<AddLabel addRemoveLabel={addRemoveLabel} dbLabels={dbLabels} getLabels={getLabels} t={t} />
</div>
<div>
<OpenSave saving={JSON.stringify(content) !== value} />
<OpenSave saving={JSON.stringify(content) !== value} t={t} />
</div>
</div>
{/* <div className="pb-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default async function EditBlog({ params: { postId, locale } }: LocalePos
<h1>{blog.title}</h1>
{blog.validated && <UnValidate locale={locale} id={id} />}
<QuillEditor
locale={blogLocale}
locale={locale}
id={id}
content={JSON.parse(blog.content)}
title={blog.title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ export function QuillEditor({ id, content, title, locale, dbLabels, blogLabels }
setValue(JSON.stringify(quill.getContents().ops));
const newContent = quill.getContents().ops;
if (newContent != content) {
updateLocaleBlogContent(id, newContent).finally(() => router.refresh());
updateLocaleBlogContent(id, newContent, locale).finally(() => router.refresh());
}
});
setLoaded(true);
}
}, [quill, content, id, router, loaded]);
}, [quill, content, id, router, loaded, locale]);

return (
<div className="w-full">
Expand Down
Loading
Loading