From 3734e2ef56b3209a83b724957179d72d65523c8a Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Apr 2025 17:56:11 +0200 Subject: [PATCH 01/18] feat(backend): notify users when a followed user posted (#8313) --- .../notifications/followed-users.spec.ts | 420 ++++++++++++++++++ .../notifications/notificationsMiddleware.ts | 45 ++ .../validation/validationMiddleware.ts | 7 +- backend/src/models/User.ts | 4 + backend/src/schema/resolvers/users.spec.ts | 8 + backend/src/schema/resolvers/users.ts | 4 + .../enum/EmailNotificationSettingsName.gql | 3 +- backend/src/schema/types/type/NOTIFIED.gql | 1 + webapp/locales/de.json | 4 +- webapp/locales/en.json | 4 +- webapp/locales/es.json | 2 + webapp/locales/fr.json | 2 + webapp/locales/it.json | 2 + webapp/locales/nl.json | 2 + webapp/locales/pl.json | 2 + webapp/locales/pt.json | 2 + webapp/locales/ru.json | 2 + 17 files changed, 510 insertions(+), 4 deletions(-) create mode 100644 backend/src/middleware/notifications/followed-users.spec.ts diff --git a/backend/src/middleware/notifications/followed-users.spec.ts b/backend/src/middleware/notifications/followed-users.spec.ts new file mode 100644 index 000000000..b82ef2571 --- /dev/null +++ b/backend/src/middleware/notifications/followed-users.spec.ts @@ -0,0 +1,420 @@ +import { createTestClient } from 'apollo-server-testing' +import gql from 'graphql-tag' + +import { cleanDatabase } from '@db/factories' +import { getNeode, getDriver } from '@db/neo4j' +import { createGroupMutation } from '@graphql/groups' +import CONFIG from '@src/config' +import createServer from '@src/server' + +CONFIG.CATEGORIES_ACTIVE = false + +let server, query, mutate, authenticatedUser + +let postAuthor, firstFollower, secondFollower + +const driver = getDriver() +const neode = getNeode() + +const createPostMutation = gql` + mutation ($id: ID, $title: String!, $content: String!, $groupId: ID) { + CreatePost(id: $id, title: $title, content: $content, groupId: $groupId) { + id + title + content + } + } +` + +const notificationQuery = gql` + query ($read: Boolean) { + notifications(read: $read, orderBy: updatedAt_desc) { + read + reason + createdAt + relatedUser { + id + } + from { + __typename + ... on Post { + id + content + } + ... on Comment { + id + content + } + ... on Group { + id + } + } + } + } +` + +const followUserMutation = gql` + mutation ($id: ID!) { + followUser(id: $id) { + id + } + } +` + +beforeAll(async () => { + await cleanDatabase() + + const createServerResult = createServer({ + context: () => { + return { + user: authenticatedUser, + neode, + driver, + cypherParams: { + currentUserId: authenticatedUser ? authenticatedUser.id : null, + }, + } + }, + }) + server = createServerResult.server + const createTestClientResult = createTestClient(server) + query = createTestClientResult.query + mutate = createTestClientResult.mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('following users notifications', () => { + beforeAll(async () => { + postAuthor = await neode.create( + 'User', + { + id: 'post-author', + name: 'Post Author', + slug: 'post-author', + }, + { + email: 'test@example.org', + password: '1234', + }, + ) + firstFollower = await neode.create( + 'User', + { + id: 'first-follower', + name: 'First Follower', + slug: 'first-follower', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + secondFollower = await neode.create( + 'User', + { + id: 'second-follower', + name: 'Second Follower', + slug: 'second-follower', + }, + { + email: 'test3@example.org', + password: '1234', + }, + ) + await secondFollower.update({ emailNotificationsFollowingUsers: false }) + authenticatedUser = await firstFollower.toJson() + await mutate({ + mutation: followUserMutation, + variables: { id: 'post-author' }, + }) + authenticatedUser = await secondFollower.toJson() + await mutate({ + mutation: followUserMutation, + variables: { id: 'post-author' }, + }) + }) + + describe('the followed user writes a post', () => { + beforeAll(async () => { + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'post', + title: 'This is the post', + content: 'This is the content of the post', + }, + }) + }) + + it('sends NO notification to the post author', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends notification to the first follower', async () => { + authenticatedUser = await firstFollower.toJson() + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'followed_user_posted', + }, + ], + }, + errors: undefined, + }) + }) + + it('sends notification to the second follower', async () => { + authenticatedUser = await secondFollower.toJson() + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'followed_user_posted', + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('followed user posts in public group', () => { + beforeAll(async () => { + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createGroupMutation(), + variables: { + id: 'g-1', + name: 'A group', + description: 'A group to test the follow user notification', + groupType: 'public', + actionRadius: 'national', + }, + }) + await mutate({ + mutation: createPostMutation, + variables: { + id: 'group-post', + title: 'This is the post in the group', + content: 'This is the content of the post in the group', + groupId: 'g-1', + }, + }) + }) + + it('sends NO notification to the post author', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends notification to the first follower although he is no member of the group', async () => { + authenticatedUser = await firstFollower.toJson() + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'group-post', + }, + read: false, + reason: 'followed_user_posted', + }, + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'followed_user_posted', + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('followed user posts in closed group', () => { + beforeAll(async () => { + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createGroupMutation(), + variables: { + id: 'g-2', + name: 'A closed group', + description: 'A group to test the follow user notification', + groupType: 'closed', + actionRadius: 'national', + }, + }) + await mutate({ + mutation: createPostMutation, + variables: { + id: 'closed-group-post', + title: 'This is the post in the closed group', + content: 'This is the content of the post in the closed group', + groupId: 'g-2', + }, + }) + }) + + it('sends NO notification to the post author', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends NO notification to the first follower', async () => { + authenticatedUser = await firstFollower.toJson() + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'group-post', + }, + read: false, + reason: 'followed_user_posted', + }, + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'followed_user_posted', + }, + ], + }, + errors: undefined, + }) + }) + }) + + describe('followed user posts in hidden group', () => { + beforeAll(async () => { + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createGroupMutation(), + variables: { + id: 'g-3', + name: 'A hidden group', + description: 'A hidden group to test the follow user notification', + groupType: 'hidden', + actionRadius: 'national', + }, + }) + await mutate({ + mutation: createPostMutation, + variables: { + id: 'hidden-group-post', + title: 'This is the post in the hidden group', + content: 'This is the content of the post in the hidden group', + groupId: 'g-3', + }, + }) + }) + + it('sends NO notification to the post author', async () => { + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends NO notification to the first follower', async () => { + authenticatedUser = await firstFollower.toJson() + await expect( + query({ + query: notificationQuery, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'group-post', + }, + read: false, + reason: 'followed_user_posted', + }, + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'followed_user_posted', + }, + ], + }, + errors: undefined, + }) + }) + }) +}) diff --git a/backend/src/middleware/notifications/notificationsMiddleware.ts b/backend/src/middleware/notifications/notificationsMiddleware.ts index d24ddc8ef..a733bc201 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.ts +++ b/backend/src/middleware/notifications/notificationsMiddleware.ts @@ -111,6 +111,7 @@ const handleRemoveUserFromGroup = async (resolve, root, args, context, resolveIn } const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => { + const { groupId } = args const idsOfUsers = extractMentionedUsers(args.content) const post = await resolve(root, args, context, resolveInfo) if (post) { @@ -119,6 +120,11 @@ const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo [notifyUsersOfMention('Post', post.id, idsOfUsers, 'mentioned_in_post', context)], 'emailNotificationsMention', ) + await publishNotifications( + context, + [notifyFollowingUsers(post.id, groupId, context)], + 'emailNotificationsFollowingUsers', + ) } return post } @@ -171,6 +177,45 @@ const postAuthorOfComment = async (commentId, { context }) => { } } +const notifyFollowingUsers = async (postId, groupId, context) => { + const reason = 'followed_user_posted' + const cypher = ` + MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId })<-[:FOLLOWS]-(user:User) + OPTIONAL MATCH (post)-[:IN]->(group:Group { id: $groupId }) + WITH post, author, user, group WHERE group IS NULL OR group.groupType = 'public' + MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user) + SET notification.read = FALSE + SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) + SET notification.updatedAt = toString(datetime()) + WITH notification, author, user, + post {.*, author: properties(author) } AS finalResource + RETURN notification { + .*, + from: finalResource, + to: properties(user), + relatedUser: properties(author) + } + ` + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const notificationTransactionResponse = await transaction.run(cypher, { + postId, + reason, + groupId: groupId || null, + userId: context.user.id, + }) + return notificationTransactionResponse.records.map((record) => record.get('notification')) + }) + try { + const notifications = await writeTxResultPromise + return notifications + } catch (error) { + throw new Error(error) + } finally { + session.close() + } +} + const notifyOwnersOfGroup = async (groupId, userId, reason, context) => { const cypher = ` MATCH (user:User { id: $userId }) diff --git a/backend/src/middleware/validation/validationMiddleware.ts b/backend/src/middleware/validation/validationMiddleware.ts index ff26f5ef1..0920df6e0 100644 --- a/backend/src/middleware/validation/validationMiddleware.ts +++ b/backend/src/middleware/validation/validationMiddleware.ts @@ -101,7 +101,12 @@ const validateReview = async (resolve, root, args, context, info) => { } export const validateNotifyUsers = async (label, reason) => { - const reasonsAllowed = ['mentioned_in_post', 'mentioned_in_comment', 'commented_on_post'] + const reasonsAllowed = [ + 'mentioned_in_post', + 'mentioned_in_comment', + 'commented_on_post', + 'followed_user_posted', + ] if (!reasonsAllowed.includes(reason)) throw new Error('Notification reason is not allowed!') if ( (label === 'Post' && reason !== 'mentioned_in_post') || diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index e9fbfb6ce..e0cc770b4 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -185,6 +185,10 @@ export default { type: 'boolean', default: true, }, + emailNotificationsFollowingUsers: { + type: 'boolean', + default: true, + }, locale: { type: 'string', diff --git a/backend/src/schema/resolvers/users.spec.ts b/backend/src/schema/resolvers/users.spec.ts index df5a7f785..77d606fbb 100644 --- a/backend/src/schema/resolvers/users.spec.ts +++ b/backend/src/schema/resolvers/users.spec.ts @@ -675,6 +675,10 @@ describe('emailNotificationSettings', () => { name: 'mention', value: true, }, + { + name: 'followingUsers', + value: true, + }, ], }, { @@ -765,6 +769,10 @@ describe('emailNotificationSettings', () => { name: 'mention', value: false, }, + { + name: 'followingUsers', + value: true, + }, ], }, { diff --git a/backend/src/schema/resolvers/users.ts b/backend/src/schema/resolvers/users.ts index cca8e1278..134fb34cb 100644 --- a/backend/src/schema/resolvers/users.ts +++ b/backend/src/schema/resolvers/users.ts @@ -383,6 +383,10 @@ export default { name: 'mention', value: parent.emailNotificationsMention ?? true, }, + { + name: 'followingUsers', + value: parent.emailNotificationsFollowingUsers ?? true, + }, ], }, { diff --git a/backend/src/schema/types/enum/EmailNotificationSettingsName.gql b/backend/src/schema/types/enum/EmailNotificationSettingsName.gql index fa1d5846e..bcc6e617c 100644 --- a/backend/src/schema/types/enum/EmailNotificationSettingsName.gql +++ b/backend/src/schema/types/enum/EmailNotificationSettingsName.gql @@ -1,9 +1,10 @@ enum EmailNotificationSettingsName { commentOnObservedPost mention + followingUsers chatMessage groupMemberJoined groupMemberLeft groupMemberRemoved groupMemberRoleChanged -} \ No newline at end of file +} diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index 1f825decc..2726f503a 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -26,6 +26,7 @@ enum NotificationReason { user_left_group changed_group_member_role removed_user_from_group + followed_user_posted } type Query { diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 42f6ab74f..0a64283a5 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -737,7 +737,8 @@ "post": "Beitrag oder Gruppe", "reason": { "changed_group_member_role": "Hat Deine Rolle in der Gruppe geändert …", - "commented_on_post": "Hat Deinen Beitrag kommentiert …", + "commented_on_post": "Hat einen Beitrag den du beobachtest kommentiert …", + "followed_user_posted": "Hat einen neuen Betrag geschrieben …", "mentioned_in_comment": "Hat Dich in einem Kommentar erwähnt …", "mentioned_in_post": "Hat Dich in einem Beitrag erwähnt …", "removed_user_from_group": "Hat Dich aus der Gruppe entfernt …", @@ -1043,6 +1044,7 @@ "chatMessage": "Nachricht erhalten während Abwesenheit", "checkAll": "Alle auswählen", "commentOnObservedPost": "Kommentare zu beobachteten Beiträgen", + "followingUsers": "Ein Nutzer dem ich folge veröffentlichte einen neuen Beitrag", "group": "Gruppen", "groupMemberJoined": "Ein Mitglied ist deiner Gruppe beigetreten", "groupMemberLeft": "Ein Mitglied hat deine Gruppe verlassen", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 714c3f3c0..f73e77804 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -737,7 +737,8 @@ "post": "Post or Group", "reason": { "changed_group_member_role": "Changed your role in group …", - "commented_on_post": "Commented on your post …", + "commented_on_post": "Commented on a post you observe …", + "followed_user_posted": "Wrote a new post …", "mentioned_in_comment": "Mentioned you in a comment …", "mentioned_in_post": "Mentioned you in a post …", "removed_user_from_group": "Removed you from group …", @@ -1043,6 +1044,7 @@ "chatMessage": "Message received while absent", "checkAll": "Check all", "commentOnObservedPost": "Comments on observed posts", + "followingUsers": "User I follow published a new post", "group": "Groups", "groupMemberJoined": "Member joined a group I own", "groupMemberLeft": "Member left a group I own", diff --git a/webapp/locales/es.json b/webapp/locales/es.json index f0a1a866b..8efa724e9 100644 --- a/webapp/locales/es.json +++ b/webapp/locales/es.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": "Comentó su contribución ...", + "followed_user_posted": null, "mentioned_in_comment": "Le mencionó en un comentario …", "mentioned_in_post": "Le mencionó en una contribución …", "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Mensaje recibido mientras estaba ausente", "checkAll": "Seleccionar todo", "commentOnObservedPost": "Comentario en una contribución que estoy observando", + "followingUsers": null, "group": "Grupos", "groupMemberJoined": "Un nuevo miembro se unió a un grupo mio", "groupMemberLeft": "Un miembro dejó un grupo mio", diff --git a/webapp/locales/fr.json b/webapp/locales/fr.json index a31e197a1..e00df6543 100644 --- a/webapp/locales/fr.json +++ b/webapp/locales/fr.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": "Commenté sur votre post…", + "followed_user_posted": null, "mentioned_in_comment": "Vous a mentionné dans un commentaire…", "mentioned_in_post": "Vous a mentionné dans un post…", "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Message reçu pendant l'absence", "checkAll": "Tout cocher", "commentOnObservedPost": "Commentez une contribution que je suis", + "followingUsers": null, "group": "Groups", "groupMemberJoined": "Un nouveau membre a rejoint un de mes groupes", "groupMemberLeft": "Un membre a quitté un de mes groupes", diff --git a/webapp/locales/it.json b/webapp/locales/it.json index 8f14dfda2..52597f9fb 100644 --- a/webapp/locales/it.json +++ b/webapp/locales/it.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": null, + "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Messaggio ricevuto durante l'assenza", "checkAll": "Seleziona tutto", "commentOnObservedPost": "Commenta un contributo che sto guardando", + "followingUsers": null, "group": "Gruppi", "groupMemberJoined": "Un nuovo membro si è unito a un mio gruppo", "groupMemberLeft": "Un membro ha lasciato un mio gruppo", diff --git a/webapp/locales/nl.json b/webapp/locales/nl.json index e332d38dc..bbf99f186 100644 --- a/webapp/locales/nl.json +++ b/webapp/locales/nl.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": null, + "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Bericht ontvangen tijdens afwezigheid", "checkAll": "Vink alles aan", "commentOnObservedPost": "Geef commentaar op een bijdrage die ik volg", + "followingUsers": null, "group": "Groepen", "groupMemberJoined": "Een nieuw lid is lid geworden van een groep van mij", "groupMemberLeft": "Een lid heeft een groep van mij verlaten", diff --git a/webapp/locales/pl.json b/webapp/locales/pl.json index 5c636dfab..78223f943 100644 --- a/webapp/locales/pl.json +++ b/webapp/locales/pl.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": null, + "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Wiadomość otrzymana podczas nieobecności", "checkAll": "Wybierz wszystko", "commentOnObservedPost": "Skomentuj wpis, który obserwuję", + "followingUsers": null, "group": "Grupy", "groupMemberJoined": "Nowy członek dołączył do mojej grupy", "groupMemberLeft": "Członek opuścił moją grupę", diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index c00acbf0a..4848546a0 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": "Comentou no seu post …", + "followed_user_posted": null, "mentioned_in_comment": "Mentionou você em um comentário …", "mentioned_in_post": "Mencinou você em um post …", "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Mensagem recebida durante a ausência", "checkAll": "Marcar tudo", "commentOnObservedPost": "Comentários sobre as mensagens observadas", + "followingUsers": null, "group": "Grupos", "groupMemberJoined": "Member joined a group I own", "groupMemberLeft": "Membro saiu de um grupo de que sou proprietário", diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json index 5775264fa..ac33dff47 100644 --- a/webapp/locales/ru.json +++ b/webapp/locales/ru.json @@ -738,6 +738,7 @@ "reason": { "changed_group_member_role": null, "commented_on_post": "Комментарий к посту...", + "followed_user_posted": null, "mentioned_in_comment": "Упоминание в комментарии....", "mentioned_in_post": "Упоминание в посте....", "removed_user_from_group": null, @@ -1043,6 +1044,7 @@ "chatMessage": "Сообщение, полученное во время отсутствия", "checkAll": "Отметить все", "commentOnObservedPost": "Комментарии по поводу замеченных сообщений", + "followingUsers": null, "group": "Группы", "groupMemberJoined": "Участник присоединился к группе, которой я владею", "groupMemberLeft": "Участник вышел из группы, которой владею", From 7b4b0774e4c0a17128c7dc8eeb106b3a59599de4 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 11 Apr 2025 19:44:22 +0200 Subject: [PATCH 02/18] docker compose files: use current maildev image from the right repo (#8351) --- docker-compose.override.yml | 6 +++--- docker-compose.test.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 53f7e7b4e..e0f91c358 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -39,8 +39,8 @@ services: - 7474:7474 mailserver: - image: djfarrelly/maildev + image: maildev/maildev container_name: mailserver ports: - - 1080:80 - - 25:25 + - 1080:1080 + - 1025:1025 diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 119cd20eb..cc7490106 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -37,7 +37,7 @@ services: # - NEO4J_dbms_connector_https_listen__address=0.0.0.0:7473 mailserver: - image: djfarrelly/maildev + image: maildev/maildev ports: - - 1080:80 - - 25:25 + - 1080:1080 + - 1025:1025 From aedf8d93c759c16fc6de678bac57ad94cc9b0eb4 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Apr 2025 22:50:59 +0200 Subject: [PATCH 03/18] feat(backend): notify posts in groups (#8346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wolfgang Huß --- .../notifications/followed-users.spec.ts | 26 +- .../notifications/notificationsMiddleware.ts | 48 +++ .../notifications/posts-in-groups.spec.ts | 395 ++++++++++++++++++ .../src/middleware/permissionsMiddleware.ts | 2 + .../validation/validationMiddleware.ts | 1 + backend/src/models/User.ts | 4 + backend/src/schema/resolvers/groups.ts | 62 +++ backend/src/schema/resolvers/users.spec.ts | 8 + backend/src/schema/resolvers/users.ts | 4 + .../enum/EmailNotificationSettingsName.gql | 1 + backend/src/schema/types/type/Group.gql | 7 + backend/src/schema/types/type/NOTIFIED.gql | 1 + webapp/locales/de.json | 1 + webapp/locales/en.json | 1 + webapp/locales/es.json | 1 + webapp/locales/fr.json | 1 + webapp/locales/it.json | 1 + webapp/locales/nl.json | 1 + webapp/locales/pl.json | 1 + webapp/locales/pt.json | 1 + webapp/locales/ru.json | 1 + 21 files changed, 560 insertions(+), 8 deletions(-) create mode 100644 backend/src/middleware/notifications/posts-in-groups.spec.ts diff --git a/backend/src/middleware/notifications/followed-users.spec.ts b/backend/src/middleware/notifications/followed-users.spec.ts index b82ef2571..4d4b0e872 100644 --- a/backend/src/middleware/notifications/followed-users.spec.ts +++ b/backend/src/middleware/notifications/followed-users.spec.ts @@ -1,7 +1,7 @@ import { createTestClient } from 'apollo-server-testing' import gql from 'graphql-tag' -import { cleanDatabase } from '@db/factories' +import Factory, { cleanDatabase } from '@db/factories' import { getNeode, getDriver } from '@db/neo4j' import { createGroupMutation } from '@graphql/groups' import CONFIG from '@src/config' @@ -9,6 +9,11 @@ import createServer from '@src/server' CONFIG.CATEGORIES_ACTIVE = false +const sendMailMock = jest.fn() +jest.mock('../helpers/email/sendMail', () => ({ + sendMail: () => sendMailMock(), +})) + let server, query, mutate, authenticatedUser let postAuthor, firstFollower, secondFollower @@ -89,8 +94,8 @@ afterAll(async () => { describe('following users notifications', () => { beforeAll(async () => { - postAuthor = await neode.create( - 'User', + postAuthor = await Factory.build( + 'user', { id: 'post-author', name: 'Post Author', @@ -101,8 +106,8 @@ describe('following users notifications', () => { password: '1234', }, ) - firstFollower = await neode.create( - 'User', + firstFollower = await Factory.build( + 'user', { id: 'first-follower', name: 'First Follower', @@ -113,8 +118,8 @@ describe('following users notifications', () => { password: '1234', }, ) - secondFollower = await neode.create( - 'User', + secondFollower = await Factory.build( + 'user', { id: 'second-follower', name: 'Second Follower', @@ -136,6 +141,7 @@ describe('following users notifications', () => { mutation: followUserMutation, variables: { id: 'post-author' }, }) + jest.clearAllMocks() }) describe('the followed user writes a post', () => { @@ -209,6 +215,10 @@ describe('following users notifications', () => { errors: undefined, }) }) + + it('sends only one email, as second follower has emails disabled', () => { + expect(sendMailMock).toHaveBeenCalledTimes(1) + }) }) describe('followed user posts in public group', () => { @@ -248,7 +258,7 @@ describe('following users notifications', () => { }) }) - it('sends notification to the first follower although he is no member of the group', async () => { + it('sends a notification to the first follower', async () => { authenticatedUser = await firstFollower.toJson() await expect( query({ diff --git a/backend/src/middleware/notifications/notificationsMiddleware.ts b/backend/src/middleware/notifications/notificationsMiddleware.ts index a733bc201..ebbcd7886 100644 --- a/backend/src/middleware/notifications/notificationsMiddleware.ts +++ b/backend/src/middleware/notifications/notificationsMiddleware.ts @@ -125,6 +125,11 @@ const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo [notifyFollowingUsers(post.id, groupId, context)], 'emailNotificationsFollowingUsers', ) + await publishNotifications( + context, + [notifyGroupMembersOfNewPost(post.id, groupId, context)], + 'emailNotificationsPostInGroup', + ) } return post } @@ -216,6 +221,49 @@ const notifyFollowingUsers = async (postId, groupId, context) => { } } +const notifyGroupMembersOfNewPost = async (postId, groupId, context) => { + if (!groupId) return [] + const reason = 'post_in_group' + const cypher = ` + MATCH (post:Post { id: $postId })<-[:WROTE]-(author:User { id: $userId }) + MATCH (post)-[:IN]->(group:Group { id: $groupId })<-[membership:MEMBER_OF]-(user:User) + WHERE NOT membership.role = 'pending' + AND NOT (user)-[:MUTED]->(group) + AND NOT user.id = $userId + WITH post, author, user + MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user) + SET notification.read = FALSE + SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime())) + SET notification.updatedAt = toString(datetime()) + WITH notification, author, user, + post {.*, author: properties(author) } AS finalResource + RETURN notification { + .*, + from: finalResource, + to: properties(user), + relatedUser: properties(author) + } + ` + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const notificationTransactionResponse = await transaction.run(cypher, { + postId, + reason, + groupId, + userId: context.user.id, + }) + return notificationTransactionResponse.records.map((record) => record.get('notification')) + }) + try { + const notifications = await writeTxResultPromise + return notifications + } catch (error) { + throw new Error(error) + } finally { + session.close() + } +} + const notifyOwnersOfGroup = async (groupId, userId, reason, context) => { const cypher = ` MATCH (user:User { id: $userId }) diff --git a/backend/src/middleware/notifications/posts-in-groups.spec.ts b/backend/src/middleware/notifications/posts-in-groups.spec.ts new file mode 100644 index 000000000..86e700d1c --- /dev/null +++ b/backend/src/middleware/notifications/posts-in-groups.spec.ts @@ -0,0 +1,395 @@ +import { createTestClient } from 'apollo-server-testing' +import gql from 'graphql-tag' + +import Factory, { cleanDatabase } from '@db/factories' +import { getNeode, getDriver } from '@db/neo4j' +import { + createGroupMutation, + joinGroupMutation, + changeGroupMemberRoleMutation, +} from '@graphql/groups' +import CONFIG from '@src/config' +import createServer from '@src/server' + +CONFIG.CATEGORIES_ACTIVE = false + +const sendMailMock = jest.fn() +jest.mock('../helpers/email/sendMail', () => ({ + sendMail: () => sendMailMock(), +})) + +let server, query, mutate, authenticatedUser + +let postAuthor, groupMember, pendingMember + +const driver = getDriver() +const neode = getNeode() + +const createPostMutation = gql` + mutation ($id: ID, $title: String!, $content: String!, $groupId: ID) { + CreatePost(id: $id, title: $title, content: $content, groupId: $groupId) { + id + title + content + } + } +` + +const notificationQuery = gql` + query ($read: Boolean) { + notifications(read: $read, orderBy: updatedAt_desc) { + read + reason + createdAt + relatedUser { + id + } + from { + __typename + ... on Post { + id + content + } + ... on Comment { + id + content + } + ... on Group { + id + } + } + } + } +` + +const muteGroupMutation = gql` + mutation ($id: ID!) { + muteGroup(id: $id) { + id + isMutedByMe + } + } +` + +const unmuteGroupMutation = gql` + mutation ($id: ID!) { + unmuteGroup(id: $id) { + id + isMutedByMe + } + } +` + +const markAllAsRead = async () => + mutate({ + mutation: gql` + mutation { + markAllAsRead { + id + } + } + `, + }) + +beforeAll(async () => { + await cleanDatabase() + + const createServerResult = createServer({ + context: () => { + return { + user: authenticatedUser, + neode, + driver, + cypherParams: { + currentUserId: authenticatedUser ? authenticatedUser.id : null, + }, + } + }, + }) + server = createServerResult.server + const createTestClientResult = createTestClient(server) + query = createTestClientResult.query + mutate = createTestClientResult.mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('notify group members of new posts in group', () => { + beforeAll(async () => { + postAuthor = await Factory.build( + 'user', + { + id: 'post-author', + name: 'Post Author', + slug: 'post-author', + }, + { + email: 'test@example.org', + password: '1234', + }, + ) + groupMember = await Factory.build( + 'user', + { + id: 'group-member', + name: 'Group Member', + slug: 'group-member', + }, + { + email: 'test2@example.org', + password: '1234', + }, + ) + pendingMember = await Factory.build( + 'user', + { + id: 'pending-member', + name: 'Pending Member', + slug: 'pending-member', + }, + { + email: 'test3@example.org', + password: '1234', + }, + ) + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createGroupMutation(), + variables: { + id: 'g-1', + name: 'A closed group', + description: 'A closed group to test the notifications to group members', + groupType: 'closed', + actionRadius: 'national', + }, + }) + authenticatedUser = await groupMember.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'g-1', + userId: 'group-member', + }, + }) + authenticatedUser = await pendingMember.toJson() + await mutate({ + mutation: joinGroupMutation(), + variables: { + groupId: 'g-1', + userId: 'pending-member', + }, + }) + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: changeGroupMemberRoleMutation(), + variables: { + groupId: 'g-1', + userId: 'group-member', + roleInGroup: 'usual', + }, + }) + }) + + describe('group owner posts in group', () => { + beforeAll(async () => { + jest.clearAllMocks() + authenticatedUser = await groupMember.toJson() + await markAllAsRead() + authenticatedUser = await postAuthor.toJson() + await markAllAsRead() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'post', + title: 'This is the new post in the group', + content: 'This is the content of the new post in the group', + groupId: 'g-1', + }, + }) + }) + + it('sends NO notification to the author of the post', async () => { + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends NO notification to the pending group member', async () => { + authenticatedUser = await pendingMember.toJson() + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + it('sends notification to the group member', async () => { + authenticatedUser = await groupMember.toJson() + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'post', + }, + read: false, + reason: 'post_in_group', + }, + ], + }, + errors: undefined, + }) + }) + + it('sends one email', () => { + expect(sendMailMock).toHaveBeenCalledTimes(1) + }) + + describe('group member mutes group', () => { + it('sets the muted status correctly', async () => { + authenticatedUser = await groupMember.toJson() + await expect( + mutate({ + mutation: muteGroupMutation, + variables: { + id: 'g-1', + }, + }), + ).resolves.toMatchObject({ + data: { + muteGroup: { + isMutedByMe: true, + }, + }, + errors: undefined, + }) + }) + + it('sends NO notification when another post is posted', async () => { + authenticatedUser = await groupMember.toJson() + await markAllAsRead() + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'post-1', + title: 'This is another post in the group', + content: 'This is the content of another post in the group', + groupId: 'g-1', + }, + }) + authenticatedUser = await groupMember.toJson() + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toMatchObject({ + data: { + notifications: [], + }, + errors: undefined, + }) + }) + + describe('group member unmutes group again but disables email', () => { + beforeAll(async () => { + jest.clearAllMocks() + await groupMember.update({ emailNotificationsPostInGroup: false }) + }) + + it('sets the muted status correctly', async () => { + authenticatedUser = await groupMember.toJson() + await expect( + mutate({ + mutation: unmuteGroupMutation, + variables: { + id: 'g-1', + }, + }), + ).resolves.toMatchObject({ + data: { + unmuteGroup: { + isMutedByMe: false, + }, + }, + errors: undefined, + }) + }) + + it('sends notification when another post is posted', async () => { + authenticatedUser = await groupMember.toJson() + await markAllAsRead() + authenticatedUser = await postAuthor.toJson() + await mutate({ + mutation: createPostMutation, + variables: { + id: 'post-2', + title: 'This is yet another post in the group', + content: 'This is the content of yet another post in the group', + groupId: 'g-1', + }, + }) + authenticatedUser = await groupMember.toJson() + await expect( + query({ + query: notificationQuery, + variables: { + read: false, + }, + }), + ).resolves.toMatchObject({ + data: { + notifications: [ + { + from: { + __typename: 'Post', + id: 'post-2', + }, + read: false, + reason: 'post_in_group', + }, + ], + }, + errors: undefined, + }) + }) + + it('sends NO email', () => { + expect(sendMailMock).not.toHaveBeenCalled() + }) + }) + }) + }) +}) diff --git a/backend/src/middleware/permissionsMiddleware.ts b/backend/src/middleware/permissionsMiddleware.ts index fcda6d218..b8c728f4c 100644 --- a/backend/src/middleware/permissionsMiddleware.ts +++ b/backend/src/middleware/permissionsMiddleware.ts @@ -468,6 +468,8 @@ export default shield( CreateMessage: isAuthenticated, MarkMessagesAsSeen: isAuthenticated, toggleObservePost: isAuthenticated, + muteGroup: and(isAuthenticated, isMemberOfGroup), + unmuteGroup: and(isAuthenticated, isMemberOfGroup), }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/middleware/validation/validationMiddleware.ts b/backend/src/middleware/validation/validationMiddleware.ts index 0920df6e0..072f2d7b9 100644 --- a/backend/src/middleware/validation/validationMiddleware.ts +++ b/backend/src/middleware/validation/validationMiddleware.ts @@ -106,6 +106,7 @@ export const validateNotifyUsers = async (label, reason) => { 'mentioned_in_comment', 'commented_on_post', 'followed_user_posted', + 'post_in_group', ] if (!reasonsAllowed.includes(reason)) throw new Error('Notification reason is not allowed!') if ( diff --git a/backend/src/models/User.ts b/backend/src/models/User.ts index e0cc770b4..754f879a4 100644 --- a/backend/src/models/User.ts +++ b/backend/src/models/User.ts @@ -189,6 +189,10 @@ export default { type: 'boolean', default: true, }, + emailNotificationsPostInGroup: { + type: 'boolean', + default: true, + }, locale: { type: 'string', diff --git a/backend/src/schema/resolvers/groups.ts b/backend/src/schema/resolvers/groups.ts index 8b383e702..6a54ce17f 100644 --- a/backend/src/schema/resolvers/groups.ts +++ b/backend/src/schema/resolvers/groups.ts @@ -368,6 +368,64 @@ export default { session.close() } }, + muteGroup: async (_parent, params, context, _resolveInfo) => { + const { id: groupId } = params + const userId = context.user.id + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const transactionResponse = await transaction.run( + ` + MATCH (group:Group { id: $groupId }) + MATCH (user:User { id: $userId }) + MERGE (user)-[m:MUTED]->(group) + SET m.createdAt = toString(datetime()) + RETURN group { .* } + `, + { + groupId, + userId, + }, + ) + const [group] = await transactionResponse.records.map((record) => record.get('group')) + return group + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, + unmuteGroup: async (_parent, params, context, _resolveInfo) => { + const { id: groupId } = params + const userId = context.user.id + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const transactionResponse = await transaction.run( + ` + MATCH (group:Group { id: $groupId }) + MATCH (user:User { id: $userId }) + OPTIONAL MATCH (user)-[m:MUTED]->(group) + DELETE m + RETURN group { .* } + `, + { + groupId, + userId, + }, + ) + const [group] = await transactionResponse.records.map((record) => record.get('group')) + return group + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new Error(error) + } finally { + session.close() + } + }, }, Group: { ...Resolver('Group', { @@ -380,6 +438,10 @@ export default { avatar: '-[:AVATAR_IMAGE]->(related:Image)', location: '-[:IS_IN]->(related:Location)', }, + boolean: { + isMutedByMe: + 'MATCH (this)<-[:MUTED]-(related:User {id: $cypherParams.currentUserId}) RETURN COUNT(related) >= 1', + }, }), }, } diff --git a/backend/src/schema/resolvers/users.spec.ts b/backend/src/schema/resolvers/users.spec.ts index 77d606fbb..0b14575db 100644 --- a/backend/src/schema/resolvers/users.spec.ts +++ b/backend/src/schema/resolvers/users.spec.ts @@ -679,6 +679,10 @@ describe('emailNotificationSettings', () => { name: 'followingUsers', value: true, }, + { + name: 'postInGroup', + value: true, + }, ], }, { @@ -773,6 +777,10 @@ describe('emailNotificationSettings', () => { name: 'followingUsers', value: true, }, + { + name: 'postInGroup', + value: true, + }, ], }, { diff --git a/backend/src/schema/resolvers/users.ts b/backend/src/schema/resolvers/users.ts index 134fb34cb..e4e701006 100644 --- a/backend/src/schema/resolvers/users.ts +++ b/backend/src/schema/resolvers/users.ts @@ -387,6 +387,10 @@ export default { name: 'followingUsers', value: parent.emailNotificationsFollowingUsers ?? true, }, + { + name: 'postInGroup', + value: parent.emailNotificationsPostInGroup ?? true, + }, ], }, { diff --git a/backend/src/schema/types/enum/EmailNotificationSettingsName.gql b/backend/src/schema/types/enum/EmailNotificationSettingsName.gql index bcc6e617c..59989faca 100644 --- a/backend/src/schema/types/enum/EmailNotificationSettingsName.gql +++ b/backend/src/schema/types/enum/EmailNotificationSettingsName.gql @@ -2,6 +2,7 @@ enum EmailNotificationSettingsName { commentOnObservedPost mention followingUsers + postInGroup chatMessage groupMemberJoined groupMemberLeft diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index acf585f71..2e14c8c0a 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -41,6 +41,10 @@ type Group { myRole: GroupMemberRole # if 'null' then the current user is no member posts: [Post] @relation(name: "IN", direction: "IN") + + isMutedByMe: Boolean! + @cypher( + statement: "MATCH (this)<-[m:MUTED]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(m) >= 1") } @@ -137,4 +141,7 @@ type Mutation { groupId: ID! userId: ID! ): User + + muteGroup(id: ID!): Group + unmuteGroup(id: ID!): Group } diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index 2726f503a..d32b4e042 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -27,6 +27,7 @@ enum NotificationReason { changed_group_member_role removed_user_from_group followed_user_posted + post_in_group } type Query { diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 0a64283a5..dd2f36115 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -741,6 +741,7 @@ "followed_user_posted": "Hat einen neuen Betrag geschrieben …", "mentioned_in_comment": "Hat Dich in einem Kommentar erwähnt …", "mentioned_in_post": "Hat Dich in einem Beitrag erwähnt …", + "post_in_group": "Hat einen Beitrag in der Gruppe geschrieben …", "removed_user_from_group": "Hat Dich aus der Gruppe entfernt …", "user_joined_group": "Ist Deiner Gruppe beigetreten …", "user_left_group": "Hat deine Gruppe verlassen …" diff --git a/webapp/locales/en.json b/webapp/locales/en.json index f73e77804..7e5570b89 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -741,6 +741,7 @@ "followed_user_posted": "Wrote a new post …", "mentioned_in_comment": "Mentioned you in a comment …", "mentioned_in_post": "Mentioned you in a post …", + "post_in_group": "Posted in a group …", "removed_user_from_group": "Removed you from group …", "user_joined_group": "Joined your group …", "user_left_group": "Left your group …" diff --git a/webapp/locales/es.json b/webapp/locales/es.json index 8efa724e9..a3e5cfcc2 100644 --- a/webapp/locales/es.json +++ b/webapp/locales/es.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": "Le mencionó en un comentario …", "mentioned_in_post": "Le mencionó en una contribución …", + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/fr.json b/webapp/locales/fr.json index e00df6543..0153c20a1 100644 --- a/webapp/locales/fr.json +++ b/webapp/locales/fr.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": "Vous a mentionné dans un commentaire…", "mentioned_in_post": "Vous a mentionné dans un post…", + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/it.json b/webapp/locales/it.json index 52597f9fb..586f44839 100644 --- a/webapp/locales/it.json +++ b/webapp/locales/it.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/nl.json b/webapp/locales/nl.json index bbf99f186..2e183bdcc 100644 --- a/webapp/locales/nl.json +++ b/webapp/locales/nl.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/pl.json b/webapp/locales/pl.json index 78223f943..0624842fe 100644 --- a/webapp/locales/pl.json +++ b/webapp/locales/pl.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": null, "mentioned_in_post": null, + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 4848546a0..0ab934e23 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": "Mentionou você em um comentário …", "mentioned_in_post": "Mencinou você em um post …", + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json index ac33dff47..cf0d8ed62 100644 --- a/webapp/locales/ru.json +++ b/webapp/locales/ru.json @@ -741,6 +741,7 @@ "followed_user_posted": null, "mentioned_in_comment": "Упоминание в комментарии....", "mentioned_in_post": "Упоминание в посте....", + "post_in_group": null, "removed_user_from_group": null, "user_joined_group": null, "user_left_group": null From 7a44e1aa4e8e2026754a758276668f0f15cb2c97 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 11 Apr 2025 23:49:31 +0200 Subject: [PATCH 04/18] test that there is no email sent when no notification (#8362) --- backend/src/middleware/notifications/posts-in-groups.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/middleware/notifications/posts-in-groups.spec.ts b/backend/src/middleware/notifications/posts-in-groups.spec.ts index 86e700d1c..742685816 100644 --- a/backend/src/middleware/notifications/posts-in-groups.spec.ts +++ b/backend/src/middleware/notifications/posts-in-groups.spec.ts @@ -295,6 +295,7 @@ describe('notify group members of new posts in group', () => { }) it('sends NO notification when another post is posted', async () => { + jest.clearAllMocks() authenticatedUser = await groupMember.toJson() await markAllAsRead() authenticatedUser = await postAuthor.toJson() @@ -323,6 +324,10 @@ describe('notify group members of new posts in group', () => { }) }) + it('sends NO email', () => { + expect(sendMailMock).not.toHaveBeenCalled() + }) + describe('group member unmutes group again but disables email', () => { beforeAll(async () => { jest.clearAllMocks() From caeff070b7d3e2a00b29493251da82ba1559ab35 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 12 Apr 2025 01:10:42 +0200 Subject: [PATCH 05/18] feat(webapp): add mute/unumute group to menu (#8335) * basics to notify a user when a followed user posted * do not notify following user on posts in groups * followig user wrote post notification * notify regular group members when a new post is posted in the group * mute and unmute groups * clean database at end * locale for post in group notification * post in group notification triggers correctly * email settings for post in group * Add mute/unumute group to menu (WIP) * Add mute group functionality (WIP) * Add locales; use mute/unmute mutations, cleanup tests * Overhaul group content menu test * Rename isMuted to isMutedByMe and add it to group query * Add German and English locales * Add spanish translations * Add missing translation keys (with null values) * Remove console statement * Add snapshot * Replace mount by render * Mock Math.random(), add tests for mute/unmute * Use container instead of baseElement for snapshots * fix group slug tests * undo wrong variable naming * rename parameter to groupId of mute/unmute group mutation * rename parameter to groupId of mute/unmute group mutation * only non pending members have access to the comtext menu --------- Co-authored-by: Moriz Wahl Co-authored-by: Ulf Gebhardt --- .../notifications/posts-in-groups.spec.ts | 12 +- backend/src/schema/resolvers/groups.ts | 4 +- backend/src/schema/types/type/Group.gql | 4 +- .../ContentMenu/GroupContentMenu.spec.js | 75 +- .../ContentMenu/GroupContentMenu.vue | 21 + .../GroupContentMenu.spec.js.snap | 321 + webapp/graphql/groups.js | 1 + webapp/graphql/settings/MutedGroups.js | 25 + webapp/locales/de.json | 5 + webapp/locales/en.json | 5 + webapp/locales/es.json | 5 + webapp/locales/fr.json | 5 + webapp/locales/it.json | 5 + webapp/locales/nl.json | 5 + webapp/locales/pl.json | 5 + webapp/locales/pt.json | 5 + webapp/locales/ru.json | 5 + .../_id/__snapshots__/_slug.spec.js.snap | 7845 +++++++++++++++++ webapp/pages/groups/_id/_slug.spec.js | 1375 +-- webapp/pages/groups/_id/_slug.vue | 57 +- 20 files changed, 8519 insertions(+), 1266 deletions(-) create mode 100644 webapp/components/ContentMenu/__snapshots__/GroupContentMenu.spec.js.snap create mode 100644 webapp/graphql/settings/MutedGroups.js create mode 100644 webapp/pages/groups/_id/__snapshots__/_slug.spec.js.snap diff --git a/backend/src/middleware/notifications/posts-in-groups.spec.ts b/backend/src/middleware/notifications/posts-in-groups.spec.ts index 742685816..a46de2830 100644 --- a/backend/src/middleware/notifications/posts-in-groups.spec.ts +++ b/backend/src/middleware/notifications/posts-in-groups.spec.ts @@ -63,8 +63,8 @@ const notificationQuery = gql` ` const muteGroupMutation = gql` - mutation ($id: ID!) { - muteGroup(id: $id) { + mutation ($groupId: ID!) { + muteGroup(groupId: $groupId) { id isMutedByMe } @@ -72,8 +72,8 @@ const muteGroupMutation = gql` ` const unmuteGroupMutation = gql` - mutation ($id: ID!) { - unmuteGroup(id: $id) { + mutation ($groupId: ID!) { + unmuteGroup(groupId: $groupId) { id isMutedByMe } @@ -281,7 +281,7 @@ describe('notify group members of new posts in group', () => { mutate({ mutation: muteGroupMutation, variables: { - id: 'g-1', + groupId: 'g-1', }, }), ).resolves.toMatchObject({ @@ -340,7 +340,7 @@ describe('notify group members of new posts in group', () => { mutate({ mutation: unmuteGroupMutation, variables: { - id: 'g-1', + groupId: 'g-1', }, }), ).resolves.toMatchObject({ diff --git a/backend/src/schema/resolvers/groups.ts b/backend/src/schema/resolvers/groups.ts index 6a54ce17f..4bf535f35 100644 --- a/backend/src/schema/resolvers/groups.ts +++ b/backend/src/schema/resolvers/groups.ts @@ -369,7 +369,7 @@ export default { } }, muteGroup: async (_parent, params, context, _resolveInfo) => { - const { id: groupId } = params + const { groupId } = params const userId = context.user.id const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { @@ -398,7 +398,7 @@ export default { } }, unmuteGroup: async (_parent, params, context, _resolveInfo) => { - const { id: groupId } = params + const { groupId } = params const userId = context.user.id const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async (transaction) => { diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index 2e14c8c0a..0d399d287 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -142,6 +142,6 @@ type Mutation { userId: ID! ): User - muteGroup(id: ID!): Group - unmuteGroup(id: ID!): Group + muteGroup(groupId: ID!): Group + unmuteGroup(groupId: ID!): Group } diff --git a/webapp/components/ContentMenu/GroupContentMenu.spec.js b/webapp/components/ContentMenu/GroupContentMenu.spec.js index 49a66aaac..f7336589d 100644 --- a/webapp/components/ContentMenu/GroupContentMenu.spec.js +++ b/webapp/components/ContentMenu/GroupContentMenu.spec.js @@ -1,5 +1,5 @@ -import { mount } from '@vue/test-utils' import GroupContentMenu from './GroupContentMenu.vue' +import { render, screen, fireEvent } from '@testing-library/vue' const localVue = global.localVue @@ -7,36 +7,77 @@ const stubs = { 'router-link': { template: '', }, + 'v-popover': true, } -const propsData = { - usage: 'groupTeaser', - resource: {}, - group: {}, - resourceType: 'group', -} +// Mock Math.random, used in Dropdown +Object.assign(Math, { + random: () => 0, +}) describe('GroupContentMenu', () => { - let wrapper let mocks beforeEach(() => { mocks = { - $t: jest.fn(), + $t: jest.fn((s) => s), } }) - describe('mount', () => { - const Wrapper = () => { - return mount(GroupContentMenu, { propsData, mocks, localVue, stubs }) - } + const Wrapper = (propsData) => { + return render(GroupContentMenu, { propsData, mocks, localVue, stubs }) + } - beforeEach(() => { - wrapper = Wrapper() + it('renders as groupTeaser', () => { + const wrapper = Wrapper({ usage: 'groupTeaser', group: { id: 'groupid' } }) + expect(wrapper.container).toMatchSnapshot() + }) + + it('renders as groupProfile, not muted', () => { + const wrapper = Wrapper({ + usage: 'groupProfile', + group: { isMutedByMe: false, id: 'groupid' }, }) + expect(wrapper.container).toMatchSnapshot() + }) - it('renders', () => { - expect(wrapper.findAll('.group-content-menu')).toHaveLength(1) + it('renders as groupProfile, muted', () => { + const wrapper = Wrapper({ + usage: 'groupProfile', + group: { isMutedByMe: true, id: 'groupid' }, + }) + expect(wrapper.container).toMatchSnapshot() + }) + + it('renders as groupProfile when I am the owner', () => { + const wrapper = Wrapper({ + usage: 'groupProfile', + group: { myRole: 'owner', id: 'groupid' }, + }) + expect(wrapper.container).toMatchSnapshot() + }) + + describe('mute button', () => { + it('emits mute', async () => { + const wrapper = Wrapper({ + usage: 'groupProfile', + group: { isMutedByMe: false, id: 'groupid' }, + }) + const muteButton = screen.getByText('group.contentMenu.muteGroup') + await fireEvent.click(muteButton) + expect(wrapper.emitted().mute).toBeTruthy() + }) + }) + + describe('unmute button', () => { + it('emits unmute', async () => { + const wrapper = Wrapper({ + usage: 'groupProfile', + group: { isMutedByMe: true, id: 'groupid' }, + }) + const muteButton = screen.getByText('group.contentMenu.unmuteGroup') + await fireEvent.click(muteButton) + expect(wrapper.emitted().unmute).toBeTruthy() }) }) }) diff --git a/webapp/components/ContentMenu/GroupContentMenu.vue b/webapp/components/ContentMenu/GroupContentMenu.vue index 1ca1b5b33..e28a855ac 100644 --- a/webapp/components/ContentMenu/GroupContentMenu.vue +++ b/webapp/components/ContentMenu/GroupContentMenu.vue @@ -62,6 +62,27 @@ export default { params: { id: this.group.id, slug: this.group.slug }, }) } + + if (this.usage === 'groupProfile') { + if (this.group.isMutedByMe) { + routes.push({ + label: this.$t('group.contentMenu.unmuteGroup'), + icon: 'volume-up', + callback: () => { + this.$emit('unmute', this.group.id) + }, + }) + } else { + routes.push({ + label: this.$t('group.contentMenu.muteGroup'), + icon: 'volume-off', + callback: () => { + this.$emit('mute', this.group.id) + }, + }) + } + } + if (this.group.myRole === 'owner') { routes.push({ label: this.$t('admin.settings.name'), diff --git a/webapp/components/ContentMenu/__snapshots__/GroupContentMenu.spec.js.snap b/webapp/components/ContentMenu/__snapshots__/GroupContentMenu.spec.js.snap new file mode 100644 index 000000000..0553dfa79 --- /dev/null +++ b/webapp/components/ContentMenu/__snapshots__/GroupContentMenu.spec.js.snap @@ -0,0 +1,321 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GroupContentMenu renders as groupProfile when I am the owner 1`] = ` +
+ + + + + +
+`; + +exports[`GroupContentMenu renders as groupProfile, muted 1`] = ` +
+ + + + + +
+`; + +exports[`GroupContentMenu renders as groupProfile, not muted 1`] = ` +
+ + + + + +
+`; + +exports[`GroupContentMenu renders as groupTeaser 1`] = ` +
+ + + + + +
+`; diff --git a/webapp/graphql/groups.js b/webapp/graphql/groups.js index 6aedc205d..bd17b0484 100644 --- a/webapp/graphql/groups.js +++ b/webapp/graphql/groups.js @@ -177,6 +177,7 @@ export const groupQuery = (i18n) => { descriptionExcerpt groupType actionRadius + isMutedByMe categories { id slug diff --git a/webapp/graphql/settings/MutedGroups.js b/webapp/graphql/settings/MutedGroups.js new file mode 100644 index 000000000..847fac4c4 --- /dev/null +++ b/webapp/graphql/settings/MutedGroups.js @@ -0,0 +1,25 @@ +import gql from 'graphql-tag' + +export const muteGroup = () => { + return gql` + mutation ($groupId: ID!) { + muteGroup(groupId: $groupId) { + id + name + isMutedByMe + } + } + ` +} + +export const unmuteGroup = () => { + return gql` + mutation ($groupId: ID!) { + unmuteGroup(groupId: $groupId) { + id + name + isMutedByMe + } + } + ` +} diff --git a/webapp/locales/de.json b/webapp/locales/de.json index dd2f36115..fb8866005 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -485,6 +485,8 @@ "categoriesTitle": "Themen der Gruppe", "changeMemberRole": "Die Rolle wurde auf „{role}“ geändert!", "contentMenu": { + "muteGroup": "Gruppe stummschalten", + "unmuteGroup": "Gruppe nicht mehr stummschalten", "visitGroupPage": "Gruppe anzeigen" }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": "Nutzer „{name}“ zur Gruppe hinzufügen?", "confirmAddGroupMemberTitle": "Bestätigen" }, + "muted": "Gruppe stummgeschaltet", "myGroups": "Meine Gruppen", "name": "Gruppenname", "radius": "Radius", @@ -559,6 +562,8 @@ "hidden": "Geheim — Gruppe (auch der Name) komplett unsichtbar", "public": "Öffentlich — Gruppe und alle Beiträge für registrierte Nutzer sichtbar" }, + "unmute": "Gruppe nicht mehr stummschalten", + "unmuted": "Gruppe nicht mehr stummgeschaltet", "update": "Änderung speichern", "updatedGroup": "Die Gruppendaten wurden geändert!" }, diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 7e5570b89..b4c1125f3 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -485,6 +485,8 @@ "categoriesTitle": "Topics of the group", "changeMemberRole": "The role has been changed to “{role}”!", "contentMenu": { + "muteGroup": "Mute group", + "unmuteGroup": "Unmute group", "visitGroupPage": "Show group" }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": "Add user “{name}” to group?", "confirmAddGroupMemberTitle": "Confirm" }, + "muted": "Group muted", "myGroups": "My Groups", "name": "Group name", "radius": "Radius", @@ -559,6 +562,8 @@ "hidden": "Secret — Group (including the name) is completely invisible", "public": "Public — Group and all posts are visible for all registered users" }, + "unmute": "Unmute group", + "unmuted": "Group unmuted", "update": "Save change", "updatedGroup": "The group data has been changed." }, diff --git a/webapp/locales/es.json b/webapp/locales/es.json index a3e5cfcc2..7184a327a 100644 --- a/webapp/locales/es.json +++ b/webapp/locales/es.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": "Silenciar grupo", + "unmuteGroup": "Desactivar silencio del grupo", "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": "Grupo silenciado", "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": "Desactivar silencio", + "unmuted": "Silencio del grupo desactivado", "update": null, "updatedGroup": null }, diff --git a/webapp/locales/fr.json b/webapp/locales/fr.json index 0153c20a1..851743e63 100644 --- a/webapp/locales/fr.json +++ b/webapp/locales/fr.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/locales/it.json b/webapp/locales/it.json index 586f44839..0c693ca43 100644 --- a/webapp/locales/it.json +++ b/webapp/locales/it.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/locales/nl.json b/webapp/locales/nl.json index 2e183bdcc..433adf8e8 100644 --- a/webapp/locales/nl.json +++ b/webapp/locales/nl.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/locales/pl.json b/webapp/locales/pl.json index 0624842fe..c0ab9d09c 100644 --- a/webapp/locales/pl.json +++ b/webapp/locales/pl.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 0ab934e23..02f8fb2cc 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json index cf0d8ed62..ea0279450 100644 --- a/webapp/locales/ru.json +++ b/webapp/locales/ru.json @@ -485,6 +485,8 @@ "categoriesTitle": null, "changeMemberRole": null, "contentMenu": { + "muteGroup": null, + "unmuteGroup": null, "visitGroupPage": null }, "createNewGroup": { @@ -535,6 +537,7 @@ "confirmAddGroupMemberText": null, "confirmAddGroupMemberTitle": null }, + "muted": null, "myGroups": null, "name": null, "radius": null, @@ -559,6 +562,8 @@ "hidden": null, "public": null }, + "unmute": null, + "unmuted": null, "update": null, "updatedGroup": null }, diff --git a/webapp/pages/groups/_id/__snapshots__/_slug.spec.js.snap b/webapp/pages/groups/_id/__snapshots__/_slug.spec.js.snap new file mode 100644 index 000000000..cb43b8526 --- /dev/null +++ b/webapp/pages/groups/_id/__snapshots__/_slug.spec.js.snap @@ -0,0 +1,7845 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a closed group – "school-for-citizens" given a current user as group owner – "peter-lustig" renders 1`] = ` +
+
+
+ +
+
+
+
+
+
+
+
+ + SFC + + + + + +
+ +
+
+ +
+
+
+
+
+
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + School For Citizens + +

+ +

+ + &school-for-citizens + +

+ +

+ + + + + Paris + +

+ +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.owner + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.closed + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.national + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.children + + + +
+
+
+ + + + + + contribution.category.name.science + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Our children shall receive education for life. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ + English + +

+

+ Our goal +

+

+ Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives. +

+

+ Curiosity +

+

+ For this we need a school that takes up the curiosity of the children, … +

+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a closed group – "school-for-citizens" given a current user as none(!) member – "huey" renders 1`] = ` +
+
+
+ +
+
+
+
+ + SFC + + + + + +
+ + + + + +
+

+ + School For Citizens + +

+ +

+ + &school-for-citizens + +

+ +

+ + + + + Paris + +

+ +

+ + group.foundation + +

+
+ + + +
+ + + +
+ +
+ +
+ + +

+ + group.type + +

+ +
+ + + group.types.closed + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.national + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.children + + + +
+
+
+ + + + + + contribution.category.name.science + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Our children shall receive education for life. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+

+ group.membersListTitleNotAllowedSeeingGroupMembers +

+ + +
+
+ +
+
+
+
+

+ + English + +

+

+ Our goal +

+

+ Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives. +

+

+ Curiosity +

+

+ For this we need a school that takes up the curiosity of the children, … +

+
+ + + + +
+
+ + + +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a closed group – "school-for-citizens" given a current user as pending member – "bob-der-baumeister" renders 1`] = ` +
+
+
+ +
+
+
+
+ + SFC + + + + + +
+ + + + + +
+

+ + School For Citizens + +

+ +

+ + &school-for-citizens + +

+ +

+ + + + + Paris + +

+ +

+ + group.foundation + +

+
+ + + +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.pending + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.closed + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.national + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.children + + + +
+
+
+ + + + + + contribution.category.name.science + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Our children shall receive education for life. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+

+ group.membersListTitleNotAllowedSeeingGroupMembers +

+ + +
+
+ +
+
+
+
+

+ + English + +

+

+ Our goal +

+

+ Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives. +

+

+ Curiosity +

+

+ For this we need a school that takes up the curiosity of the children, … +

+
+ + + + +
+
+ + + +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a closed group – "school-for-citizens" given a current user as usual member – "jenny-rostock" renders 1`] = ` +
+
+
+ +
+
+
+
+ + SFC + + + + + +
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + School For Citizens + +

+ +

+ + &school-for-citizens + +

+ +

+ + + + + Paris + +

+ +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.usual + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.closed + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.national + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.children + + + +
+
+
+ + + + + + contribution.category.name.science + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Our children shall receive education for life. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ + English + +

+

+ Our goal +

+

+ Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives. +

+

+ Curiosity +

+

+ For this we need a school that takes up the curiosity of the children, … +

+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a current user as group owner – "peter-lustig" renders 1`] = ` +
+
+
+ +
+
+
+
+
+
+
+
+ + YP + + + + + +
+ +
+
+ +
+
+
+
+
+
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + Yoga Practice + +

+ +

+ + &yoga-practice + +

+ + + +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.owner + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.public + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.interplanetary + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.body-and-excercise + + + +
+
+
+ + + + + + contribution.category.name.psyche + + + +
+
+
+ + + + + + contribution.category.name.spirituality + + + + +
+
+
+ + + + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ What Is yoga? +

+

+ Yoga is not just about practicing asanas. It's about how we do it. +

+

+ And practicing asanas doesn't have to be yoga, it can be more athletic than yogic. +

+

+ What makes practicing asanas yogic? +

+

+ The important thing is: +

+
    +
  • +

    + Use the exercises … +

    +
  • +
+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a current user as none(!) member – "huey" renders 1`] = ` +
+
+
+ +
+
+
+
+ + YP + + + + + +
+ + + + + +
+

+ + Yoga Practice + +

+ +

+ + &yoga-practice + +

+ + + +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+ + +

+ + group.type + +

+ +
+ + + group.types.public + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.interplanetary + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.body-and-excercise + + + +
+
+
+ + + + + + contribution.category.name.psyche + + + +
+
+
+ + + + + + contribution.category.name.spirituality + + + + +
+
+
+ + + + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ What Is yoga? +

+

+ Yoga is not just about practicing asanas. It's about how we do it. +

+

+ And practicing asanas doesn't have to be yoga, it can be more athletic than yogic. +

+

+ What makes practicing asanas yogic? +

+

+ The important thing is: +

+
    +
  • +

    + Use the exercises … +

    +
  • +
+
+ + + + +
+
+ + + +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a current user as pending member – "bob-der-baumeister" renders 1`] = ` +
+
+
+ +
+
+
+
+ + YP + + + + + +
+ + + + + +
+

+ + Yoga Practice + +

+ +

+ + &yoga-practice + +

+ + + +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.pending + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.public + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.interplanetary + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.body-and-excercise + + + +
+
+
+ + + + + + contribution.category.name.psyche + + + +
+
+
+ + + + + + contribution.category.name.spirituality + + + + +
+
+
+ + + + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ What Is yoga? +

+

+ Yoga is not just about practicing asanas. It's about how we do it. +

+

+ And practicing asanas doesn't have to be yoga, it can be more athletic than yogic. +

+

+ What makes practicing asanas yogic? +

+

+ The important thing is: +

+
    +
  • +

    + Use the exercises … +

    +
  • +
+
+ + + + +
+
+ + + +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a current user as usual member – "jenny-rostock" renders 1`] = ` +
+
+
+ +
+
+
+
+ + YP + + + + + +
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + Yoga Practice + +

+ +

+ + &yoga-practice + +

+ + + +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.usual + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.public + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.interplanetary + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.body-and-excercise + + + +
+
+
+ + + + + + contribution.category.name.psyche + + + +
+
+
+ + + + + + contribution.category.name.spirituality + + + + +
+
+
+ + + + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ What Is yoga? +

+

+ Yoga is not just about practicing asanas. It's about how we do it. +

+

+ And practicing asanas doesn't have to be yoga, it can be more athletic than yogic. +

+

+ What makes practicing asanas yogic? +

+

+ The important thing is: +

+
    +
  • +

    + Use the exercises … +

    +
  • +
+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidden group – "investigative-journalism" given a current user as group owner – "peter-lustig" renders 1`] = ` +
+
+
+ +
+
+
+
+
+
+
+
+ + IJ + + + + + +
+ +
+
+ +
+
+
+
+
+
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + Investigative Journalism + +

+ +

+ + &investigative-journalism + +

+ +

+ + + + + Hamburg + +

+ +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.owner + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.hidden + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.global + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.it-and-media + + + +
+
+
+ + + + + + contribution.category.name.law + + + +
+
+
+ + + + + + contribution.category.name.politics + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Investigative journalists share ideas and insights and can collaborate. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ + English: + +

+

+ This group is hidden. +

+

+ What is our group for? +

+

+ This group was created to allow investigative journalists to share and collaborate. +

+

+ How does it work? +

+

+ Here you can internally share posts and comments about them. +

+

+
+

+

+ + Deutsch: + +

+

+ Diese Gruppe ist verborgen. +

+

+ … +

+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidden group – "investigative-journalism" given a current user as none(!) member – "huey" renders 1`] = ` +
+ +
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidden group – "investigative-journalism" given a current user as pending member – "bob-der-baumeister" renders 1`] = ` +
+ +
+`; + +exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidden group – "investigative-journalism" given a current user as usual member – "jenny-rostock" renders 1`] = ` +
+
+
+ +
+
+
+
+ + IJ + + + + + +
+ + + + + +
+
+ +
+
+
+
+ +
+

+ + Investigative Journalism + +

+ +

+ + &investigative-journalism + +

+ +

+ + + + + Hamburg + +

+ +

+ + group.foundation + +

+
+ +
+
+ +
+

+ + + + + 0 + + + + +

+

+ + group.membersCount + +

+
+
+
+
+ +
+ + + +
+ +
+ +
+

+ + group.role + +

+ +
+ + + group.roles.usual + + + +
+ +

+ + group.type + +

+ +
+ + + group.types.hidden + + + +
+ +

+ + group.actionRadius + +

+ +
+ + + group.actionRadii.global + + + +
+ +
+
+ +
+ +
+

+ + group.categories + +

+ +
+ +
+
+ + + + + + contribution.category.name.it-and-media + + + +
+
+
+ + + + + + contribution.category.name.law + + + +
+
+
+ + + + + + contribution.category.name.politics + + + + +
+
+
+ +
+ +
+

+ + group.goal + +

+ +
+ +
+ + Investigative journalists share ideas and insights and can collaborate. + + +
+
+ + +
+ +
+ +

+ + profile.network.title + +

+ +
+
+ + group.membersListTitle + +
+ +
    +
  • +
    +
    + +
    + + PL + + + + + +
    +
    + +
    +
    + + + + @peter-lustig + + + + Peter Lustig + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + JR + + + + + +
    +
    + +
    +
    + + + + @jenny-rostock + + + + Jenny Rostock + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + BDB + + + + + +
    +
    + +
    +
    + + + + @bob-der-baumeister + + + + Bob der Baumeister + + + + + + + +
    + + +
    +
    +
    +
  • +
  • +
    +
    + +
    + + H + + + + + +
    +
    + +
    +
    + + + + @huey + + + + Huey + + + + + + + +
    + + +
    +
    +
    +
  • +
+ + + + + + +
+
+ +
+
+
+
+

+ + English: + +

+

+ This group is hidden. +

+

+ What is our group for? +

+

+ This group was created to allow investigative journalists to share and collaborate. +

+

+ How does it work? +

+

+ Here you can internally share posts and comments about them. +

+

+
+

+

+ + Deutsch: + +

+

+ Diese Gruppe ist verborgen. +

+

+ … +

+
+ + + + +
+
+ +
+ + + +
+ +
+
+
+

+ Empty + +
+ + +

+
+
+
+ + +
+ + + + + + + +
+
+
+
+
+
+`; diff --git a/webapp/pages/groups/_id/_slug.spec.js b/webapp/pages/groups/_id/_slug.spec.js index bb9279bce..2fb9fc37c 100644 --- a/webapp/pages/groups/_id/_slug.spec.js +++ b/webapp/pages/groups/_id/_slug.spec.js @@ -1,5 +1,5 @@ -import { mount } from '@vue/test-utils' import GroupProfileSlug from './_slug.vue' +import { render, screen, fireEvent } from '@testing-library/vue' const localVue = global.localVue @@ -10,13 +10,19 @@ const stubs = { 'v-popover': true, 'nuxt-link': true, 'router-link': true, - 'infinite-loading': true, + // 'infinite-loading': true, 'follow-list': true, } +// Mock Math.random, used in Dropdown +Object.assign(Math, { + random: () => 0, +}) + +jest.mock('vue-infinite-loading', () => ({})) + describe('GroupProfileSlug', () => { let wrapper - let Wrapper let mocks let yogaPractice let schoolForCitizens @@ -95,6 +101,7 @@ describe('GroupProfileSlug', () => { ], locationName: null, location: null, + isMutedByMe: false, // myRole: 'usual', } schoolForCitizens = { @@ -128,6 +135,7 @@ describe('GroupProfileSlug', () => { nameDE: 'Paris', nameEN: 'Paris', }, + isMutedByMe: true, // myRole: 'usual', } investigativeJournalism = { @@ -170,6 +178,7 @@ describe('GroupProfileSlug', () => { nameDE: 'Hamburg', nameEN: 'Hamburg', }, + isMutedByMe: false, // myRole: 'usual', } peterLustig = { @@ -198,508 +207,137 @@ describe('GroupProfileSlug', () => { } }) - describe('mount', () => { - Wrapper = (data = () => {}) => { - return mount(GroupProfileSlug, { - mocks, - localVue, - data, - stubs, + const Wrapper = (data = () => {}) => { + return render(GroupProfileSlug, { + mocks, + localVue, + data, + stubs, + }) + } + + describe('given a puplic group – "yoga-practice"', () => { + describe('given a current user', () => { + describe('as group owner – "peter-lustig"', () => { + beforeEach(() => { + mocks.$store = { + getters: { + 'auth/user': peterLustig, + 'auth/isModerator': () => false, + }, + } + wrapper = Wrapper(() => { + return { + Group: [ + { + ...yogaPractice, + myRole: 'owner', + }, + ], + GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], + } + }) + }) + + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() + }) + + describe('after "show more" click displays full description', () => { + beforeEach(async () => { + const button = screen.getByText('comment.show.more') + await fireEvent.click(button) + // await wrapper.container.vm.$nextTick() + }) + + it('has full description', () => { + // test if end of full description is visible + expect( + screen.queryByText('Use the exercises (consciously) for your personal development.'), + ).not.toBeNull() + }) + + it('has "show less" button', () => { + expect(screen.queryByText('comment.show.less')).not.toBeNull() + }) + }) }) - } - describe('given a puplic group – "yoga-practice"', () => { - describe('given a current user', () => { - describe('as group owner – "peter-lustig"', () => { - beforeEach(() => { - mocks.$store = { - getters: { - 'auth/user': peterLustig, - 'auth/isModerator': () => false, - }, + describe('as usual member – "jenny-rostock"', () => { + beforeEach(() => { + mocks.$store = { + getters: { + 'auth/user': jennyRostock, + 'auth/isModerator': () => false, + }, + } + wrapper = Wrapper(() => { + return { + Group: [ + { + ...yogaPractice, + myRole: 'usual', + }, + ], + GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], } - wrapper = Wrapper(() => { - return { - Group: [ - { - ...yogaPractice, - myRole: 'owner', - }, - ], - GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], - } - }) - }) - - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Yoga Practice') - }) - - it('has AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(true) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(true) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&yoga-practice') - }) - - describe('displays no(!) group location – because is "null"', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button disabled(!)', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBe('disabled') - }) - - it('has group role "owner"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.owner') - }) - - it('has group type "public"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.public') - }) - - it('has group action radius "interplanetary"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.interplanetary') - }) - - it('has group categories "psyche", "body-and-excercise", "spirituality"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.psyche') - expect(wrapper.text()).toContain('contribution.category.name.body-and-excercise') - expect(wrapper.text()).toContain('contribution.category.name.spirituality') - }) - - it('has no(!) group goal – because is "null"', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - describe('displays description – here as well the functionallity', () => { - let groupDescriptionBaseCard - - beforeEach(async () => { - groupDescriptionBaseCard = wrapper.find('.group-description') - }) - - it('has description BaseCard', () => { - expect(groupDescriptionBaseCard.exists()).toBe(true) - }) - - describe('displays descriptionExcerpt first', () => { - it('has descriptionExcerpt', () => { - expect(groupDescriptionBaseCard.text()).toContain( - `What Is yoga?Yoga is not just about practicing asanas. It's about how we do it.And practicing asanas doesn't have to be yoga, it can be more athletic than yogic.What makes practicing asanas yogic?The important thing is:Use the exercises …`, - ) - }) - - it('has "show more" button', () => { - expect(wrapper.vm.isDescriptionCollapsed).toBe(true) - expect(groupDescriptionBaseCard.text()).toContain('comment.show.more') - }) - }) - - describe('after "show more" click displays full description', () => { - beforeEach(async () => { - await groupDescriptionBaseCard.find('.collaps-button').trigger('click') - await wrapper.vm.$nextTick() - }) - - it('has full description', () => { - // test if end of full description is visible - expect(groupDescriptionBaseCard.text()).toContain( - `Use the exercises (consciously) for your personal development.`, - ) - }) - - it('has "show less" button', () => { - expect(wrapper.vm.isDescriptionCollapsed).toBe(false) - expect(groupDescriptionBaseCard.text()).toContain('comment.show.less') - }) - }) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) }) }) - describe('as usual member – "jenny-rostock"', () => { - beforeEach(() => { - mocks.$store = { - getters: { - 'auth/user': jennyRostock, - 'auth/isModerator': () => false, - }, + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() + }) + }) + + describe('as pending member – "bob-der-baumeister"', () => { + beforeEach(() => { + mocks.$store = { + getters: { + 'auth/user': bobDerBaumeister, + 'auth/isModerator': () => false, + }, + } + wrapper = Wrapper(() => { + return { + Group: [ + { + ...yogaPractice, + myRole: 'pending', + }, + ], + GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], } - wrapper = Wrapper(() => { - return { - Group: [ - { - ...yogaPractice, - myRole: 'usual', - }, - ], - GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], - } - }) - }) - - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Yoga Practice') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&yoga-practice') - }) - - describe('displays no(!) group location – because is "null"', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has group role "usual"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.usual') - }) - - it('has group type "public"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.public') - }) - - it('has group action radius "interplanetary"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.interplanetary') - }) - - it('has group categories "psyche", "body-and-excercise", "spirituality"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.psyche') - expect(wrapper.text()).toContain('contribution.category.name.body-and-excercise') - expect(wrapper.text()).toContain('contribution.category.name.spirituality') - }) - - it('has no(!) group goal – because is "null"', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) }) }) - describe('as pending member – "bob-der-baumeister"', () => { - beforeEach(() => { - mocks.$store = { - getters: { - 'auth/user': bobDerBaumeister, - 'auth/isModerator': () => false, - }, + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() + }) + }) + + describe('as none(!) member – "huey"', () => { + beforeEach(() => { + mocks.$store = { + getters: { + 'auth/user': huey, + 'auth/isModerator': () => false, + }, + } + wrapper = Wrapper(() => { + return { + Group: [ + { + ...yogaPractice, + myRole: null, + }, + ], + GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], } - wrapper = Wrapper(() => { - return { - Group: [ - { - ...yogaPractice, - myRole: 'pending', - }, - ], - GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], - } - }) - }) - - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Yoga Practice') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&yoga-practice') - }) - - describe('displays no(!) group location – because is "null"', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has group role "pending"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.pending') - }) - - it('has group type "public"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.public') - }) - - it('has group action radius "interplanetary"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.interplanetary') - }) - - it('has group categories "psyche", "body-and-excercise", "spirituality"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.psyche') - expect(wrapper.text()).toContain('contribution.category.name.body-and-excercise') - expect(wrapper.text()).toContain('contribution.category.name.spirituality') - }) - - it('has no(!) group goal – because is "null"', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) }) }) - describe('as none(!) member – "huey"', () => { - beforeEach(() => { - mocks.$store = { - getters: { - 'auth/user': huey, - 'auth/isModerator': () => false, - }, - } - wrapper = Wrapper(() => { - return { - Group: [ - { - ...yogaPractice, - myRole: null, - }, - ], - GroupMembers: [peterLustig, jennyRostock, bobDerBaumeister, huey], - } - }) - }) - - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Yoga Practice') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&yoga-practice') - }) - - describe('displays no(!) group location – because is "null"', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has no(!) group role', () => { - expect(wrapper.text()).not.toContain('group.role') - expect(wrapper.text()).not.toContain('group.roles') - }) - - it('has group type "public"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.public') - }) - - it('has group action radius "interplanetary"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.interplanetary') - }) - - it('has group categories "psyche", "body-and-excercise", "spirituality"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.psyche') - expect(wrapper.text()).toContain('contribution.category.name.body-and-excercise') - expect(wrapper.text()).toContain('contribution.category.name.spirituality') - }) - - it('has no(!) group goal – because is "null"', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) - }) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) }) @@ -727,99 +365,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('School For Citizens') - }) - - it('has AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(true) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(true) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&school-for-citizens') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) - }) - - it('has group location name "Paris"', () => { - expect(wrapper.text()).toContain('Paris') - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button disabled(!)', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBe('disabled') - }) - - it('has group role "owner"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.owner') - }) - - it('has group type "closed"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.closed') - }) - - it('has group action radius "national"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.national') - }) - - it('has group categories "children", "science"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.children') - expect(wrapper.text()).toContain('contribution.category.name.science') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain('Our children shall receive education for life.') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) @@ -844,99 +391,31 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('School For Citizens') + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&school-for-citizens') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) + describe('clicking unmute button with valid server answer', () => { + beforeEach(async () => { + const button = screen.getByText('group.unmute') + await fireEvent.click(button) }) - it('has group location name "Paris"', () => { - expect(wrapper.text()).toContain('Paris') + it('shows a success message', () => { + expect(mocks.$toast.success).toHaveBeenCalledWith('group.unmuted') }) }) - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) + describe('clicking unmute button with server error', () => { + beforeEach(async () => { + mocks.$apollo.mutate = jest.fn().mockRejectedValue({ message: 'Ouch!' }) + const button = screen.getByText('group.unmute') + await fireEvent.click(button) + }) - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has group role "usual"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.usual') - }) - - it('has group type "closed"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.closed') - }) - - it('has group action radius "national"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.national') - }) - - it('has group categories "children", "science"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.children') - expect(wrapper.text()).toContain('contribution.category.name.science') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain('Our children shall receive education for life.') - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('shows error message', async () => { + expect(mocks.$toast.error).toHaveBeenCalledWith('Ouch!') + }) }) }) @@ -961,99 +440,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('School For Citizens') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&school-for-citizens') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) - }) - - it('has group location name "Paris"', () => { - expect(wrapper.text()).toContain('Paris') - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has no(!) members count', () => { - expect(wrapper.text()).not.toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has group role "pending"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.pending') - }) - - it('has group type "closed"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.closed') - }) - - it('has group action radius "national"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.national') - }) - - it('has group categories "children", "science"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.children') - expect(wrapper.text()).toContain('contribution.category.name.science') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain('Our children shall receive education for life.') - }) - - it('has ProfileList without(!) members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - // expect(profileList.text()).not.toContain('group.membersListTitle') // does not work, because is part of 'group.membersListTitleNotAllowedSeeingGroupMembers' - expect(profileList.text()).toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).not.toContain('Peter Lustig') - expect(profileList.text()).not.toContain('Jenny Rostock') - expect(profileList.text()).not.toContain('Bob der Baumeister') - expect(profileList.text()).not.toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) @@ -1078,99 +466,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('School For Citizens') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&school-for-citizens') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) - }) - - it('has group location name "Paris"', () => { - expect(wrapper.text()).toContain('Paris') - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has no(!) members count', () => { - expect(wrapper.text()).not.toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has no(!) group role', () => { - expect(wrapper.text()).not.toContain('group.role') - expect(wrapper.text()).not.toContain('group.roles') - }) - - it('has group type "closed"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.closed') - }) - - it('has group action radius "national"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.national') - }) - - it('has group categories "children", "science"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.children') - expect(wrapper.text()).toContain('contribution.category.name.science') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain('Our children shall receive education for life.') - }) - - it('has ProfileList without(!) members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - // expect(profileList.text()).not.toContain('group.membersListTitle') // does not work, because is part of 'group.membersListTitleNotAllowedSeeingGroupMembers' - expect(profileList.text()).toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).not.toContain('Peter Lustig') - expect(profileList.text()).not.toContain('Jenny Rostock') - expect(profileList.text()).not.toContain('Bob der Baumeister') - expect(profileList.text()).not.toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) }) @@ -1199,102 +496,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Investigative Journalism') - }) - - it('has AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(true) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(true) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&investigative-journalism') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) - }) - - it('has group location name "Hamburg"', () => { - expect(wrapper.text()).toContain('Hamburg') - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button disabled(!)', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBe('disabled') - }) - - it('has group role "owner"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.owner') - }) - - it('has group type "hidden"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.hidden') - }) - - it('has group action radius "global"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.global') - }) - - it('has group categories "law", "politics", "it-and-media"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.law') - expect(wrapper.text()).toContain('contribution.category.name.politics') - expect(wrapper.text()).toContain('contribution.category.name.it-and-media') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain( - 'Investigative journalists share ideas and insights and can collaborate.', - ) - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) @@ -1319,102 +522,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has group name – to verificate the group', () => { - expect(wrapper.text()).toContain('Investigative Journalism') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(true) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(true) - expect(wrapper.text()).toContain('&investigative-journalism') - }) - - describe('displays group location', () => { - it('has group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(true) - }) - - it('has group location name "Hamburg"', () => { - expect(wrapper.text()).toContain('Hamburg') - }) - }) - - it('has group foundation', () => { - expect(wrapper.text()).toContain('group.foundation') - }) - - it('has members count', () => { - expect(wrapper.text()).toContain('group.membersCount') - }) - - it('has join/leave button enabled', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(true) - expect(wrapper.find('.join-leave-button').attributes('disabled')).toBeFalsy() - }) - - it('has group role "usual"', () => { - expect(wrapper.text()).toContain('group.role') - expect(wrapper.text()).toContain('group.roles.usual') - }) - - it('has group type "hidden"', () => { - expect(wrapper.text()).toContain('group.type') - expect(wrapper.text()).toContain('group.types.hidden') - }) - - it('has group action radius "global"', () => { - expect(wrapper.text()).toContain('group.actionRadius') - expect(wrapper.text()).toContain('group.actionRadii.global') - }) - - it('has group categories "law", "politics", "it-and-media"', () => { - expect(wrapper.text()).toContain('group.categories') - expect(wrapper.text()).toContain('contribution.category.name.law') - expect(wrapper.text()).toContain('contribution.category.name.politics') - expect(wrapper.text()).toContain('contribution.category.name.it-and-media') - }) - - it('has group goal', () => { - expect(wrapper.text()).toContain('group.goal') - expect(wrapper.text()).toContain( - 'Investigative journalists share ideas and insights and can collaborate.', - ) - }) - - it('has ProfileList with members', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(true) - expect(profileList.text()).toContain('group.membersListTitle') - expect(profileList.text()).not.toContain( - 'group.membersListTitleNotAllowedSeeingGroupMembers', - ) - expect(profileList.text()).toContain('Peter Lustig') - expect(profileList.text()).toContain('Jenny Rostock') - expect(profileList.text()).toContain('Bob der Baumeister') - expect(profileList.text()).toContain('Huey') - }) - - it('has description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(true) - }) - - it('has profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(true) - }) - - it('has empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(true) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) @@ -1439,90 +548,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has no(!) group name – to verificate the group', () => { - expect(wrapper.text()).not.toContain('Investigative Journalism') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has not(!) ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(false) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has no(!) group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(false) - expect(wrapper.text()).not.toContain('&investigative-journalism') - }) - - describe('displays not(!) group location', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - - it('has no(!) group location name "Hamburg"', () => { - expect(wrapper.text()).not.toContain('Hamburg') - }) - }) - - it('has no(!) group foundation', () => { - expect(wrapper.text()).not.toContain('group.foundation') - }) - - it('has no(!) members count', () => { - expect(wrapper.text()).not.toContain('group.membersCount') - }) - - it('has no(!) join/leave button', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(false) - }) - - it('has no(!) group role', () => { - expect(wrapper.text()).not.toContain('group.role') - expect(wrapper.text()).not.toContain('group.roles') - }) - - it('has no(!) group type', () => { - expect(wrapper.text()).not.toContain('group.type') - expect(wrapper.text()).not.toContain('group.types') - }) - - it('has no(!) group action radius', () => { - expect(wrapper.text()).not.toContain('group.actionRadius') - expect(wrapper.text()).not.toContain('group.actionRadii') - }) - - it('has no(!) group categories "law", "politics", "it-and-media"', () => { - expect(wrapper.text()).not.toContain('group.categories') - expect(wrapper.text()).not.toContain('contribution.category.name.law') - expect(wrapper.text()).not.toContain('contribution.category.name.politics') - expect(wrapper.text()).not.toContain('contribution.category.name.it-and-media') - }) - - it('has no(!) group goal', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has not(!) ProfileList', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(false) - }) - - it('has not(!) description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(false) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has no(!) empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(false) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) @@ -1547,90 +574,8 @@ describe('GroupProfileSlug', () => { }) }) - it('has no(!) group name – to verificate the group', () => { - expect(wrapper.text()).not.toContain('Investigative Journalism') - }) - - it('has not(!) AvatarUploader', () => { - expect(wrapper.find('.avatar-uploader').exists()).toBe(false) - }) - - it('has not(!) ProfileAvatar', () => { - expect(wrapper.find('.profile-avatar').exists()).toBe(false) - }) - - it('has not(!) GroupContentMenu', () => { - expect(wrapper.find('.group-content-menu').exists()).toBe(false) - }) - - it('has no(!) group slug', () => { - // expect(wrapper.find('[data-test="ampersand"]').exists()).toBe(false) - expect(wrapper.text()).not.toContain('&investigative-journalism') - }) - - describe('displays not(!) group location', () => { - it('has no(!) group location icon "map-marker"', () => { - expect(wrapper.find('[data-test="map-marker"]').exists()).toBe(false) - }) - - it('has no(!) group location name "Hamburg"', () => { - expect(wrapper.text()).not.toContain('Hamburg') - }) - }) - - it('has no(!) group foundation', () => { - expect(wrapper.text()).not.toContain('group.foundation') - }) - - it('has no(!) members count', () => { - expect(wrapper.text()).not.toContain('group.membersCount') - }) - - it('has no(!) join/leave button', () => { - expect(wrapper.find('.join-leave-button').exists()).toBe(false) - }) - - it('has no(!) group role', () => { - expect(wrapper.text()).not.toContain('group.role') - expect(wrapper.text()).not.toContain('group.roles') - }) - - it('has no(!) group type', () => { - expect(wrapper.text()).not.toContain('group.type') - expect(wrapper.text()).not.toContain('group.types') - }) - - it('has no(!) group action radius', () => { - expect(wrapper.text()).not.toContain('group.actionRadius') - expect(wrapper.text()).not.toContain('group.actionRadii') - }) - - it('has no(!) group categories "law", "politics", "it-and-media"', () => { - expect(wrapper.text()).not.toContain('group.categories') - expect(wrapper.text()).not.toContain('contribution.category.name.law') - expect(wrapper.text()).not.toContain('contribution.category.name.politics') - expect(wrapper.text()).not.toContain('contribution.category.name.it-and-media') - }) - - it('has no(!) group goal', () => { - expect(wrapper.text()).not.toContain('group.goal') - }) - - it('has not(!) ProfileList', () => { - const profileList = wrapper.find('.profile-list') - expect(profileList.exists()).toBe(false) - }) - - it('has not(!) description BaseCard', () => { - expect(wrapper.find('.group-description').exists()).toBe(false) - }) - - it('has no(!) profile post add button', () => { - expect(wrapper.find('.profile-post-add-button').exists()).toBe(false) - }) - - it('has no(!) empty post list', () => { - expect(wrapper.find('[data-test="icon-empty"]').exists()).toBe(false) + it('renders', () => { + expect(wrapper.container).toMatchSnapshot() }) }) }) diff --git a/webapp/pages/groups/_id/_slug.vue b/webapp/pages/groups/_id/_slug.vue index 10d2ca8d2..9061f047e 100644 --- a/webapp/pages/groups/_id/_slug.vue +++ b/webapp/pages/groups/_id/_slug.vue @@ -18,18 +18,14 @@ - - @@ -84,19 +80,9 @@ -->
- + + {{ $t('group.unmute') }} + -

@@ -314,8 +298,7 @@ import uniqBy from 'lodash/uniqBy' import { profilePagePosts } from '~/graphql/PostQuery' import { updateGroupMutation, groupQuery, groupMembersQuery } from '~/graphql/groups' -// import { muteUser, unmuteUser } from '~/graphql/settings/MutedUsers' -// import { blockUser, unblockUser } from '~/graphql/settings/BlockedUsers' +import { muteGroup, unmuteGroup } from '~/graphql/settings/MutedGroups' import UpdateQuery from '~/components/utils/UpdateQuery' import postListActions from '~/mixins/postListActions' import AvatarUploader from '~/components/Uploader/AvatarUploader' @@ -470,6 +453,32 @@ export default { // this.resetPostList() // } // }, + async muteGroup() { + try { + await this.$apollo.mutate({ + mutation: muteGroup(), + variables: { + groupId: this.group.id, + }, + }) + this.$toast.success(this.$t('group.muted')) + } catch (error) { + this.$toast.error(error.message) + } + }, + async unmuteGroup() { + try { + await this.$apollo.mutate({ + mutation: unmuteGroup(), + variables: { + groupId: this.group.id, + }, + }) + this.$toast.success(this.$t('group.unmuted')) + } catch (error) { + this.$toast.error(error.message) + } + }, uniq(items, field = 'id') { return uniqBy(items, field) }, From fa0280f9e9787ae9b74d22556fc59088cc2d4d74 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Apr 2025 01:44:21 +0200 Subject: [PATCH 06/18] fix block user (#8363) --- backend/src/schema/resolvers/users.ts | 65 ++++++++++++++++++--------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/backend/src/schema/resolvers/users.ts b/backend/src/schema/resolvers/users.ts index e4e701006..afbdd42a6 100644 --- a/backend/src/schema/resolvers/users.ts +++ b/backend/src/schema/resolvers/users.ts @@ -113,32 +113,53 @@ export default { blockUser: async (object, args, context, resolveInfo) => { const { user: currentUser } = context if (currentUser.id === args.id) return null - await neode.cypher( - ` - MATCH(u:User {id: $currentUser.id})-[r:FOLLOWS]->(b:User {id: $args.id}) - DELETE r - `, - { currentUser, args }, - ) - const [user, blockedUser] = await Promise.all([ - neode.find('User', currentUser.id), - neode.find('User', args.id), - ]) - await user.relateTo(blockedUser, 'blocked') - return blockedUser.toJson() + + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const unBlockUserTransactionResponse = await transaction.run( + ` + MATCH (blockedUser:User {id: $args.id}) + MATCH (currentUser:User {id: $currentUser.id}) + OPTIONAL MATCH (currentUser)-[r:FOLLOWS]->(blockedUser) + DELETE r + CREATE (currentUser)-[:BLOCKED]->(blockedUser) + RETURN blockedUser {.*} + `, + { currentUser, args }, + ) + return unBlockUserTransactionResponse.records.map((record) => record.get('blockedUser'))[0] + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new UserInputError(error.message) + } finally { + session.close() + } }, unblockUser: async (object, args, context, resolveInfo) => { const { user: currentUser } = context if (currentUser.id === args.id) return null - await neode.cypher( - ` - MATCH(u:User {id: $currentUser.id})-[r:BLOCKED]->(b:User {id: $args.id}) - DELETE r - `, - { currentUser, args }, - ) - const blockedUser = await neode.find('User', args.id) - return blockedUser.toJson() + + const session = context.driver.session() + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const unBlockUserTransactionResponse = await transaction.run( + ` + MATCH(u:User {id: $currentUser.id})-[r:BLOCKED]->(blockedUser:User {id: $args.id}) + DELETE r + RETURN blockedUser {.*} + `, + { currentUser, args }, + ) + return unBlockUserTransactionResponse.records.map((record) => record.get('blockedUser'))[0] + }) + try { + return await writeTxResultPromise + } catch (error) { + throw new UserInputError(error.message) + } finally { + session.close() + } }, UpdateUser: async (_parent, params, context, _resolveInfo) => { const { avatar: avatarInput } = params From 117c0d75e71388c2c1d2d163b30b0d6ffd098cd4 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Apr 2025 02:50:16 +0200 Subject: [PATCH 07/18] refactor(backend): user graphql (#8354) * refactor user graphql - remove isLoggedIn query - currentUser query only for authenticated, currenUser always returns a User - currentUser query implementation uses neo4jgraphql with id parameter - remove custom email field from user - fix bug in frontend when there is no categories * remove comment * remove unused filter * fix currentuser test * fixedswitchUserRole mutation * fix categories --- .../src/middleware/permissionsMiddleware.ts | 3 +- .../schema/resolvers/user_management.spec.ts | 79 ++++++------------- .../src/schema/resolvers/user_management.ts | 35 +------- backend/src/schema/resolvers/users.ts | 18 ++--- backend/src/schema/types/type/User.gql | 3 +- backend/src/server.spec.ts | 44 ----------- webapp/components/LoginForm/LoginForm.vue | 2 +- 7 files changed, 37 insertions(+), 147 deletions(-) delete mode 100644 backend/src/server.spec.ts diff --git a/backend/src/middleware/permissionsMiddleware.ts b/backend/src/middleware/permissionsMiddleware.ts index b8c728f4c..0f2b71678 100644 --- a/backend/src/middleware/permissionsMiddleware.ts +++ b/backend/src/middleware/permissionsMiddleware.ts @@ -384,7 +384,7 @@ export default shield( Tag: allow, reports: isModerator, statistics: allow, - currentUser: allow, + currentUser: isAuthenticated, Group: isAuthenticated, GroupMembers: isAllowedSeeingGroupMembers, GroupCount: isAuthenticated, @@ -392,7 +392,6 @@ export default shield( profilePagePosts: allow, Comment: allow, User: or(noEmailFilter, isAdmin), - isLoggedIn: allow, Badge: allow, PostsEmotionsCountByEmotion: allow, PostsEmotionsByCurrentUser: isAuthenticated, diff --git a/backend/src/schema/resolvers/user_management.spec.ts b/backend/src/schema/resolvers/user_management.spec.ts index d9905fd71..527821856 100644 --- a/backend/src/schema/resolvers/user_management.spec.ts +++ b/backend/src/schema/resolvers/user_management.spec.ts @@ -64,55 +64,6 @@ afterEach(async () => { await cleanDatabase() }) -describe('isLoggedIn', () => { - const isLoggedInQuery = gql` - { - isLoggedIn - } - ` - const respondsWith = async (expected) => { - await expect(query({ query: isLoggedInQuery })).resolves.toMatchObject(expected) - } - - describe('unauthenticated', () => { - it('returns false', async () => { - await respondsWith({ data: { isLoggedIn: false } }) - }) - }) - - describe('authenticated', () => { - beforeEach(async () => { - user = await Factory.build('user', { id: 'u3' }) - const userBearerToken = encode({ id: 'u3' }) - req = { headers: { authorization: `Bearer ${userBearerToken}` } } - }) - - it('returns true', async () => { - await respondsWith({ data: { isLoggedIn: true } }) - }) - - describe('but user is disabled', () => { - beforeEach(async () => { - await disable('u3') - }) - - it('returns false', async () => { - await respondsWith({ data: { isLoggedIn: false } }) - }) - }) - - describe('but user is deleted', () => { - beforeEach(async () => { - await user.update({ updatedAt: new Date().toISOString(), deleted: true }) - }) - - it('returns false', async () => { - await respondsWith({ data: { isLoggedIn: false } }) - }) - }) - }) -}) - describe('currentUser', () => { const currentUserQuery = gql` { @@ -135,8 +86,8 @@ describe('currentUser', () => { } describe('unauthenticated', () => { - it('returns null', async () => { - await respondsWith({ data: { currentUser: null } }) + it('throws "Not Authorized!"', async () => { + await respondsWith({ errors: [{ message: 'Not Authorized!' }] }) }) }) @@ -200,10 +151,32 @@ describe('currentUser', () => { ) }) - it('returns empty array for all categories', async () => { + it('returns all categories by default', async () => { await respondsWith({ data: { - currentUser: expect.objectContaining({ activeCategories: [] }), + currentUser: expect.objectContaining({ + activeCategories: [ + 'cat1', + 'cat10', + 'cat11', + 'cat12', + 'cat13', + 'cat14', + 'cat15', + 'cat16', + 'cat17', + 'cat18', + 'cat19', + 'cat2', + 'cat3', + 'cat4', + 'cat5', + 'cat6', + 'cat7', + 'cat8', + 'cat9', + ], + }), }, }) }) diff --git a/backend/src/schema/resolvers/user_management.ts b/backend/src/schema/resolvers/user_management.ts index dfc33b6ae..e9376f940 100644 --- a/backend/src/schema/resolvers/user_management.ts +++ b/backend/src/schema/resolvers/user_management.ts @@ -1,5 +1,6 @@ import { AuthenticationError } from 'apollo-server' import bcrypt from 'bcryptjs' +import { neo4jgraphql } from 'neo4j-graphql-js' import { getNeode } from '@db/neo4j' import encode from '@jwt/encode' @@ -11,38 +12,8 @@ const neode = getNeode() export default { Query: { - isLoggedIn: (_, args, { driver, user }) => { - return Boolean(user && user.id) - }, - currentUser: async (object, params, context, resolveInfo) => { - const { user, driver } = context - if (!user) return null - const session = driver.session() - const currentUserTransactionPromise = session.readTransaction(async (transaction) => { - const result = await transaction.run( - ` - MATCH (user:User {id: $id}) - OPTIONAL MATCH (category:Category) WHERE NOT ((user)-[:NOT_INTERESTED_IN]->(category)) - OPTIONAL MATCH (cats:Category) - WITH user, [(user)<-[:OWNED_BY]-(medium:SocialMedia) | properties(medium) ] AS media, category, toString(COUNT(cats)) AS categoryCount - RETURN user {.*, socialMedia: media, activeCategories: collect(category.id) } AS user, categoryCount - `, - { id: user.id }, - ) - const [categoryCount] = result.records.map((record) => record.get('categoryCount')) - const [currentUser] = result.records.map((record) => record.get('user')) - // frontend expects empty array when all categories are selected - if (currentUser.activeCategories.length === parseInt(categoryCount)) - currentUser.activeCategories = [] - return currentUser - }) - try { - const currentUser = await currentUserTransactionPromise - return currentUser - } finally { - session.close() - } - }, + currentUser: async (object, params, context, resolveInfo) => + neo4jgraphql(object, { id: context.user.id }, context, resolveInfo), }, Mutation: { login: async (_, { email, password }, { driver, req, user }) => { diff --git a/backend/src/schema/resolvers/users.ts b/backend/src/schema/resolvers/users.ts index afbdd42a6..e93dffbd0 100644 --- a/backend/src/schema/resolvers/users.ts +++ b/backend/src/schema/resolvers/users.ts @@ -66,12 +66,12 @@ export default { const result = txc.run( ` MATCH (user:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email: $args.email}) - RETURN user`, + RETURN user {.*, email: e.email}`, { args }, ) return result }) - return readTxResult.records.map((r) => r.get('user').properties) + return readTxResult.records.map((r) => r.get('user')) } finally { session.close() } @@ -291,14 +291,14 @@ export default { const switchUserRoleResponse = await transaction.run( ` MATCH (user:User {id: $id}) + OPTIONAL MATCH (user)-[:PRIMARY_EMAIL]->(e:EmailAddress) SET user.role = $role SET user.updatedAt = toString(datetime()) - RETURN user {.*} + RETURN user {.*, email: e.email} `, { id, role }, ) - const [user] = switchUserRoleResponse.records.map((record) => record.get('user')) - return user + return switchUserRoleResponse.records.map((record) => record.get('user'))[0] }) try { const user = await writeTxResultPromise @@ -383,14 +383,6 @@ export default { }, }, User: { - email: async (parent, params, context, resolveInfo) => { - if (typeof parent.email !== 'undefined') return parent.email - const { id } = parent - const statement = `MATCH(u:User {id: $id})-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e` - const result = await neode.cypher(statement, { id }) - const [{ email }] = result.records.map((r) => r.get('e').properties) - return email - }, emailNotificationSettings: async (parent, params, context, resolveInfo) => { return [ { diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index 37281d6bb..cac622316 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -199,8 +199,7 @@ type Query { availableRoles: [UserRole]! mutedUsers: [User] blockedUsers: [User] - isLoggedIn: Boolean! - currentUser: User + currentUser: User! } enum Deletable { diff --git a/backend/src/server.spec.ts b/backend/src/server.spec.ts deleted file mode 100644 index 1d5c5aca8..000000000 --- a/backend/src/server.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { createTestClient } from 'apollo-server-testing' - -import createServer from './server' - -/** - * This file is for demonstration purposes. It does not really test the - * `isLoggedIn` query but demonstrates how we can use `apollo-server-testing`. - * All we need to do is to get an instance of `ApolloServer` and maybe we want - * stub out `context` as shown below. - * - */ - -let user -let action -describe('isLoggedIn', () => { - beforeEach(() => { - action = async () => { - const { server } = createServer({ - context: () => { - return { - user, - } - }, - }) - const { query } = createTestClient(server) - - const isLoggedIn = `{ isLoggedIn }` - return query({ query: isLoggedIn }) - } - }) - - it('returns false', async () => { - const expected = expect.objectContaining({ data: { isLoggedIn: false } }) - await expect(action()).resolves.toEqual(expected) - }) - - describe('when authenticated', () => { - it('returns true', async () => { - user = { id: '123' } - const expected = expect.objectContaining({ data: { isLoggedIn: true } }) - await expect(action()).resolves.toEqual(expected) - }) - }) -}) diff --git a/webapp/components/LoginForm/LoginForm.vue b/webapp/components/LoginForm/LoginForm.vue index 59a6d7a24..5bdf356fe 100644 --- a/webapp/components/LoginForm/LoginForm.vue +++ b/webapp/components/LoginForm/LoginForm.vue @@ -100,7 +100,7 @@ export default { await this.$store.dispatch('auth/login', { email, password }) if (this.currentUser && this.currentUser.activeCategories) { this.resetCategories() - if (this.currentUser.activeCategories.length > 0) { + if (this.currentUser.activeCategories.length < 19) { this.currentUser.activeCategories.forEach((categoryId) => { this.toggleCategory(categoryId) }) From 04bf693453ac0ac7ecf15e04c742aad97d1c4e2c Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Apr 2025 12:18:05 +0200 Subject: [PATCH 08/18] release script does not include commits (#8381) --- scripts/release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release.sh b/scripts/release.sh index 453375203..c078d6b04 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -26,4 +26,4 @@ sed -i -e 's/appVersion: ".*"/appVersion: "'"$VERSION_NEW"'"/g' $ROOT_DIR/deploy # generate changelog cd $ROOT_DIR -yarn run auto-changelog --latest-version $VERSION_NEW \ No newline at end of file +yarn run auto-changelog --commit-limit 0 --latest-version $VERSION_NEW \ No newline at end of file From 7d9b0e6437641df45d077137b13fafe431e67822 Mon Sep 17 00:00:00 2001 From: mahula Date: Sat, 12 Apr 2025 12:59:56 +0200 Subject: [PATCH 09/18] refactor(backend): set up smtp pooling for nodemailer (#8167) * backend: active SMTP pooling in Nodemailer configuration * backend: add max SMTPconnections and messages to Nodemailer configuration * move transport outside function to ensure pooling can work --------- Co-authored-by: Ulf Gebhardt --- backend/.env.template | 2 ++ backend/src/config/index.ts | 2 ++ .../src/middleware/helpers/email/sendMail.ts | 35 ++++++++++--------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/backend/.env.template b/backend/.env.template index d398c2265..ddade4e40 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -12,6 +12,8 @@ EMAIL_DEFAULT_SENDER="devops@ocelot.social" SMTP_HOST= SMTP_PORT= SMTP_IGNORE_TLS=true +SMTP_MAX_CONNECTIONS=5 +SMTP_MAX_MESSAGES=Infinity SMTP_USERNAME= SMTP_PASSWORD= SMTP_SECURE="false" # true for 465, false for other ports diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 5eb58fa89..328bbbd61 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -57,6 +57,8 @@ const smtp = { SMTP_DKIM_KEYSELECTOR: hasDKIMData && env.SMTP_DKIM_KEYSELECTOR, // PEM format: https://docs.progress.com/bundle/datadirect-hybrid-data-pipeline-installation-46/page/PEM-file-format.html SMTP_DKIM_PRIVATKEY: hasDKIMData && env.SMTP_DKIM_PRIVATKEY.replace(/\\n/g, '\n'), // replace all "\n" in .env string by real line break + SMTP_MAX_CONNECTIONS: env.SMTP_MAX_CONNECTIONS || 5, + SMTP_MAX_MESSAGES: env.SMTP_MAX_MESSAGES || 100, } const neo4j = { diff --git a/backend/src/middleware/helpers/email/sendMail.ts b/backend/src/middleware/helpers/email/sendMail.ts index 02456f391..46d808742 100644 --- a/backend/src/middleware/helpers/email/sendMail.ts +++ b/backend/src/middleware/helpers/email/sendMail.ts @@ -9,6 +9,25 @@ const hasAuthData = CONFIG.SMTP_USERNAME && CONFIG.SMTP_PASSWORD const hasDKIMData = CONFIG.SMTP_DKIM_DOMAINNAME && CONFIG.SMTP_DKIM_KEYSELECTOR && CONFIG.SMTP_DKIM_PRIVATKEY +const transporter = nodemailer.createTransport({ + host: CONFIG.SMTP_HOST, + port: CONFIG.SMTP_PORT, + ignoreTLS: CONFIG.SMTP_IGNORE_TLS, + secure: CONFIG.SMTP_SECURE, // true for 465, false for other ports + pool: true, + maxConnections: CONFIG.SMTP_MAX_CONNECTIONS, + maxMessages: CONFIG.SMTP_MAX_MESSAGES, + auth: hasAuthData && { + user: CONFIG.SMTP_USERNAME, + pass: CONFIG.SMTP_PASSWORD, + }, + dkim: hasDKIMData && { + domainName: CONFIG.SMTP_DKIM_DOMAINNAME, + keySelector: CONFIG.SMTP_DKIM_KEYSELECTOR, + privateKey: CONFIG.SMTP_DKIM_PRIVATKEY, + }, +}) + let sendMailCallback: any = async () => {} if (!hasEmailConfig) { if (!CONFIG.TEST) { @@ -38,22 +57,6 @@ if (!hasEmailConfig) { } } else { sendMailCallback = async (templateArgs) => { - const transporter = nodemailer.createTransport({ - host: CONFIG.SMTP_HOST, - port: CONFIG.SMTP_PORT, - ignoreTLS: CONFIG.SMTP_IGNORE_TLS, - secure: CONFIG.SMTP_SECURE, // true for 465, false for other ports - auth: hasAuthData && { - user: CONFIG.SMTP_USERNAME, - pass: CONFIG.SMTP_PASSWORD, - }, - dkim: hasDKIMData && { - domainName: CONFIG.SMTP_DKIM_DOMAINNAME, - keySelector: CONFIG.SMTP_DKIM_KEYSELECTOR, - privateKey: CONFIG.SMTP_DKIM_PRIVATKEY, - }, - }) - transporter.use( 'compile', htmlToText({ From 2c7bfc700e5675a5390d98aa41a35a48e0b5e008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 12 Apr 2025 13:27:03 +0200 Subject: [PATCH 10/18] chore(backend): add e-mail setting for our new 'mailserver' to our backend .env.template (#8359) * Add e-mail setting for our new 'mailserver' to our backend .env.template * Reverse to default settings --------- Co-authored-by: Ulf Gebhardt --- backend/.env.template | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/.env.template b/backend/.env.template index ddade4e40..4d7ae42d2 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -6,7 +6,7 @@ NEO4J_PASSWORD=letmein GRAPHQL_URI=http://localhost:4000 CLIENT_URI=http://localhost:3000 -# EMail +# E-Mail default settings EMAIL_SUPPORT="devops@ocelot.social" EMAIL_DEFAULT_SENDER="devops@ocelot.social" SMTP_HOST= @@ -20,6 +20,12 @@ SMTP_SECURE="false" # true for 465, false for other ports SMTP_DKIM_DOMAINNAME= SMTP_DKIM_KEYSELECTOR= SMTP_DKIM_PRIVATKEY= +# E-Mail settings for our 'docker compose up mailserver' +# SMTP_HOST=localhost +# SMTP_PORT=1025 +# SMTP_IGNORE_TLS=true +# SMTP_USERNAME= +# SMTP_PASSWORD= JWT_SECRET="b/&&7b78BF&fv/Vd" JWT_EXPIRES="2y" From a494f5e41e1bf1bf5ad9e2d9440b15cfdc18c630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 12 Apr 2025 13:55:12 +0200 Subject: [PATCH 11/18] fix(webapp): refine group muting locales (#8378) * Refine group muting locales * Revert toast message text in locale DE --- webapp/locales/de.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index fb8866005..19d0896a9 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -485,8 +485,8 @@ "categoriesTitle": "Themen der Gruppe", "changeMemberRole": "Die Rolle wurde auf „{role}“ geändert!", "contentMenu": { - "muteGroup": "Gruppe stummschalten", - "unmuteGroup": "Gruppe nicht mehr stummschalten", + "muteGroup": "Stummschalten", + "unmuteGroup": "Nicht stummschalten", "visitGroupPage": "Gruppe anzeigen" }, "createNewGroup": { @@ -562,7 +562,7 @@ "hidden": "Geheim — Gruppe (auch der Name) komplett unsichtbar", "public": "Öffentlich — Gruppe und alle Beiträge für registrierte Nutzer sichtbar" }, - "unmute": "Gruppe nicht mehr stummschalten", + "unmute": "Nicht stummschalten", "unmuted": "Gruppe nicht mehr stummgeschaltet", "update": "Änderung speichern", "updatedGroup": "Die Gruppendaten wurden geändert!" From 8aa00216dfbb90d87626220cdf88a7c701fe3e74 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 12 Apr 2025 14:47:01 +0200 Subject: [PATCH 12/18] v3.3.0 (#8380) regenerate changelog --- CHANGELOG.md | 280 +++++------------- backend/package.json | 2 +- .../helm/charts/ocelot-neo4j/Chart.yaml | 2 +- .../helm/charts/ocelot-social/Chart.yaml | 2 +- frontend/package.json | 2 +- package.json | 2 +- webapp/maintenance/source/package.json | 2 +- webapp/package.json | 2 +- 8 files changed, 87 insertions(+), 207 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f383034d5..361c5df32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,88 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [3.3.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.2.1...3.3.0) + +- fix(webapp): refine group muting locales [`#8378`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8378) +- chore(backend): add e-mail setting for our new 'mailserver' to our backend .env.template [`#8359`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8359) +- refactor(backend): set up smtp pooling for nodemailer [`#8167`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8167) +- release script does not include commits [`#8381`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8381) +- refactor(backend): user graphql [`#8354`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8354) +- fix block user [`#8363`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8363) +- feat(webapp): add mute/unumute group to menu [`#8335`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8335) +- test that there is no email sent when no notification [`#8362`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8362) +- feat(backend): notify posts in groups [`#8346`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8346) +- docker compose files: use current maildev image from the right repo [`#8351`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8351) +- feat(backend): notify users when a followed user posted [`#8313`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8313) +- fix(backend): fixing admin email notification settings [`#8356`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8356) +- fix(backend): error when there is an abandoned email [`#8315`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8315) +- migrate commenting users to observe commented posts [`#8308`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8308) +- refactor(backend): new chat message notification email [`#8357`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8357) +- refactor(backend): clean migrate scripts [`#8317`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8317) +- feat(webapp): notification settings frontend [`#8320`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8320) +- posts and comments created by the factory set the observe relation [`#8344`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8344) +- refactor(backend): lint - import/order [`#8350`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8350) +- lint - import/no-relative-parent-imports [`#8349`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8349) +- refactor(other): cleanup cypress configuration [`#8345`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8345) +- lint - update plugin promise and cleanup rules [`#8343`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8343) +- lint plugin n - update and cleanup [`#8342`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8342) +- lint import/no-extraneous-dependencies [`#8341`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8341) +- build(deps): bump express from 4.21.2 to 5.1.0 in /webapp [`#8334`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8334) +- build(deps): bump express from 4.21.2 to 5.1.0 in /backend [`#8322`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8322) +- build(deps): bump mime-types from 2.1.35 to 3.0.1 in /backend [`#8298`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8298) +- feat(backend): lint rules [`#8339`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8339) +- feat(backend): chat notify via email [`#8314`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8314) +- build(deps): Bump docker/metadata-action [`#8245`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8245) +- build(deps): Bump docker/build-push-action from 6.9.0 to 6.15.0 [`#8244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8244) +- build(deps): bump docker/login-action from 3.3.0 to 3.4.0 [`#8271`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8271) +- build(deps): bump sass from 1.85.0 to 1.86.3 in /webapp [`#8333`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8333) +- build(deps): bump validator from 13.12.0 to 13.15.0 in /webapp [`#8305`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8305) +- build(deps-dev): bump @faker-js/faker from 9.5.0 to 9.6.0 [`#8257`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8257) +- build(deps-dev): bump @faker-js/faker from 9.5.0 to 9.6.0 in /webapp [`#8262`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8262) +- build(deps): bump crazy-max/ghaction-github-pages from 4.1.0 to 4.2.0 [`#8328`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8328) +- build(deps): bump peter-evans/repository-dispatch [`#8330`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8330) +- build(deps): Bump actions/checkout from 4.2.1 to 4.2.2 [`#8247`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8247) +- build(deps-dev): bump eslint-config-prettier in /webapp [`#8259`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8259) +- build(deps-dev): bump eslint-import-resolver-typescript in /backend [`#8326`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8326) +- build(deps): bump actions/cache from 4.2.1 to 4.2.3 [`#8287`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8287) +- build(deps-dev): bump @types/node from 22.13.5 to 22.14.0 in /backend [`#8325`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8325) +- build(deps-dev): bump typescript from 5.7.3 to 5.8.3 in /backend [`#8324`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8324) +- build(deps): bump the babel group across 1 directory with 2 updates [`#8296`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8296) +- build(deps-dev): bump @faker-js/faker from 9.5.0 to 9.6.0 in /backend [`#8268`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8268) +- build(deps-dev): Bump ts-jest in /backend in the typescript group [`#8237`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8237) +- build(deps): bump helmet from 8.0.0 to 8.1.0 in /backend [`#8284`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8284) +- build(deps): bump validator from 13.12.0 to 13.15.0 in /backend [`#8297`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8297) +- build(deps): bump sanitize-html from 2.14.0 to 2.15.0 in /backend [`#8285`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8285) +- build(deps): bump the metascraper group across 1 directory with 12 updates [`#8327`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8327) +- build(deps-dev): bump @babel/core in the babel group [`#8277`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8277) +- build(deps-dev): bump prettier from 3.5.2 to 3.5.3 in /webapp [`#8260`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8260) +- build(deps-dev): bump eslint-plugin-vue from 9.32.0 to 9.33.0 in /webapp [`#8264`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8264) +- build(deps-dev): bump prettier from 3.5.2 to 3.5.3 in /backend [`#8266`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8266) +- fix(other): leftover hetzner deployment [`#8254`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8254) +- refactor(backend): comment on observed post notification [`#8311`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8311) +- feat(frontend): observe posts [`#8293`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8293) +- expose port so the mailserver can actually be used [`#8319`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8319) +- build(deps-dev): bump eslint-config-prettier in /backend [`#8269`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8269) +- build(deps-dev): bump eslint-plugin-prettier in /backend [`#8300`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8300) +- build(deps): bump amannn/action-semantic-pull-request [`#8303`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8303) +- build(deps): bump actions/setup-node from 4.2.0 to 4.3.0 [`#8288`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8288) +- build(deps): bump actions/upload-artifact from 4.6.1 to 4.6.2 [`#8289`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8289) +- fix(backend): typo in groups resolver [`#8318`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8318) +- fix frontend package lock [`#8316`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8316) +- migration adds OBSERVES relation between author and post [`#8307`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8307) +- fix(backend): users observing post count [`#8295`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8295) +- feat(webapp): track online status [`#8312`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8312) +- Replace argfile by slurpfile [`#8309`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8309) +- build(deps-dev): Bump cypress from 14.0.3 to 14.1.0 in the cypress group [`#8229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8229) +- provide information of the observing status of the post after creating a comment [`#8310`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8310) +- feat(backend): observe posts [`#8292`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8292) +- release: also update helmchart versions [`#8256`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8256) + #### [3.2.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.2.0...3.2.1) +> 3 March 2025 + +- v3.2.1 [`#8248`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8248) - remove the requirement for non-existant job in publish workflow [`#8251`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8251) - removed dockerhub related stuff [`#8249`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8249) - feat(webapp): implement configurable custom button in header [`#8215`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8215) @@ -295,9 +375,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump dotenv from 16.3.1 to 16.4.4 [`#7010`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/7010) - Bump dorny/paths-filter from 3.0.0 to 3.0.1 [`#7006`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/7006) - chore(other): update packages 08.02 [`#75`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/75) -- update frontend packages [`fef8157`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fef8157b0cdf9081678365e9a7f6339ef787423c) -- update frontend packages [`dce59c1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/dce59c11089e23f3ed97dfbfea39507e7c098c30) -- Add converted SVG icons with properties 'fill' and 'stroke' on 'svg' tag [`b1a7e91`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/b1a7e916314a0d59a65d2cdb244e6117d796dda1) #### [3.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.2...3.2.0) @@ -453,9 +530,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix(other): fix link in `deployment/TODO-next-update.md` to `deployment/deployment-values.md` [`#6729`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6729) - Bump cypress from 13.2.0 to 13.3.1 [`#6789`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6789) - fix(other): remove buggy space in filename 'neo4j-data-snapshot.yaml ' to 'neo4j-data-snapshot.yaml' [`#6777`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6777) -- storybook tests [`ff7a1c5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ff7a1c548405c3a60341844679e70d93aebb2e3c) -- update vuepress [`cbf7bdc`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/cbf7bdc84ccf02c9658748b945dac7ebc405e5b2) -- update storybook [`a0b77d7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a0b77d78a3e7a483d204337e3d42dd9dd56ad69a) #### [3.1.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.1...3.1.2) @@ -464,9 +538,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(release): release v3.1.2 - fix kubernetes deployment by degrade Node version from v20.7.0 to v20.2.0 [`#6782`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6782) - fix(other): kubernetes error by degrading node version from v20.7.0 to v20.2.0 [`#6779`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6779) - fix(backend): cypher statement in user locales unit test [`#6780`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6780) -- Release v3.1.2 - Fix Kubernetes Deployment by degrade Node version from v20.7.0 to v20.2.0 [`aa2d27e`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/aa2d27e8caefeac578fb30fc5b426dbd51e84b34) -- Fix Dockerfile labels [`5d2c41d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5d2c41d12ec9c892a38d8f8e2325194618fc35e4) -- Degrade Node version from v20.7.0 to v20.2.0 [`988e874`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/988e874934dcf0caa060600e843138664fb367c5) #### [3.1.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.0...3.1.1) @@ -496,9 +567,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(other): bump node from 20.2.0-alpine3.17 to 20.6.0-alpine3.17 in /backend [`#6710`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6710) - build(other): bump actions/cache from 3.3.1 to 3.3.2 [`#6714`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6714) - build(other): bump actions/checkout from 3 to 4 [`#6713`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6713) -- Bump @storybook/vue from 6.3.6 to 7.4.0 in /webapp [`8113d47`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8113d47dfcbfa0a63ae1f035d9d24a4c548d2089) -- Revert "update cypress packages" [`2229baf`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2229baff6fb74d92ed395fb90a1421f994368a20) -- update cypress packages [`dbedcf9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/dbedcf901d3040d1a6a8db62170bdea86d020bb1) #### [3.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.0.4...3.1.0) @@ -507,9 +575,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(release): release v3.1.0 – use of dkim in deployment [`#6733`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6733) - chore(other): use dkim values in helm script of backend [`#6731`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6731) - fix(other): add global package.json to workflow file filters [`#6706`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6706) -- Release v3.1.0 [`6276d87`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/6276d87c6a427438c5fbf56c0f7bc414293e671d) -- Fix super fluid spaces [`ecdaf83`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ecdaf83ac57bd4186f064d891d2570ce2438d47f) -- Use DKIM values in Helm script of backend [`2ea98b1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2ea98b1900c1b33712a2456dde6ba3dfb6d95b00) #### [3.0.4](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.0.3...3.0.4) @@ -525,9 +590,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(other): bump @babel/preset-env from 7.9.5 to 7.22.9 in /backend [`#6578`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6578) - build(other): bump @babel/preset-env from 7.22.7 to 7.22.9 [`#6572`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6572) - build(other): bump dotenv from 8.6.0 to 16.3.1 [`#6483`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6483) -- Bump @babel/preset-env from 7.9.5 to 7.22.9 in /backend [`ae0c6f1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ae0c6f12bd86c39b33a2b48c2eeb0eccb880821c) -- Revert "Revert "Revert "update metascraper packages""" [`7fdc5e8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7fdc5e8f5ed8e191763acfcd74c510138145f612) -- Revert "Revert "update metascraper packages"" [`d5c1421`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d5c142129291264d5508b3f32b8500c2451a5f39) #### [3.0.3](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.0.2...3.0.3) @@ -539,9 +601,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix(webapp): filtermenu mobile bug [`#6694`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6694) - fix(webapp): fix proxyapiurl in chat rooms for the avatars [`#6693`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6693) - fix(webapp): fix the group link in the map [`#6698`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6698) -- Bump @babel/core from 7.22.8 to 7.22.9 [`209390a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/209390a7e026b03ee92f7b1ecb3b1a7b3b2e0232) -- Write documentation for DKIM e-mail setting [`9f5d32e`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9f5d32e527151854f1888614c59e0aa5f2b504d0) -- Release v3.0.3 [`7d761c2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7d761c262a6e7bf6382cc49148c55ac8037db12a) #### [3.0.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.0.1...3.0.2) @@ -550,9 +609,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(release): release v3.0.2 – fix chat avatar error and wrong font in network [`#6674`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6674) - fix(webapp): fix wrong font in whole network comming from chat component [`#6672`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6672) - fix(webapp): fix 'm.avatar is null' error message [`#6671`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6671) -- Release v3.0.2 [`7bcad81`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7bcad81785de39115ba03aa37fb26caeff7775f2) -- Remove font 'Quicksand' from the chat [`5b95419`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5b954197dc93bd5715f657539ca1b9b32d7d557a) -- Fix 'm.avatar is null' error message [`2c12331`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2c123313ed6267bb1c88470ba7ae3f4f693cfc15) #### [3.0.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.0.0...3.0.1) @@ -560,9 +616,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(release): release v3.0.1 – fix chat avatars [`#6667`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6667) - fix(webapp): try to fix avatars [`#6660`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6660) -- Releasde v3.0.1 – fix chat avatars [`0daeb5b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/0daeb5b957e11d206ceddc3e8b275929e1850d18) -- conditional url replacement [`5c1ab88`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5c1ab880127a5f4c1b457598fafd3ae9fe1a0d12) -- try to fix avatars [`6f43321`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/6f43321abad945602529b962e536546ab541cd70) ### [3.0.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.7.0...3.0.0) @@ -656,9 +709,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump node from 20.2.0-alpine3.17 to 20.3.0-alpine3.17 in /webapp [`#6408`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6408) - fix(backend): typescript fix [`#6448`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6448) - refactor(backend): migrate completely to typescript [`#6434`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6434) -- remove package cypress-file-upload from e2e testing [`73f6bc6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/73f6bc642194b0c73769d4e8d8e53645b6e80adf) -- fixed cypress [`5f545f3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5f545f3b8fc6927954e036b27ad2e123bcd36149) -- fix seed to not use promise all where easily refactored [`1b0f512`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/1b0f5124159033214f99bfbc4cebe9dfaa7dd76e) #### [2.7.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.6.0...2.7.0) @@ -716,9 +766,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat(backend): event parameters [`#6198`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6198) - feat(backend): create and update posts with labels [`#6197`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6197) - feat(backend): add article label to posts [`#6196`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6196) -- Cypress: update packaage info [`b38769b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/b38769b048e9cb9ca07862a61ea810f21b4ce82a) -- update cypress related packageges in package.json [`692ec2a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/692ec2a11555600647ec8d95b8296c9869948b02) -- fixed coverage reporting [`540cd40`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/540cd40e10ec0461ef17379cb93d914839f3a84f) #### [2.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.1...2.6.0) @@ -752,9 +799,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump @babel/core from 7.9.0 to 7.21.4 [`#6200`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6200) - Bump @babel/preset-env from 7.12.7 to 7.21.4 [`#6204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6204) - Bump expect from 25.3.0 to 29.5.0 [`#6098`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6098) -- separate test workflows [`3533a36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3533a36cdc811c0e1dae218fbc2184f7c4bc3951) -- get it working [`8df7d5d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8df7d5d265b0c5ba16f167a213631d765d2f985e) -- feat(webapp): group categories on posts [`3244f3f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3244f3f86d1e8c09e0fd49f43c49f0a3aa8b85ab) #### [2.5.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.0...2.5.1) @@ -763,9 +807,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(other): release v2.5.1 – fix filter menu width [`#6180`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6180) - feat(webapp): add tooltips to all menu icons [`#6185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6185) - fix(webapp): popup filter max-width [`#6177`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6177) -- Add tooltip to header notifications menu [`28505a5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/28505a5b181008ebcde6fa58b7a4a8459a492018) -- Add tooltip to header avatar menu [`4c0469f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4c0469f61a3c2fae23e50c6a5a2a91b63fac149a) -- Release v2.5.1 - fix filter menu width [`08def14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/08def14cafef7816d8e43f1896430400bda9635d) #### [2.5.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.4.0...2.5.0) @@ -885,9 +926,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - brand_as_default [`#4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4) - limit_replicasets [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3) - Deployment [`#2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2) -- moved example into stage.ocelot.social [`61b5112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/61b5112b8b547a7491d644c7c4dbfead39b61d79) -- feat(backand): upgrade jest to 29.4 [`4390d72`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4390d72477fb941f69bc9bdc24ac7713ef06e827) -- pages tests nearly working [`4850e45`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4850e456fe5b7c158f23acc7f153576472604300) #### [2.4.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.3.0...2.4.0) @@ -910,9 +948,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix(backend): do not expose registered emails on registration [`#5909`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5909) - refactor(backend): node 19 with fixed image upload [`#5897`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5897) - refactor(webapp): nump docker version to `16.19.0` in webapp & maintenance [`#5842`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5842) -- updated required packages for node19, fix fs-capacitator [`11087cb`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/11087cbaefde604668ac192b710666df09cb813c) -- fixed build error [`3889204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3889204f871df97b307401032900db7940913038) -- linting [`8bfe486`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8bfe486034badd55a8096982f81aba08207b9e83) #### [2.3.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.2.0...2.3.0) @@ -931,9 +966,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat(other): semantic pullrequest workflow [`#5634`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5634) - fix: Cannot Add Group Members as New Members to Group [`#5635`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5635) - fix: My Groups Count Includes Pending Membership [`#5631`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5631) -- frontend: jest coverage [`f57e11d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f57e11dd021dbb156b33fbd5538cf5ca32df7334) -- reverted yarn lock [`a01aee8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a01aee89a92bbc9885e2895c577eb3c63042ba22) -- reverted all package updates [`a520089`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a5200893f4508d45619447231b6789178a51daf7) #### [2.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.1.0...2.2.0) @@ -953,9 +985,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix: 🍰 Fix Group Teaser [`#5584`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5584) - feat: 🍰 List All Groups [`#5582`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5582) - feat: 🍰 Header Logo Routing Update [`#5579`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5579) -- add header menu to component, central variabl for screen width [`401f59a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/401f59ae8de5b1c27f0e26e1f71778d3257d2180) -- comment out LanguagesFilter, EmotionsFilter, fix tests, fix lint [`52dcd77`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/52dcd772fa81e02a0d95e89a9fc8232e70a09d28) -- fix lint [`15561cb`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/15561cb94f8768e93846c25945c935ae83977553) #### [2.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.0.0...2.1.0) @@ -965,9 +994,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 EPIC Groups [`#5132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5132) - chore: 🍰 Remove Group Branchs `5059-epic-groups` Separate Auto-Deployment [`#5552`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5552) - fix: [WIP] 🍰 Long Words Are Being Wrapped Now [`#5559`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5559) -- Remove groups separate auto-deployment [`c8d8168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c8d816887b2d49293d1b8ee2805d452fe10d907e) -- Release v2.1.0 [`dc085e9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/dc085e9e69b288fce6dd06e8d7eb05ef34bd9a7b) -- Add database migration to auto-deployment on publish [`ef06f1a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ef06f1a67d2654aaeb55d0434d3324a3ac37a380) ### [2.0.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.1.1...2.0.0) @@ -999,9 +1025,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 Implement `JoinGroup`, `GroupMember`, `SwitchGroupMemberRole` Resolvers [`#5199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5199) - chore: 🍰 Add Groups To Seeding [`#5185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5185) - feat: 🍰 Implement Group GQL Model And CRUD Resolvers – First Step [`#5139`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5139) -- Refine design and functionality of group list and create, edit group [`7b11122`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7b11122bea4868624dd1c1641219e71070412e20) -- improved code and tests as suggested by @tirokk, thanks for the great review! [`631f34a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/631f34a2e5224d68279337a92e7535794b670d70) -- implement and test post visibilty when leaving or changing the role in a group [`76bfe48`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/76bfe484768cf9b20b2dced865d5d3e3eb999235) #### [1.1.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.1.0...1.1.1) @@ -1030,9 +1053,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump cross-env from 7.0.2 to 7.0.3 in /webapp [`#5168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5168) - chore: 🍰 Add `--logHeapUsage` To Jest Test Call [`#5182`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5182) - refactor: 🍰 Rename `UserGroup` To `UserRole` [`#5143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5143) -- add new yunite icons [`bb0d632`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/bb0d6329e7e36ea03671318ea8dd128a6d5a5a7a) -- cleanup refactor rebranding [`5f5c0fa`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5f5c0faa1f28cd4df7681eba335ae5998b2d9cca) -- change color and scss in branding [`52070b8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/52070b8c570970bf48df561134bf67cb4111b640) #### [1.1.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.9...1.1.0) @@ -1042,9 +1062,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: Make Categories Optional [`#5102`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5102) - Update issue templates [`#5101`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5101) - chore: 🍰 Betters Automatic Deployment To `stage.ocelot.social` On Push To `master` Branch [`#5097`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5097) -- add optional categories to teaser and post [`bc95500`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/bc955003f7c33aabe592bee782aca973b4f00cba) -- env vatiable for CATEGORIES_ACTIVE and switch for categories in contribution form [`e31f250`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e31f250ea5e1949f4f08e72fe82622d41ecd85f1) -- fix some tests [`5393c2a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5393c2aeaaf070a637390c430d5f03057030ff52) #### [1.0.9](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.8...1.0.9) @@ -1058,9 +1075,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore: 🍰 Change `image` Entries In Docker Compose Files And Fix Apple M1 Problem [`#5073`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5073) - chore: 🍰 Rename Neo4j Docker Image In General To `neo4j-community:*` [`#5078`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5078) - chore: 🍰 Fix `ocelotsocialnetwork/webapp:latest` And `ocelotsocialnetwork/backend:latest` On Start In Cluster [`#5076`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5076) -- Add documentation for Apple M1 Docker Compose override files [`2f3f37c`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2f3f37c158cfc9b300540d3c8f016548b15a5277) -- Add documentation for Docker build analyzes [`fbbcc5b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fbbcc5bb854d53b5fa658b83d56d381a3cbc2b1a) -- Implement DigitalOcean Kubernetes deployment on publishing [`485e698`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/485e6986b88a14db5ab75ed12bab5cdc73592ca6) #### [1.0.8](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.7...1.0.8) @@ -1077,9 +1091,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - bug: 🍰 Replace Deleted Faker Package [`#4973`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4973) - fix: 🍰 Change Tip Tap Editor Legend Hover To Click [`#4911`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4911) - fix: 🍰 Fix Embed iframe Width And Height CSS [`#4897`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4897) -- Implement MySomethingList for social media, use list item slot [`d3cc49d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d3cc49d37ba260f9a285c078c57e673a32a76732) -- Split social media page and list component [`b740033`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/b7400339aba22d5fb5506dc3b25f082d7f09edfc) -- Remove input addSocialMedia [`58464fd`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/58464fd53ef6aab52af1c2477c2615648ad889e3) #### [1.0.7](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.6...1.0.7) @@ -1096,9 +1107,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - doc: 🍰 Update README.md Etc. [`#4733`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4733) - feat: 🍰 New CSS For Internal Pages [`#4741`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4741) - fix: 🍰 Change Notification E-Mails Settings Page Link [`#4742`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4742) -- Refactor internal pages to new CSS [`acad80c`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/acad80c3c8262934dd2e38961c08c0fde769099a) -- Renew JWT in decode test [`46eb6b8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/46eb6b82ea802d4d6ca7294cd32d1fe16425bfea) -- Revert "Renew JWT in decode test" only for changing the Neode version [`a0d92b4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a0d92b4853d09d725c1fb7886cbfed2a00e1f05c) #### [1.0.6](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.5...1.0.6) @@ -1111,9 +1119,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Bump codecov from 3.7.1 to 3.8.2 [`#4401`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4401) - Centered the login-form [`#4660`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4660) - Spelling Change [`#4654`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4654) -- suggested solutions [`5699620`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5699620c858925101f561f315034c57fae878964) -- Implement or move sort by date filter in filter menu [`16d8a42`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/16d8a42d9b4f90e8a1c22da0637f95adb25b4e8f) -- Translate order by [`245be52`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/245be52ac8d9e41998da10cf2d1a752bbefc0c0c) #### [1.0.5](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.4...1.0.5) @@ -1172,9 +1177,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 Post Editor Legend [`#4492`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4492) - New Issue type EPIC [`#4536`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4536) - Upgrade to GitHub-native Dependabot [`#4399`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4399) -- Remove superfluous package-lock.json [`c7e4e6d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c7e4e6d2b26d448b3d2787aff4a0bde32c24e919) -- Delete superfluous and always conflicting file package-lock.json [`9932796`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9932796d233789c76b917de533ec2efc99f6aa4a) -- Refactor pageParams, second step [`e8a0a5d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e8a0a5d13c0610066c50c98d5e0d661ee8139217) #### [1.0.4](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.3...1.0.4) @@ -1186,9 +1188,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 Flexible Footer Links [`#4468`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4468) - docs: 🍰 Correct 'Contribution.md' [`#4466`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4466) - docs: 🍰 Correct Discord Links And Divers [`#4461`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4461) -- Implement flexible page footer links [`1bd4af6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/1bd4af6fd3b5db167575910948a0a72461a1129a) -- Implement tests for flexible page footer links [`627a20f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/627a20f66a65450996a5fe3128fd37769fdfd629) -- Correct Discord links and divers [`0318910`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/0318910488e245c4a1d09181265de63d05a89cf1) #### [1.0.3](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.2...1.0.3) @@ -1204,18 +1203,12 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - frontend + backend coverage tests [`#4367`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4367) - refactor: 🍰 Refactor E-Mail Templates [`#4350`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4350) - feat: 🍰 Remove More-Info Of Post [`#4316`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4316) -- have cypress running locally - the tests still fail [`e3e0341`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e3e03415e1bd9e0be88f33930a52e63d8af64ee1) -- have cypress running locally - the tests still fail [`0ec0574`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/0ec05743751cfef0cb86c17b87e9e4ef9a2c9e47) -- Refactor logos, first step [`ff6cc30`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ff6cc306aff6150a924f1a647387e498d050ea9f) #### [1.0.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.1...1.0.2) > 6 April 2021 - fix: Email Confirmation-Link When An Invite-Code Is Given [`#4336`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4336) -- release v1.0.2 [`e583010`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e5830101e4b449905fe2d0018627d75af62b2a20) -- slider jumps to enter-nonce when link contains invite-code, email and nonce and method is invite-code. Thanks @tirokk [`c80b3a2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c80b3a212835f76cfc2f11542345d6c3b226995b) -- fix enail confirmation link when an invite-code is given [`27f0de9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/27f0de9464685c8f960bde9d07986fdc5b20f8f9) #### [1.0.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/1.0.0...1.0.1) @@ -1225,9 +1218,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - jwt_expiretime [`#4330`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4330) - Clean env, docker & workflow [`#4337`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4337) - fix: 🍰 Fixing The Avatars unwanted Border [`#4320`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4320) -- Change background color of avatar image to white [`e48a99a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e48a99afe63e96cffafe16db7bf5ae35cfdebd7a) -- removed config warning [`f6c070a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f6c070a3cb36c5593123b27b4d1b6a5b7a10aba3) -- include env files in build process [`dfe6f67`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/dfe6f679b3bb0f440aee986d6d12925cccee9050) ### [1.0.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.15...1.0.0) @@ -1241,9 +1231,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix: JWT Expires In 2 Years [`#4278`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4278) - Deployment [`#4263`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4263) - feat: 🍰 Redesign Registration Process Frontend [`#4168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4168) -- Delete unnecessary code [`3fa7e04`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3fa7e04d4895161db1f764ccad58e35188c9d065) -- basic invite button in frontend [`356f026`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/356f02622655a57561fcdecfcc8a735d23cac79f) -- setting up invite button [`e6dc3f4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e6dc3f42cedaf9953d737cf30cf7ed317b634be7) #### [0.6.15](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.14...0.6.15) @@ -1255,18 +1242,12 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - dashboard restructuring image [`#4266`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4266) - fix: 🐛 Adapted Editor List Styles [`#4239`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4239) - fix: Scrolling On Profile Page [`#4234`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4234) -- release 0.6.15 [`ef4265d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ef4265d9387d94aa09db2b80461c2ec90b4623ae) -- count views of post teaser [`1c3f628`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/1c3f628fb2e161400319b32da274952c1b57836e) -- tests fixed for clickedCount [`96066ea`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/96066eae02e659a00bce280f9f97a28ac1446ce0) #### [0.6.14](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.13...0.6.14) > 17 February 2021 - fix: Add Null Migration [`#4233`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4233) -- release 0.6.14 [`394860c`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/394860c1d0d6ff23f6653b81288890a67720deab) -- add null mutation [`a7489a0`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a7489a044c4b4b556f6b26d555657478ebd6409b) -- fixed misspelling in changelog [`3ad6d73`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3ad6d738fd5d9ed25c0cccc6ae60ed5cc37540ba) #### [0.6.13](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.12...0.6.13) @@ -1274,9 +1255,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix: css so follow button isn't blocked by adblock [`#4230`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4230) - fix: Query Available Roles As Admin [`#4225`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4225) -- release 0.6.13 [`e2503d4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e2503d496606aa79b5ab59319f76466e04a79bd0) -- avoid introspection to get available roles as admin [`a5df793`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a5df793c55ec8792066e61547ae287f7702675fd) -- css fix to trick adblock on follow button by @nila99 [`13931c9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/13931c90e7642da93de0e884afd1649de8181c6c) #### [0.6.12](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.11...0.6.12) @@ -1284,8 +1262,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Smtp secure option [`#4223`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4223) - chore: 🐛 Fix Migrations By Migrations Folder Having .gitkeep [`#4222`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4222) -- SMTP_SECURE option [`8e2d8a7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8e2d8a77c3a825880deb4c668d647ee6503edc7f) -- New file .gitkeep in migrations [`814c1b8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/814c1b88aed2e6e353f2af2f277229629cc2e788) #### [0.6.11](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.10...0.6.11) @@ -1294,16 +1270,12 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore: 🍰 Resolve WEBSOCKETS_URI .env Problem [`#4219`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4219) - chore: 🐛 'db:migrate up' By Moving Examples Outside Of Migrations Folder [`#4221`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4221) - fix: Location Tests In Backend [`#4220`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4220) -- MAPBOX introduced district for US-Cities. So I used a German City instead [`7a31334`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7a313344cbddaca7bcb073b01a549bfe2a5c3852) -- Resolve WEBSOCKETS_URI config problem [`ac27d6a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ac27d6ac9653046d98e559fe1532648d7ddfa92e) -- Fix 'db:migrate up' by moving examples outside of migrations folder [`063c730`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/063c730e5fb3e3ea363deb5adebdbf69589ec7b4) #### [0.6.10](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.9...0.6.10) > 12 February 2021 - Use original images [`#4217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4217) -- original images instead of broken whitelabled ones [`2303b92`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2303b92146d71d8ec12b6fa75a4a0c513db96594) #### [0.6.9](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.8...0.6.9) @@ -1311,25 +1283,18 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix_webapp_production [`#4216`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4216) - Move Old Migrations From HC To Examples Folder To Avoid Conflicts [`#4215`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4215) -- typo [`7d21196`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7d21196973282ce904db8776fbef8e0961dac6e5) -- fixed prodution stage of webapp container [`02d31d0`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/02d31d0a94aa73a5026d2d9c183c63d1a7e43b6c) -- moved old migrations from HC to examples folder to avoid conflicts with new migrations [`efec46d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/efec46d9d485ec439a25adcac6da105683a221ad) #### [0.6.8](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.7...0.6.8) > 11 February 2021 - refactor: 🍰 Remove Emojis From Post Page [`#4208`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4208) -- release 0.6.8 [`b947918`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/b94791873bb3c9524daff78fc9d0f7bdb385127d) -- Refinied design [`58728df`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/58728df97b3a21d34e9476f2be139add33c75b42) -- remove emojis from post page [`4097cc1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4097cc16f723dfd2af64c4adcfef978b1c81e07b) #### [0.6.7](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.6...0.6.7) > 10 February 2021 - Support newest docker [`#4210`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4210) -- push all tags again, since docker is updated on github (...) [`c491fd6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c491fd692155b16822426372c58b5770daf2c0aa) #### [0.6.6](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.5...0.6.6) @@ -1339,9 +1304,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 Switch User Role As Admin [`#4136`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4136) - feat: Image Cropping Is Optional [`#4199`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4199) - publish workflow [`#4195`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4195) -- change user roles is working, test fails [`c528269`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c528269cb2972e6ea937d31ba22d0e11168141f2) -- file upload: refactored [`650e83f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/650e83f4c250389477933a2e7d21d8245b0ce882) -- change user role: tests are working [`14dfe2a`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/14dfe2ae2cd4a24c06c9229893b33586dfceae4f) #### [0.6.5](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.6.4...0.6.5) @@ -1366,9 +1328,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat: 🍰 Allow Only Supported Image File Formats [`#3928`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3928) - refactor: Disbale Emoji, Language And Catgeory Filter [`#4193`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4193) - refactor: Remove Catgeories From Post Teaser [`#4191`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4191) -- - adjusted changelog to ocelot-social repo [`9603882`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9603882edebf8967e05abfa94e4e1ebf452d4e24) -- - first steps towards docker image deployment & github autotagging [`5503216`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5503216ad4a0230ac533042e4a69806590fc2a5a) -- - lots of additional tests [`0ba37aa`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/0ba37aab18f537d722aede7b87fa0b8e79f80e66) #### [0.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.6.0...0.6.0) @@ -1547,9 +1506,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps-dev): bump babel-jest from 25.2.3 to 25.2.4 in /backend [`#3363`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3363) - build(deps-dev): bump expect from 25.2.3 to 25.2.4 [`#3360`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3360) - build(deps-dev): bump auto-changelog from 1.16.2 to 1.16.3 [`#3334`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3334) -- snapshot changed / facebook link stays the same for testing purposes [`71f4e2b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/71f4e2bd6e8427de8ddab410ef0f8fc476309bf8) -- design data up to now [`72b8c22`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/72b8c2263496ac640ce4cba60da2159092ad2ae0) -- Change maintenance svg [`11aabf0`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/11aabf0b16ad69fa9d3e84a1628775d357c24985) #### [v0.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.5.0...v0.6.0) @@ -1575,9 +1531,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps-dev): bump babel-jest from 25.2.0 to 25.2.1 in /backend [`#3341`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3341) - build(deps-dev): bump jest from 25.1.0 to 25.2.1 in /webapp [`#3342`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3342) - feat(backend): upload original image files on S3 object storage [`#3262`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3262) -- refactor: CategoriesFilter to not use ds-flex [`1ffde6b`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/1ffde6bf1034d1a1d9b7bca62fe66fe64527314c) -- chore: fix lint w/ new linting rules [`06985c2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/06985c2dbbc6699cc5c3dfd6e55cac8d28e9019b) -- chore: Fix lint w/ new linting rules [`cb0a3f5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/cb0a3f5cdd5e7fe47f46ae08798628eecb28e9b5) #### [v0.5.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.4.2...v0.5.0) @@ -1632,9 +1585,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps-dev): bump date-fns from 2.10.0 to 2.11.0 [`#3273`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3273) - build(deps): [security] bump acorn from 6.3.0 to 6.4.1 in /backend [`#3270`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3270) - build(deps): [security] bump acorn from 6.1.1 to 6.4.1 [`#3269`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3269) -- Update prettier to v2 [`276ea79`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/276ea79e8ff2de2d02698b486671aee7cfda860e) -- Changes requested by @mattwr18 [`9c08db2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9c08db22dcd0ca1ad6e59be8fb0f287935b45537) -- search specs refactored [`46fca22`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/46fca229ec35047eda9ac7809e7bc456785a6c70) #### [v0.4.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.4.1...v0.4.2) @@ -1667,9 +1617,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps): bump metascraper-description from 5.11.1 to 5.11.6 in /backend [`#3233`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3233) - build(deps): bump cross-env from 7.0.1 to 7.0.2 in /backend [`#3245`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3245) - build(deps): bump metascraper-title from 5.11.1 to 5.11.6 in /backend [`#3244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3244) -- DRY user.spec.js [`da16590`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/da165906e2ed12baddd902b43064103ab3adfa06) -- test deleteuser as admin, moderator, another user and as I myself, fix lint [`3983612`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3983612c56ac92473a192a318959e4c691a3e7b8) -- feature: test delete user as admin [`84c1547`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/84c154798efac0cec4c13dfefae18a6a9542058a) #### [v0.4.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.4.0...v0.4.1) @@ -1744,9 +1691,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps): bump sanitize-html from 1.21.1 to 1.22.0 in /backend [`#3145`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3145) - build(deps): bump nodemailer from 6.4.2 to 6.4.3 in /backend [`#3144`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3144) - build(deps): bump metascraper-video from 5.10.7 to 5.11.1 in /backend [`#3143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3143) -- build(deps-dev): bump @storybook/addon-notes in /webapp [`5ef2b25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5ef2b25ee6a3402a2ebe2f3f55dd65a6e0a1111e) -- build(deps-dev): bump @storybook/addon-a11y in /webapp [`f209436`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f209436147fbf9afacfbd6edb6135847e6c4faed) -- Lokalise: update of webapp/locales/fr.json [`28e2967`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/28e2967119f1b47752afc959a4c3ae741fdad0b0) #### [v0.4.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.3.1...v0.4.0) @@ -1811,9 +1755,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix: Increase body parser limit [`#3037`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3037) - chore: Update to v0.3.1 [`#3035`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3035) - fix(subscriptions): Don't publish undefined [`#3088`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/3088) -- Upgrade cypress, remove log out step [`0df4038`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/0df40386dd866c6b9ce540b966dfe00089507d31) -- use BaseCard in Comment component and refactor [`e7bf499`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/e7bf499d373ec9d5d46be20fd838fbc4dbecb273) -- Refactor GQL and tests, first approach [`f380915`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f380915b2c679d42e5db136ea1d923cf00bbcf10) #### [v0.3.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.3.0...v0.3.1) @@ -1866,9 +1807,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix: Remove github release script breaking build [`#2971`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2971) - Use original createdAt for merged users/emails [`#2969`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2969) - Fix typo [`#2966`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2966) -- Get rid of different factory files [`fc36729`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fc367297e3e054f09b7f8f31788ab68d87f6babf) -- Refactor factory for comments [`2fc71d7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2fc71d75a5d5eab9c3467e94e00257ef6dd7d8a0) -- Refactor user factory [`2a79c53`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2a79c53765b73f9b91691eb75f55cf8c9e48306e) #### [v0.3.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.2.2...v0.3.0) @@ -1940,9 +1878,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - docs(deployment): Explain how to setup metrics [`#2825`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2825) - refactor(styleguide): Migrate Avatar component to monorepo [`#2700`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2700) - docs(deployment): Explain how to setup metrics (#2825) [`#2411`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2411) [`#2777`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2777) -- Improve styling per @alina-beck review [`bcc1ab1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/bcc1ab167e8b1dfdac1ec0a05a0c14e8234bcabc) -- test(cypress): Cover "Pinned post" feature [`d49afc2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d49afc25cfa1c1f98ed04f78dd3ff826cd85ae25) -- build(deps-dev): bump @storybook/addon-notes in /webapp [`d6b78e4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d6b78e4794ac60dee9d9fd3e3c9c53a95fcea152) #### [0.2.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.2.2...0.2.2) @@ -1965,9 +1900,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps): bump @hapi/joi from 17.0.2 to 17.1.0 in /backend [`#2846`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2846) - Release 0.2.2 [`#2844`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2844) - build(deps-dev): bump @storybook/addon-actions in /webapp [`#2842`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2842) -- Convert block/unblock to blacklist/whitelist [`c297b83`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/c297b83f873edc61ddec370633b9b65896c56591) -- Rename blacklist/whitelist to mute/unmute [`ba3e9e1`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ba3e9e1025bf432151c9bf1002045179b338ff7f) -- Generate changelog with auto-changelog [`02367f9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/02367f93e0ad635d5f43adf01695f85f06f4c0d2) #### [v0.2.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.2.1...v0.2.2) @@ -1976,7 +1908,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - build(deps): bump metascraper-title from 5.10.3 to 5.10.5 in /backend [`#2835`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2835) - build(deps): bump metascraper-publisher in /backend [`#2836`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2836) - build(deps): bump metascraper-audio from 5.10.3 to 5.10.5 in /backend [`#2840`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2840) -- chore(release): 0.2.2 [`7e26e56`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/7e26e56654d391b0f910a59e28ce67fd1ec0b4a8) #### [0.2.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/v0.2.1...0.2.1) @@ -2071,9 +2002,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - refactor(modules): Various import fixes [`#2773`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2773) [`#2774`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2774) - feat(webapp): Display deployed version in footer [`#1831`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1831) - fix #2229 [`#2229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2229) -- build(deps-dev): bump @storybook/addon-actions in /webapp [`d0124bf`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d0124bf2b4b4a641c9af76d6d2f7b5aa075ade90) -- refactor and use base-button in SearchableInput [`fcbe612`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fcbe6125f35c0dd23e2ba1ae63f539f5ef5990ea) -- manage button states and color schemes with mixin [`1b9249c`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/1b9249c685e34eb2e94b31ee0ec22421c6aa6a73) #### [v0.2.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.2.0...v0.2.1) @@ -2717,9 +2645,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat(webapp): Display deployed version in footer [`#1831`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1831) - fix #2229 [`#2229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2229) - fixes #2659 [`#2659`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2659) -- locales sorted. [`fa906ef`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fa906efb1f40dc5bd80c9678f33c7b607a320099) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) #### [v0.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.13...v0.2.0) @@ -3417,9 +3342,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat(webapp): Display deployed version in footer [`#1831`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1831) - fix #2229 [`#2229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2229) - fixes #2659 [`#2659`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2659) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) -- fix lint: tests and lint ok [`d2a43ce`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d2a43cecd74ee3bec291109a85ddb6986315763b) #### [v0.1.13](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.12...v0.1.13) @@ -4138,9 +4060,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - feat(webapp): Display deployed version in footer [`#1831`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1831) - fix #2229 [`#2229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2229) - fixes #2659 [`#2659`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2659) -- Get rid of different factory files [`fc36729`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fc367297e3e054f09b7f8f31788ab68d87f6babf) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- Refactor factory for comments [`2fc71d7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/2fc71d75a5d5eab9c3467e94e00257ef6dd7d8a0) #### [v0.1.12](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.11...v0.1.12) @@ -4968,9 +4887,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Merge pull request #2443 from Human-Connection/2237-longer-comments [`#2237`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2237) - fix #2329: Normalize email on login in the backend [`#2329`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2329) - Fix #2294 [`#2294`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2294) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.11](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.10...v0.1.11) @@ -5849,9 +5765,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2294 [`#2294`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2294) - Merge pull request #2078 from Human-Connection/fix-2042-back-link [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) -- locales sorted. [`fa906ef`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fa906efb1f40dc5bd80c9678f33c7b607a320099) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.10](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.9...v0.1.10) @@ -6783,9 +6696,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2294 [`#2294`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2294) - Merge pull request #2078 from Human-Connection/fix-2042-back-link [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.9](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.8...v0.1.9) @@ -7774,9 +7684,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.8](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.7...v0.1.8) @@ -8779,9 +8686,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.7](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.6...v0.1.7) @@ -9792,9 +9696,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.6](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.5...v0.1.6) @@ -10831,9 +10732,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- locales sorted. [`fa906ef`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fa906efb1f40dc5bd80c9678f33c7b607a320099) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- Get rid of different factory files [`fc36729`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/fc367297e3e054f09b7f8f31788ab68d87f6babf) #### [v0.1.5](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.4...v0.1.5) @@ -11920,9 +11818,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) -- fix lint: tests and lint ok [`d2a43ce`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d2a43cecd74ee3bec291109a85ddb6986315763b) #### [v0.1.4](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.3...v0.1.4) @@ -13039,9 +12934,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- remove package-lock.json [`3cf3c31`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3cf3c31808dc6ae59fb9c6ec33e9e178c5556438) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.3](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.2...v0.1.3) @@ -14170,9 +14062,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- remove package-lock.json [`3cf3c31`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3cf3c31808dc6ae59fb9c6ec33e9e178c5556438) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### [v0.1.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.1...v0.1.2) @@ -15352,9 +15241,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Fix #2042 Back Link To Login Page [`#2042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/2042) - Merge pull request #2043 from Human-Connection/fix-1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) - fix #1993 [`#1993`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1993) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) -- fix lint: tests and lint ok [`d2a43ce`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d2a43cecd74ee3bec291109a85ddb6986315763b) #### [v0.1.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/0.1.0...v0.1.1) @@ -16600,9 +16486,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Merge pull request #1641 from Human-Connection/1639_no_limits_for_post_length [`#1639`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1639) - Fix #1639 [`#1639`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1639) - Add slug to User component, fix #1486 [`#1486`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/1486) -- sorting locations files yarn run locales --fix [`3343e14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3343e1435f320e1d403e16f5d4563aa11cae49a9) -- tests user.spec.js tests once clean once broken always alternating [`9d5c192`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/9d5c192869ec0b088fa071d827b27cf6ca442b78) -- test check test WIP [`a4be3f7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a4be3f7adfc36ba7517a0f5399606b1f3d3dccfe) #### v0.1.0 @@ -17741,6 +17624,3 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Merge pull request #104 from DakshMiglani/master [`#41`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/41) - Merge pull request #93 from Gerald1614/500_error_on_login [`#49`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/49) - Update schema.graphql [`#7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/7) -- Fix resolve function returns undefind [`657a5ac`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/657a5ac1f59861a205ddfc21bc72ff3801c8fad0) -- Change strategy, only build docker image [`d6b7374`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/d6b7374ddbf497bdb5cbc935b88ae085c38b3237) -- Copy package.json from webapp/ [`f3a9996`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/f3a9996962e5dd8b2e365a032c1a5766fe666103) diff --git a/backend/package.json b/backend/package.json index 3362fe598..c086b5649 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social-backend", - "version": "3.2.1", + "version": "3.3.0", "description": "GraphQL Backend for ocelot.social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", diff --git a/deployment/helm/charts/ocelot-neo4j/Chart.yaml b/deployment/helm/charts/ocelot-neo4j/Chart.yaml index f8a6c88f1..83fb561dc 100644 --- a/deployment/helm/charts/ocelot-neo4j/Chart.yaml +++ b/deployment/helm/charts/ocelot-neo4j/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "3.2.0" +appVersion: "3.3.0" diff --git a/deployment/helm/charts/ocelot-social/Chart.yaml b/deployment/helm/charts/ocelot-social/Chart.yaml index c363a90cb..d15c18a4a 100644 --- a/deployment/helm/charts/ocelot-social/Chart.yaml +++ b/deployment/helm/charts/ocelot-social/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "3.2.0" +appVersion: "3.3.0" diff --git a/frontend/package.json b/frontend/package.json index f032f0d0c..b4e46da30 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social-frontend", - "version": "3.2.1", + "version": "3.3.0", "description": "ocelot.social new Frontend (in development and not fully implemented) by IT4C Boilerplate for frontends", "main": "build/index.js", "type": "module", diff --git a/package.json b/package.json index dd27c53ca..cc97c0399 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social", - "version": "3.2.1", + "version": "3.3.0", "description": "Free and open source software program code available to run social networks.", "author": "ocelot.social Community", "license": "MIT", diff --git a/webapp/maintenance/source/package.json b/webapp/maintenance/source/package.json index 2c5b898b6..1aa029eb4 100644 --- a/webapp/maintenance/source/package.json +++ b/webapp/maintenance/source/package.json @@ -1,6 +1,6 @@ { "name": "@ocelot-social/maintenance", - "version": "3.2.1", + "version": "3.3.0", "description": "Maintenance page for ocelot.social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", diff --git a/webapp/package.json b/webapp/package.json index f1c3778d0..65764aba6 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social-webapp", - "version": "3.2.1", + "version": "3.3.0", "description": "ocelot.social Frontend", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", From 4f375c3f763e82ddc162a2a62c71691d97e74b1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 19:18:17 +0000 Subject: [PATCH 13/18] build(deps-dev): bump @types/node from 22.14.0 to 22.14.1 in /backend (#8374) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.14.0 to 22.14.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 22.14.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- backend/package.json | 2 +- backend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/package.json b/backend/package.json index c086b5649..486c69882 100644 --- a/backend/package.json +++ b/backend/package.json @@ -102,7 +102,7 @@ "@eslint-community/eslint-plugin-eslint-comments": "^4.4.1", "@faker-js/faker": "9.6.0", "@types/jest": "^29.5.14", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "apollo-server-testing": "~2.11.0", diff --git a/backend/yarn.lock b/backend/yarn.lock index 3588f5f26..6ee73bd0b 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -2079,10 +2079,10 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@>=6", "@types/node@^22.14.0": - version "22.14.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e" - integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA== +"@types/node@*", "@types/node@>=6", "@types/node@^22.14.1": + version "22.14.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.1.tgz#53b54585cec81c21eee3697521e31312d6ca1e6f" + integrity sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw== dependencies: undici-types "~6.21.0" From 7b8fdbebbe9b6e99d85104d5616848773db8c741 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 20:20:01 +0000 Subject: [PATCH 14/18] build(deps-dev): bump eslint-config-prettier in /webapp (#8377) Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 10.1.1 to 10.1.2. - [Release notes](https://github.com/prettier/eslint-config-prettier/releases) - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.1.1...v10.1.2) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-version: 10.1.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- webapp/package.json | 2 +- webapp/yarn.lock | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index 65764aba6..0f3371b95 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -95,7 +95,7 @@ "core-js": "~2.6.10", "css-loader": "~3.5.2", "eslint": "^7.28.0", - "eslint-config-prettier": "~10.1.1", + "eslint-config-prettier": "~10.1.2", "eslint-config-standard": "~15.0.1", "eslint-loader": "~4.0.0", "eslint-plugin-import": "~2.31.0", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 55c62a3ca..6295a5bc0 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -9615,10 +9615,10 @@ eslint-config-prettier@^6.0.0: dependencies: get-stdin "^6.0.0" -eslint-config-prettier@~10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz#cf0ff6e5c4e7e15f129f1f1ce2a5ecba92dec132" - integrity sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw== +eslint-config-prettier@~10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz#31a4b393c40c4180202c27e829af43323bf85276" + integrity sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA== eslint-config-standard@~15.0.1: version "15.0.1" @@ -18637,7 +18637,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18690,6 +18690,15 @@ string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -18749,7 +18758,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18784,6 +18793,13 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -20852,7 +20868,7 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20904,6 +20920,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 63cd1d36b185605eeec3c2d0b9231a7c0dc65ac7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 20:55:41 +0000 Subject: [PATCH 15/18] build(deps): bump dotenv from 16.4.7 to 16.5.0 in /backend (#8372) Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.4.7 to 16.5.0. - [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) - [Commits](https://github.com/motdotla/dotenv/compare/v16.4.7...v16.5.0) --- updated-dependencies: - dependency-name: dotenv dependency-version: 16.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- backend/package.json | 2 +- backend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/package.json b/backend/package.json index 486c69882..1422b0cc3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -47,7 +47,7 @@ "cheerio": "~1.0.0", "cors": "~2.8.5", "cross-env": "~7.0.3", - "dotenv": "~16.4.7", + "dotenv": "~16.5.0", "express": "^5.1.0", "graphql": "^14.6.0", "graphql-middleware": "~4.0.2", diff --git a/backend/yarn.lock b/backend/yarn.lock index 6ee73bd0b..80449c983 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -4137,10 +4137,10 @@ domutils@^3.0.1, domutils@^3.1.0: domelementtype "^2.3.0" domhandler "^5.0.3" -dotenv@^16.0.0, dotenv@~16.4.7: - version "16.4.7" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" - integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== +dotenv@^16.0.0, dotenv@~16.5.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" + integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== dotenv@^4.0.0: version "4.0.0" From 25552431b552ab545b28dbf859f821a3c4248eda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Apr 2025 09:03:41 +0000 Subject: [PATCH 16/18] build(deps): bump ioredis from 4.16.1 to 5.6.1 in /backend (#8371) Bumps [ioredis](https://github.com/luin/ioredis) from 4.16.1 to 5.6.1. - [Release notes](https://github.com/luin/ioredis/releases) - [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md) - [Commits](https://github.com/luin/ioredis/compare/v4.16.1...v5.6.1) --- updated-dependencies: - dependency-name: ioredis dependency-version: 5.6.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- backend/package.json | 2 +- backend/yarn.lock | 43 ++++--------------------------------------- 2 files changed, 5 insertions(+), 40 deletions(-) diff --git a/backend/package.json b/backend/package.json index 1422b0cc3..fa70e41bb 100644 --- a/backend/package.json +++ b/backend/package.json @@ -58,7 +58,7 @@ "graphql-tag": "~2.10.3", "graphql-upload": "^11.0.0", "helmet": "~8.1.0", - "ioredis": "^4.16.1", + "ioredis": "^5.6.1", "jsonwebtoken": "~8.5.1", "languagedetect": "^2.0.0", "linkify-html": "^4.2.0", diff --git a/backend/yarn.lock b/backend/yarn.lock index 80449c983..745e06694 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3999,11 +3999,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -denque@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" - integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== - denque@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" @@ -6027,25 +6022,10 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" -ioredis@^4.16.1: - version "4.16.1" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.16.1.tgz#377c21d2a4fa8cc31fe9028c666f8dd16a6255bf" - integrity sha512-g76Mm9dE7BLuewncu1MimGZw5gDDjDwjoRony/VoSxSJEKAhuYncDEwYKYjtHi2NWsTNIB6XXRjE64uVa/wpKQ== - dependencies: - cluster-key-slot "^1.1.0" - debug "^4.1.1" - denque "^1.1.0" - lodash.defaults "^4.2.0" - lodash.flatten "^4.4.0" - redis-commands "1.5.0" - redis-errors "^1.2.0" - redis-parser "^3.0.0" - standard-as-callback "^2.0.1" - -ioredis@^5.3.2: - version "5.4.2" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.4.2.tgz#ebb6f1a10b825b2c0fb114763d7e82114a0bee6c" - integrity sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg== +ioredis@^5.3.2, ioredis@^5.6.1: + version "5.6.1" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.6.1.tgz#1ed7dc9131081e77342503425afceaf7357ae599" + integrity sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA== dependencies: "@ioredis/commands" "^1.1.1" cluster-key-slot "^1.1.0" @@ -7129,11 +7109,6 @@ lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= -lodash.flatten@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -8604,11 +8579,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -redis-commands@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" - integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== - redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" @@ -9318,11 +9288,6 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" -standard-as-callback@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.0.1.tgz#ed8bb25648e15831759b6023bdb87e6b60b38126" - integrity sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg== - standard-as-callback@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" From d34798a9d9f0df61034a02c3fef0565d18ee1a69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Apr 2025 14:20:50 +0200 Subject: [PATCH 17/18] build(deps-dev): bump dotenv from 16.4.7 to 16.5.0 (#8367) Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.4.7 to 16.5.0. - [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) - [Commits](https://github.com/motdotla/dotenv/compare/v16.4.7...v16.5.0) --- updated-dependencies: - dependency-name: dotenv dependency-version: 16.5.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 13 +++++++------ package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b708bace..a74a341c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ocelot-social", - "version": "3.2.1", + "version": "3.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ocelot-social", - "version": "3.2.1", + "version": "3.3.0", "license": "MIT", "devDependencies": { "@babel/core": "^7.26.10", @@ -22,7 +22,7 @@ "cypress": "^14.2.1", "cypress-network-idle": "^1.15.0", "date-fns": "^3.6.0", - "dotenv": "^16.4.7", + "dotenv": "^16.5.0", "expect": "^29.6.4", "graphql-request": "^2.0.0", "import": "^0.0.6", @@ -8477,10 +8477,11 @@ } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, diff --git a/package.json b/package.json index cc97c0399..eaaa1e748 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "cypress": "^14.2.1", "cypress-network-idle": "^1.15.0", "date-fns": "^3.6.0", - "dotenv": "^16.4.7", + "dotenv": "^16.5.0", "expect": "^29.6.4", "graphql-request": "^2.0.0", "import": "^0.0.6", diff --git a/yarn.lock b/yarn.lock index 4e1450d9a..67f3c5d61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4445,10 +4445,10 @@ domutils@^3.0.1, domutils@^3.1.0: domelementtype "^2.3.0" domhandler "^5.0.3" -dotenv@^16.4.7: - version "16.4.7" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" - integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== +dotenv@^16.5.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" + integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== dotenv@^4.0.0: version "4.0.0" From af5f506d223a786bad402375a24a08c5841e4f9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Apr 2025 12:49:18 +0000 Subject: [PATCH 18/18] build(deps-dev): bump eslint-import-resolver-typescript in /backend (#8369) Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 4.3.1 to 4.3.2. - [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases) - [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md) - [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v4.3.1...v4.3.2) --- updated-dependencies: - dependency-name: eslint-import-resolver-typescript dependency-version: 4.3.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- backend/package.json | 2 +- backend/yarn.lock | 178 ++++++++++++++++++++++--------------------- 2 files changed, 93 insertions(+), 87 deletions(-) diff --git a/backend/package.json b/backend/package.json index fa70e41bb..516d763ec 100644 --- a/backend/package.json +++ b/backend/package.json @@ -109,7 +109,7 @@ "eslint": "^8.57.1", "eslint-config-prettier": "^10.1.1", "eslint-config-standard": "^17.1.0", - "eslint-import-resolver-typescript": "^4.3.1", + "eslint-import-resolver-typescript": "^4.3.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-n": "^17.17.0", diff --git a/backend/yarn.lock b/backend/yarn.lock index 745e06694..628eea48d 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1579,7 +1579,7 @@ url-regex "~4.1.1" video-extensions "~1.1.0" -"@napi-rs/wasm-runtime@^0.2.7": +"@napi-rs/wasm-runtime@^0.2.8": version "0.2.8" resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.8.tgz#642e8390ee78ed21d6b79c467aa610e249224ed6" integrity sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg== @@ -2289,82 +2289,87 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@unrs/resolver-binding-darwin-arm64@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.3.3.tgz#394065916f98cdc1897cf7234adfdee395725fa8" - integrity sha512-EpRILdWr3/xDa/7MoyfO7JuBIJqpBMphtu4+80BK1bRfFcniVT74h3Z7q1+WOc92FuIAYatB1vn9TJR67sORGw== +"@unrs/resolver-binding-darwin-arm64@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.5.0.tgz#0c64ebe422a3d05ada91d8ba84e037383742c955" + integrity sha512-YmocNlEcX/AgJv8gI41bhjMOTcKcea4D2nRIbZj+MhRtSH5+vEU8r/pFuTuoF+JjVplLsBueU+CILfBPVISyGQ== -"@unrs/resolver-binding-darwin-x64@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.3.3.tgz#6a3c75ca984342261c7346db53293b0002e8cde1" - integrity sha512-ntj/g7lPyqwinMJWZ+DKHBse8HhVxswGTmNgFKJtdgGub3M3zp5BSZ3bvMP+kBT6dnYJLSVlDqdwOq1P8i0+/g== +"@unrs/resolver-binding-darwin-x64@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.5.0.tgz#57210874eca22ec3a07039c97c028fb19c0c6d57" + integrity sha512-qpUrXgH4e/0xu1LOhPEdfgSY3vIXOxDQv370NEL8npN8h40HcQDA+Pl2r4HBW6tTXezWIjxUFcP7tj529RZtDw== -"@unrs/resolver-binding-freebsd-x64@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.3.3.tgz#6532b8d4fecaca6c4424791c82f7a27aac94fcd5" - integrity sha512-l6BT8f2CU821EW7U8hSUK8XPq4bmyTlt9Mn4ERrfjJNoCw0/JoHAh9amZZtV3cwC3bwwIat+GUnrcHTG9+qixw== +"@unrs/resolver-binding-freebsd-x64@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.5.0.tgz#4519371d0ad8e557a86623d8497e3abcdcb5ae43" + integrity sha512-3tX8r8vgjvZzaJZB4jvxUaaFCDCb3aWDCpZN3EjhGnnwhztslI05KSG5NY/jNjlcZ5QWZ7dEZZ/rNBFsmTaSPw== -"@unrs/resolver-binding-linux-arm-gnueabihf@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.3.3.tgz#69a8e430095fcf6a76f7350cc27b83464f8cbb91" - integrity sha512-8ScEc5a4y7oE2BonRvzJ+2GSkBaYWyh0/Ko4Q25e/ix6ANpJNhwEPZvCR6GVRmsQAYMIfQvYLdM6YEN+qRjnAQ== +"@unrs/resolver-binding-linux-arm-gnueabihf@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.5.0.tgz#4fc05aec9e65a6478003a0b9034a06ac0da886ab" + integrity sha512-FH+ixzBKaUU9fWOj3TYO+Yn/eO6kYvMLV9eNJlJlkU7OgrxkCmiMS6wUbyT0KA3FOZGxnEQ2z3/BHgYm2jqeLA== -"@unrs/resolver-binding-linux-arm-musleabihf@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.3.3.tgz#e1fc8440e54929b1f0f6aff6f6e3e9e19ac4a73c" - integrity sha512-8qQ6l1VTzLNd3xb2IEXISOKwMGXDCzY/UNy/7SovFW2Sp0K3YbL7Ao7R18v6SQkLqQlhhqSBIFRk+u6+qu5R5A== +"@unrs/resolver-binding-linux-arm-musleabihf@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.5.0.tgz#c24b35dd5818fcd25569425b1dc1a98a883e248b" + integrity sha512-pxCgXMgwB/4PfqFQg73lMhmWwcC0j5L+dNXhZoz/0ek0iS/oAWl65fxZeT/OnU7fVs52MgdP2q02EipqJJXHSg== -"@unrs/resolver-binding-linux-arm64-gnu@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.3.3.tgz#1249e18b5fa1419addda637d62ef201ce9bcf5a4" - integrity sha512-v81R2wjqcWXJlQY23byqYHt9221h4anQ6wwN64oMD/WAE+FmxPHFZee5bhRkNVtzqO/q7wki33VFWlhiADwUeQ== +"@unrs/resolver-binding-linux-arm64-gnu@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.5.0.tgz#07dc8478a0a356d343790208dc557d6d053689af" + integrity sha512-FX2FV7vpLE/+Z0NZX9/1pwWud5Wocm/2PgpUXbT5aSV3QEB10kBPJAzssOQylvdj8mOHoKl5pVkXpbCwww/T2g== -"@unrs/resolver-binding-linux-arm64-musl@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.3.3.tgz#9af549ce9dde57b31c32a36cbe9eafa05f96befd" - integrity sha512-cAOx/j0u5coMg4oct/BwMzvWJdVciVauUvsd+GQB/1FZYKQZmqPy0EjJzJGbVzFc6gbnfEcSqvQE6gvbGf2N8Q== +"@unrs/resolver-binding-linux-arm64-musl@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.5.0.tgz#169e531731f7e462dffa410034a1d06a7a921aa8" + integrity sha512-+gF97xst1BZb28T3nwwzEtq2ewCoMDGKsenYsZuvpmNrW0019G1iUAunZN+FG55L21y+uP7zsGX06OXDQ/viKw== -"@unrs/resolver-binding-linux-ppc64-gnu@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.3.3.tgz#45aab52319f3e3b2627038a80c0331b0793a4be3" - integrity sha512-mq2blqwErgDJD4gtFDlTX/HZ7lNP8YCHYFij2gkXPtMzrXxPW1hOtxL6xg4NWxvnj4bppppb0W3s/buvM55yfg== +"@unrs/resolver-binding-linux-ppc64-gnu@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.5.0.tgz#f6ad2ff47d74c8158b28a18536a71a8ecf84a17f" + integrity sha512-5bEmVcQw9js8JYM2LkUBw5SeELSIxX+qKf9bFrfFINKAp4noZ//hUxLpbF7u/3gTBN1GsER6xOzIZlw/VTdXtA== -"@unrs/resolver-binding-linux-s390x-gnu@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.3.3.tgz#7d2fe5c43e291d42e66d74fce07d9cf0050b4241" - integrity sha512-u0VRzfFYysarYHnztj2k2xr+eu9rmgoTUUgCCIT37Nr+j0A05Xk2c3RY8Mh5+DhCl2aYibihnaAEJHeR0UOFIQ== +"@unrs/resolver-binding-linux-riscv64-gnu@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.5.0.tgz#2f3986cb44f285f90d27e87cee8b4059de3ffbdd" + integrity sha512-GGk/8TPUsf1Q99F+lzMdjE6sGL26uJCwQ9TlvBs8zR3cLQNw/MIumPN7zrs3GFGySjnwXc8gA6J3HKbejywmqA== -"@unrs/resolver-binding-linux-x64-gnu@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.3.3.tgz#be54ff88c581610c42d8614475c0560f043d7ded" - integrity sha512-OrVo5ZsG29kBF0Ug95a2KidS16PqAMmQNozM6InbquOfW/udouk063e25JVLqIBhHLB2WyBnixOQ19tmeC/hIg== +"@unrs/resolver-binding-linux-s390x-gnu@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.5.0.tgz#813ea07833012bc34ecc59f023e422b421138761" + integrity sha512-5uRkFYYVNAeVaA4W/CwugjFN3iDOHCPqsBLCCOoJiMfFMMz4evBRsg+498OFa9w6VcTn2bD5aI+RRayaIgk2Sw== -"@unrs/resolver-binding-linux-x64-musl@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.3.3.tgz#4efa7a1e4f7bf231098ed23df1e19174d360c24f" - integrity sha512-PYnmrwZ4HMp9SkrOhqPghY/aoL+Rtd4CQbr93GlrRTjK6kDzfMfgz3UH3jt6elrQAfupa1qyr1uXzeVmoEAxUA== +"@unrs/resolver-binding-linux-x64-gnu@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.5.0.tgz#18b0d7553268fa490db92be578ac4b0fd8cae049" + integrity sha512-j905CZH3nehYy6NimNqC2B14pxn4Ltd7guKMyPTzKehbFXTUgihQS/ZfHQTdojkMzbSwBOSgq1dOrY+IpgxDsA== -"@unrs/resolver-binding-wasm32-wasi@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.3.3.tgz#6df454b4a9b28d47850bcb665d243f09101b782c" - integrity sha512-81AnQY6fShmktQw4hWDUIilsKSdvr/acdJ5azAreu2IWNlaJOKphJSsUVWE+yCk6kBMoQyG9ZHCb/krb5K0PEA== +"@unrs/resolver-binding-linux-x64-musl@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.5.0.tgz#04541e98d16e358c695393251e365bc3d802dfa4" + integrity sha512-dmLevQTuzQRwu5A+mvj54R5aye5I4PVKiWqGxg8tTaYP2k2oTs/3Mo8mgnhPk28VoYCi0fdFYpgzCd4AJndQvQ== + +"@unrs/resolver-binding-wasm32-wasi@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.5.0.tgz#7a2ae7467c4c52d53c20ad7fc2bace1b23de8168" + integrity sha512-LtJMhwu7avhoi+kKfAZOKN773RtzLBVVF90YJbB0wyMpUj9yQPeA+mteVUI9P70OG/opH47FeV5AWeaNWWgqJg== dependencies: - "@napi-rs/wasm-runtime" "^0.2.7" + "@napi-rs/wasm-runtime" "^0.2.8" -"@unrs/resolver-binding-win32-arm64-msvc@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.3.3.tgz#fb19e118350e1392993a0a6565b427d38c1c1760" - integrity sha512-X/42BMNw7cW6xrB9syuP5RusRnWGoq+IqvJO8IDpp/BZg64J1uuIW6qA/1Cl13Y4LyLXbJVYbYNSKwR/FiHEng== +"@unrs/resolver-binding-win32-arm64-msvc@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.5.0.tgz#11deb282b8ce73fab26f1d04df0fa4d6363752c2" + integrity sha512-FTZBxLL4SO1mgIM86KykzJmPeTPisBDHQV6xtfDXbTMrentuZ6SdQKJUV5BWaoUK3p8kIULlrCcucqdCnk8Npg== -"@unrs/resolver-binding-win32-ia32-msvc@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.3.3.tgz#23a9c4b5621bba2d472bc78fadde7273a8c4548d" - integrity sha512-EGNnNGQxMU5aTN7js3ETYvuw882zcO+dsVjs+DwO2j/fRVKth87C8e2GzxW1L3+iWAXMyJhvFBKRavk9Og1Z6A== +"@unrs/resolver-binding-win32-ia32-msvc@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.5.0.tgz#2a5d414912379425bd395ea15901a5dd5febc7c1" + integrity sha512-i5bB7vJ1waUsFciU/FKLd4Zw0VnAkvhiJ4//jYQXyDUuiLKodmtQZVTcOPU7pp97RrNgCFtXfC1gnvj/DHPJTw== -"@unrs/resolver-binding-win32-x64-msvc@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.3.3.tgz#eee226e5b4c4d91c862248afd24452c8698ed542" - integrity sha512-GraLbYqOJcmW1qY3osB+2YIiD62nVf2/bVLHZmrb4t/YSUwE03l7TwcDJl08T/Tm3SVhepX8RQkpzWbag/Sb4w== +"@unrs/resolver-binding-win32-x64-msvc@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.5.0.tgz#5768c6bba4a27833a48a8a77e50eb01b520d0962" + integrity sha512-wAvXp4k7jhioi4SebXW/yfzzYwsUCr9kIX4gCsUFKpCTUf8Mi7vScJXI3S+kupSUf0LbVHudR8qBbe2wFMSNUw== "@wry/context@^0.4.0": version "0.4.4" @@ -4595,17 +4600,17 @@ eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" -eslint-import-resolver-typescript@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.1.tgz#6721c639716de3685363ddb284e2cec60cee60ee" - integrity sha512-/dR9YMomeBlvfuvX5q0C3Y/2PHC9OCRdT2ijFwdfq/4Bq+4m5/lqstEp9k3P6ocha1pCbhoY9fkwVYLmOqR0VQ== +eslint-import-resolver-typescript@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.2.tgz#1d2371be6d073bade177ee04a4548dbacdc334c0" + integrity sha512-T2LqBXj87ndEC9t1LrDiPkzalSFzD4rrXr6BTzGdgMx1jdQM4T972guQvg7Ih+LNO51GURXI/qMHS5GF3h1ilw== dependencies: debug "^4.4.0" get-tsconfig "^4.10.0" is-bun-module "^2.0.0" stable-hash "^0.0.5" tinyglobby "^0.2.12" - unrs-resolver "^1.3.3" + unrs-resolver "^1.4.1" eslint-module-utils@^2.12.0: version "2.12.0" @@ -10050,26 +10055,27 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unrs-resolver@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.3.3.tgz#46bd5dd2ecc650365e050055fc208b5f4ae57803" - integrity sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A== +unrs-resolver@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.5.0.tgz#d0a608f08321d8e90ba8eb10a3240e7995997275" + integrity sha512-6aia3Oy7SEe0MuUGQm2nsyob0L2+g57w178K5SE/3pvSGAIp28BB2O921fKx424Ahc/gQ6v0DXFbhcpyhGZdOA== optionalDependencies: - "@unrs/resolver-binding-darwin-arm64" "1.3.3" - "@unrs/resolver-binding-darwin-x64" "1.3.3" - "@unrs/resolver-binding-freebsd-x64" "1.3.3" - "@unrs/resolver-binding-linux-arm-gnueabihf" "1.3.3" - "@unrs/resolver-binding-linux-arm-musleabihf" "1.3.3" - "@unrs/resolver-binding-linux-arm64-gnu" "1.3.3" - "@unrs/resolver-binding-linux-arm64-musl" "1.3.3" - "@unrs/resolver-binding-linux-ppc64-gnu" "1.3.3" - "@unrs/resolver-binding-linux-s390x-gnu" "1.3.3" - "@unrs/resolver-binding-linux-x64-gnu" "1.3.3" - "@unrs/resolver-binding-linux-x64-musl" "1.3.3" - "@unrs/resolver-binding-wasm32-wasi" "1.3.3" - "@unrs/resolver-binding-win32-arm64-msvc" "1.3.3" - "@unrs/resolver-binding-win32-ia32-msvc" "1.3.3" - "@unrs/resolver-binding-win32-x64-msvc" "1.3.3" + "@unrs/resolver-binding-darwin-arm64" "1.5.0" + "@unrs/resolver-binding-darwin-x64" "1.5.0" + "@unrs/resolver-binding-freebsd-x64" "1.5.0" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.5.0" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.5.0" + "@unrs/resolver-binding-linux-arm64-gnu" "1.5.0" + "@unrs/resolver-binding-linux-arm64-musl" "1.5.0" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.5.0" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.5.0" + "@unrs/resolver-binding-linux-s390x-gnu" "1.5.0" + "@unrs/resolver-binding-linux-x64-gnu" "1.5.0" + "@unrs/resolver-binding-linux-x64-musl" "1.5.0" + "@unrs/resolver-binding-wasm32-wasi" "1.5.0" + "@unrs/resolver-binding-win32-arm64-msvc" "1.5.0" + "@unrs/resolver-binding-win32-ia32-msvc" "1.5.0" + "@unrs/resolver-binding-win32-x64-msvc" "1.5.0" update-browserslist-db@^1.1.0: version "1.1.0"