From 4dff218db4ef0e32d71171da9717dbcc23950437 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 14 Jun 2025 10:32:12 +0200 Subject: [PATCH] working prototype --- .../src/graphql/queries/createPostMutation.ts | 4 +- backend/src/graphql/resolvers/posts.ts | 61 ++++++++++++++++++- backend/src/graphql/types/type/Post.gql | 2 +- backend/src/middleware/helpers/cleanHtml.ts | 2 +- .../ContributionForm/ContributionForm.vue | 23 +++---- webapp/graphql/PostMutations.js | 4 +- 6 files changed, 76 insertions(+), 20 deletions(-) diff --git a/backend/src/graphql/queries/createPostMutation.ts b/backend/src/graphql/queries/createPostMutation.ts index 2a285401e..deda9ca24 100644 --- a/backend/src/graphql/queries/createPostMutation.ts +++ b/backend/src/graphql/queries/createPostMutation.ts @@ -7,7 +7,7 @@ export const createPostMutation = () => { $title: String! $slug: String $content: String! - $filesToUpload: [FileInput] + $files: [FileInput] $categoryIds: [ID] $groupId: ID $postType: PostType @@ -18,7 +18,7 @@ export const createPostMutation = () => { title: $title slug: $slug content: $content - $filesToUpload: $filesToUpload + $files: $files categoryIds: $categoryIds groupId: $groupId postType: $postType diff --git a/backend/src/graphql/resolvers/posts.ts b/backend/src/graphql/resolvers/posts.ts index cef255634..4334bfdc8 100644 --- a/backend/src/graphql/resolvers/posts.ts +++ b/backend/src/graphql/resolvers/posts.ts @@ -9,7 +9,7 @@ import { isEmpty } from 'lodash' import { neo4jgraphql } from 'neo4j-graphql-js' import { v4 as uuid } from 'uuid' -import CONFIG from '@config/index' +import CONFIG, { isS3configured } from '@config/index' import { Context } from '@src/server' import { validateEventParams } from './helpers/events' @@ -19,6 +19,7 @@ import { filterPostsOfMyGroups } from './helpers/filterPostsOfMyGroups' import Resolver from './helpers/Resolver' import { images } from './images/images' import { createOrUpdateLocations } from './users/location' +import { attachments } from './attachments/attachments' const maintainPinnedPosts = (params) => { const pinnedPostFilter = { pinned: true } @@ -111,14 +112,15 @@ export default { }, Mutation: { CreatePost: async (_parent, params, context, _resolveInfo) => { - const { categoryIds, groupId } = params - const { image: imageInput } = params + const { categoryIds, groupId, image: imageInput, files = [] } = params + console.log(params.content) const locationName = validateEventParams(params) delete params.categoryIds delete params.image delete params.groupId + delete params.files params.id = params.id || uuid() const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -186,6 +188,59 @@ export default { if (locationName) { await createOrUpdateLocations('Post', post.id, locationName, session) } + + // can this happen? + // if (!post) { + // return null + // } + + const writeFilesPromise = session.writeTransaction(async (transaction) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const atns: any[] = [] + + if (!isS3configured(CONFIG)) { + return atns + } + + for await (const file of files) { + const atn = await attachments(CONFIG).add( + post, + 'ATTACHMENT', + file, + {}, + { + transaction, + }, + ) + atns.push(atn) + } + return atns + }) + + const atns = await writeFilesPromise + + for await (const atn of atns) { + post.content = post.content.replace( + `${atn.name}`, + `${atn.name}`, + ) + post.contentExcerpt = post.contentExcerpt.replace( + `${atn.name}`, + `${atn.name}`, + ) + } + + await context.database.write({ + query: ` + MATCH (post:Post {id: $post.id}) + SET post.content = $post.content + SET post.contentExcerpt = $post.contentExcerpt + `, + variables: { + post, + }, + }) + return post } catch (e) { if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed') diff --git a/backend/src/graphql/types/type/Post.gql b/backend/src/graphql/types/type/Post.gql index 09f6fb8c9..d742a6938 100644 --- a/backend/src/graphql/types/type/Post.gql +++ b/backend/src/graphql/types/type/Post.gql @@ -216,7 +216,7 @@ type Mutation { title: String! slug: String content: String! - filesToUpload: [FileInput] + files: [FileInput] image: ImageInput, visibility: Visibility language: String diff --git a/backend/src/middleware/helpers/cleanHtml.ts b/backend/src/middleware/helpers/cleanHtml.ts index d429f8f9d..1ee0036c9 100644 --- a/backend/src/middleware/helpers/cleanHtml.ts +++ b/backend/src/middleware/helpers/cleanHtml.ts @@ -41,7 +41,7 @@ const standardSanitizeHtmlOptions = { allowedAttributes: { a: ['href', 'class', 'target', 'data-*', 'contenteditable'], span: ['contenteditable', 'class', 'data-*'], - img: ['src'], + img: ['src', 'alt'], }, allowedIframeHostnames: ['www.youtube.com', 'player.vimeo.com'], parser: { diff --git a/webapp/components/ContributionForm/ContributionForm.vue b/webapp/components/ContributionForm/ContributionForm.vue index 19685b2c9..fada53129 100644 --- a/webapp/components/ContributionForm/ContributionForm.vue +++ b/webapp/components/ContributionForm/ContributionForm.vue @@ -394,13 +394,14 @@ export default { } this.loading = true + console.log(content) this.$apollo .mutate({ mutation: this.contribution.id ? PostMutations().UpdatePost : PostMutations().CreatePost, variables: { title, content, - filesToUpload: this.filesToUpload, + files: this.filesToUpload, categoryIds, id: this.contribution.id || null, image, @@ -429,20 +430,20 @@ export default { const blobImages = value.match(/]+src="blob:[^"]+"[^>]*>/g) || [] this.filesToUpload = await Promise.all( blobImages - .map((img) => { - const srcMatch = img.match(/src="([^"]+)"/) - return srcMatch ? srcMatch[1] : null - }) - .filter(Boolean) - .map(async (src) => { - const fileName = src.split('/').pop() - const blob = await urlToBlob(src) + .map(async (img) => { + const src = img.match(/src="([^"]+)"/) + const filename = img.match(/alt="([^"]+)"/) + if (!src) { + return null + } + const blob = await urlToBlob(src[1]) return { upload: blob, - name: fileName, + name: filename[1], type: 'image/jpeg', } - }), + }) + .filter(Boolean), ) this.$refs.contributionForm.update('content', value) diff --git a/webapp/graphql/PostMutations.js b/webapp/graphql/PostMutations.js index 00954e11d..5059654b5 100644 --- a/webapp/graphql/PostMutations.js +++ b/webapp/graphql/PostMutations.js @@ -8,7 +8,7 @@ export default () => { $title: String! $slug: String $content: String! - $filesToUpload: [FileInput] + $files: [FileInput] $categoryIds: [ID] $image: ImageInput $groupId: ID @@ -20,7 +20,7 @@ export default () => { title: $title slug: $slug content: $content - filesToUpload: $filesToUpload + files: $files categoryIds: $categoryIds image: $image groupId: $groupId