diff --git a/src/api/post/content-types/post/schema.json b/src/api/post/content-types/post/schema.json index 57a4ce0..1da6198 100644 --- a/src/api/post/content-types/post/schema.json +++ b/src/api/post/content-types/post/schema.json @@ -19,12 +19,7 @@ "type": "media", "multiple": true, "required": false, - "allowedTypes": [ - "images", - "files", - "videos", - "audios" - ] + "allowedTypes": ["images", "files", "videos", "audios"] }, "likes": { "type": "relation", @@ -33,11 +28,7 @@ }, "category": { "type": "enumeration", - "enum": [ - "photo", - "video", - "event" - ] + "enum": ["photo", "video", "event"] }, "comments": { "type": "relation", @@ -64,6 +55,11 @@ "relation": "oneToMany", "target": "api::post-ownership.post-ownership", "mappedBy": "post" + }, + "taggedContacts": { + "type": "relation", + "relation": "oneToMany", + "target": "plugin::users-permissions.user" } } } diff --git a/src/api/post/controllers/post.ts b/src/api/post/controllers/post.ts index 650763a..85e9944 100644 --- a/src/api/post/controllers/post.ts +++ b/src/api/post/controllers/post.ts @@ -28,6 +28,13 @@ export default factories.createCoreController( }); data.media = asset[0].id; } + + // Transformer taggedContacts en format de relation Strapi + if (data.taggedContacts && Array.isArray(data.taggedContacts)) { + data.taggedContacts = data.taggedContacts.map((id) => ({ id })); + } + + delete data.author; ctx.request.body = { data }; const result = await super.create(ctx); @@ -38,8 +45,8 @@ export default factories.createCoreController( data: { post: result.data.id, author: userId, - contextType: data.contextType || "user", - contextId: data.contextId || null, + contextType: "user", + contextId: userId, relation: "owner", }, }); @@ -82,6 +89,11 @@ export default factories.createCoreController( }, }, media: true, + taggedContacts: { + populate: { + avatar: true, + }, + }, }, }, author: { @@ -165,13 +177,14 @@ export default factories.createCoreController( .findMany({ where: { $or: [ - // Posts réguliers (amis, follows, groupes, système) - exclure les cachés + // Posts réguliers (amis, follows, groupes, système, mes propres posts) - exclure les cachés { $and: [ { $or: [ { author: { id: friendIds } }, // Posts de mes amis { author: { id: followIds } }, // Posts des contacts que je suis + { author: { id: parseInt(userId) }, relation: "owner" }, // Mes propres posts { contextType: "group", contextId: groupIds }, // Posts de mes groupes { contextType: "group", contextId: friendsGroupIds }, // Posts des groupes de mes amis { contextType: "system" }, // Posts système @@ -245,9 +258,68 @@ export default factories.createCoreController( const filteredFeedBlocked = enrichedFeed.filter((post) => !post.blocked); - ctx.send(filteredFeedBlocked); + // Trier par createdAt du post (le plus récent en premier) + const sortedFeed = filteredFeedBlocked.sort((a, b) => { + const dateA = a.post?.createdAt + ? new Date(a.post.createdAt).getTime() + : 0; + const dateB = b.post?.createdAt + ? new Date(b.post.createdAt).getTime() + : 0; + return dateB - dateA; // Ordre décroissant (plus récent en premier) + }); + + ctx.send(sortedFeed); }, + async likePost(ctx) { + const user = ctx.state.user; // Utilisateur actuellement connecté + if (!user) { + return ctx.unauthorized("You must be logged in to like a post."); + } + const postId = parseInt(String(ctx.params.id)); + + if (isNaN(postId)) { + return ctx.badRequest("Invalid post ID"); + } + // Verify the post exists + const existingPost = await strapi.db.query("api::post.post").findOne({ + where: { + id: postId, + }, + populate: { + likes: true, + }, + }); + if (!existingPost) { + return ctx.notFound("Post not found"); + } + // Check if the user has already liked the post + const existingLike = existingPost.likes.find( + (like) => like.id === user.id + ); + if (existingLike) { + await strapi.db.query("api::post.post").update({ + where: { id: postId }, + data: { + likes: { + disconnect: [{ id: user.id }], + }, + }, + }); + return ctx.send({ message: "Post unliked successfully" }); + } + // Update the postLikes field on the post entity + await strapi.db.query("api::post.post").update({ + where: { id: postId }, + data: { + likes: { + connect: [{ id: user.id }], + }, + }, + }); + ctx.send({ message: "Post liked successfully" }); + }, async savePost(ctx) { console.log("🎯 savePost called with params:", ctx.params); console.log("🎯 Request method:", ctx.request.method); diff --git a/src/api/post/routes/custom.ts b/src/api/post/routes/custom.ts index dc115a5..0c80026 100644 --- a/src/api/post/routes/custom.ts +++ b/src/api/post/routes/custom.ts @@ -29,5 +29,10 @@ export default { path: "/posts/feed", handler: "post.feed", }, + { + method: "PUT", + path: "/posts/:id/like", + handler: "post.likePost", + }, ], }; diff --git a/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/src/extensions/documentation/documentation/1.0.0/full_documentation.json index a0c0b97..bc569a8 100644 --- a/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2025-10-02T15:41:39.221Z" + "x-generation-date": "2025-10-03T14:17:22.193Z" }, "x-strapi-config": { "plugins": [ @@ -17004,6 +17004,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -20438,6 +20452,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -24314,6 +24342,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -27749,6 +27791,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -31632,6 +31688,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -35766,6 +35836,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -40306,6 +40390,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -44179,6 +44277,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -47954,6 +48066,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -51716,6 +51842,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -55514,6 +55654,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -59312,6 +59466,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -63071,6 +63239,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -67011,6 +67193,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -70440,6 +70636,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -75115,6 +75325,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -79188,6 +79412,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -82965,6 +83203,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -86849,6 +87101,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -90113,6 +90379,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -91129,6 +91409,20 @@ "example": "string or id" } }, + "taggedContacts": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "string" + } + ], + "example": "string or id" + } + }, "locale": { "type": "string" }, @@ -94555,6 +94849,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -94960,6 +95268,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -98364,6 +98686,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -102147,6 +102483,20 @@ } } }, + "taggedContacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, "createdAt": { "type": "string", "format": "date-time" diff --git a/types/generated/contentTypes.d.ts b/types/generated/contentTypes.d.ts index 7ce6b85..226060d 100644 --- a/types/generated/contentTypes.d.ts +++ b/types/generated/contentTypes.d.ts @@ -1255,6 +1255,10 @@ export interface ApiPostPost extends Struct.CollectionTypeSchema { publishedAt: Schema.Attribute.DateTime; shares: Schema.Attribute.Integer; source: Schema.Attribute.String; + taggedContacts: Schema.Attribute.Relation< + 'oneToMany', + 'plugin::users-permissions.user' + >; title: Schema.Attribute.String; updatedAt: Schema.Attribute.DateTime; updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &