diff --git a/backend/src/middleware/handleHtmlContent/handleContentData.js b/backend/src/middleware/handleHtmlContent/handleContentData.js index 53a6b65fb..5fb2ae5cc 100644 --- a/backend/src/middleware/handleHtmlContent/handleContentData.js +++ b/backend/src/middleware/handleHtmlContent/handleContentData.js @@ -1,57 +1,34 @@ import extractMentionedUsers from './notifications/extractMentionedUsers' import extractHashtags from './hashtags/extractHashtags' -const notify = async (resolve, root, args, context, resolveInfo) => { - // extract user ids before xss-middleware removes link classes - const ids = extractMentionedUsers(args.content) - - console.log('ids: ', ids) - - const post = await resolve(root, args, context, resolveInfo) - +const notify = async (postId, idsOfMentionedUsers, context) => { const session = context.driver.session() - const { - id: postId - } = post const createdAt = new Date().toISOString() const cypher = ` - match(u:User) where u.id in $ids + match(u:User) where u.id in $idsOfMentionedUsers match(p:Post) where p.id = $postId create(n:Notification{id: apoc.create.uuid(), read: false, createdAt: $createdAt}) merge (n)-[:NOTIFIED]->(u) merge (p)-[:NOTIFIED]->(n) ` await session.run(cypher, { - ids, + idsOfMentionedUsers, createdAt, postId }) session.close() - - return post } -const updateHashtagsOfPost = async (postId, resolve, root, args, context, resolveInfo) => { - // extract tag (hashtag) ids before xss-middleware removes link classes - const hashtags = extractHashtags(args.content) - - console.log('hashtags: ', hashtags) - - // const post = await resolve(root, args, context, resolveInfo) - +const updateHashtagsOfPost = async (postId, hashtags, context) => { const session = context.driver.session() - // const { - // id: postId - // } = post - // const createdAt = new Date().toISOString() const cypher = ` - MATCH (p:Post { id: $postId })-[oldRelations: TAGGED]->(oldTags: Tag) + MATCH (p:Post { id: $postId })-[oldRelations:TAGGED]->(oldTags:Tag) DELETE oldRelations WITH p UNWIND $hashtags AS tagName - MERGE (t: Tag { id: tagName, name: tagName }) + MERGE (t:Tag { id: tagName, name: tagName, disabled: false, deleted: false }) MERGE (p)-[:TAGGED]->(t) - RETURN t + RETURN p, t ` await session.run(cypher, { postId, @@ -61,10 +38,20 @@ const updateHashtagsOfPost = async (postId, resolve, root, args, context, resolv } const handleContentData = async (resolve, root, args, context, resolveInfo) => { - // extract user ids before xss-middleware removes link classes + console.log('args.content: ', args.content) + // extract user ids before xss-middleware removes classes via the following "resolve" call + const idsOfMentionedUsers = extractMentionedUsers(args.content) + console.log('idsOfMentionedUsers: ', idsOfMentionedUsers) + // extract tag (hashtag) ids before xss-middleware removes classes via the following "resolve" call + const hashtags = extractHashtags(args.content) + console.log('hashtags: ', hashtags) - const post = await notify(resolve, root, args, context, resolveInfo) - await updateHashtagsOfPost(post.id, resolve, root, args, context, resolveInfo) + // removes classes from the content + const post = await resolve(root, args, context, resolveInfo) + + console.log('post.id: ', post.id) + await notify(post.id, idsOfMentionedUsers, context) + await updateHashtagsOfPost(post.id, hashtags, context) return post } diff --git a/backend/src/middleware/handleHtmlContent/notifications/extractMentionedUsers.js b/backend/src/middleware/handleHtmlContent/notifications/extractMentionedUsers.js index c2fcf169c..52016146f 100644 --- a/backend/src/middleware/handleHtmlContent/notifications/extractMentionedUsers.js +++ b/backend/src/middleware/handleHtmlContent/notifications/extractMentionedUsers.js @@ -1,7 +1,7 @@ import cheerio from 'cheerio' const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g -export default function(content) { +export default function (content) { if (!content) return [] const $ = cheerio.load(content) const urls = $('.mention') @@ -11,10 +11,11 @@ export default function(content) { .get() const ids = [] urls.forEach(url => { + console.log('url: ', url) let match while ((match = ID_REGEX.exec(url)) != null) { ids.push(match[1]) } }) return ids -} +} \ No newline at end of file diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js index 833f7116b..219b5b803 100644 --- a/webapp/components/ContributionForm/ContributionForm.spec.js +++ b/webapp/components/ContributionForm/ContributionForm.spec.js @@ -39,7 +39,9 @@ describe('ContributionForm.vue', () => { }, }, }) - .mockRejectedValue({ message: 'Not Authorised!' }), + .mockRejectedValue({ + message: 'Not Authorised!', + }), }, $toast: { error: jest.fn(), @@ -66,12 +68,26 @@ describe('ContributionForm.vue', () => { getters, }) const Wrapper = () => { - return mount(ContributionForm, { mocks, localVue, store, propsData }) + return mount(ContributionForm, { + mocks, + localVue, + store, + propsData, + }) } beforeEach(() => { wrapper = Wrapper() - wrapper.setData({ form: { languageOptions: [{ label: 'Deutsch', value: 'de' }] } }) + wrapper.setData({ + form: { + languageOptions: [ + { + label: 'Deutsch', + value: 'de', + }, + ], + }, + }) }) describe('CreatePost', () => { @@ -100,7 +116,12 @@ describe('ContributionForm.vue', () => { beforeEach(async () => { expectedParams = { mutation: PostMutations().CreatePost, - variables: { title: postTitle, content: postContent, language: 'en', id: null }, + variables: { + title: postTitle, + content: postContent, + language: 'en', + id: null, + }, } postTitleInput = wrapper.find('.ds-input') postTitleInput.setValue(postTitle) @@ -124,25 +145,13 @@ describe('ContributionForm.vue', () => { expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams)) }) - it('supports adding tags', async () => { + it.skip('supports adding tags', async () => { expectedParams.variables.tags = ['Frieden'] - tagsInput = wrapper.findAll('input').at(1) - tagsInput.setValue('Frieden') - tagsInput.trigger('keyup.enter') - await wrapper.find('form').trigger('submit') expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams)) }) - it('displays tags if they exist', () => { + it.skip('displays tags if they exist', () => { expectedParams.variables.tags = ['Frieden'] - tagsInput = wrapper.findAll('input').at(1) - tagsInput.setValue('Frieden') - tagsInput.trigger('keyup.enter') - chipText = wrapper - .findAll('span.ds-chip') - .at(0) - .text() - expect(chipText).toEqual('Frieden') }) it("pushes the user to the post's page", async () => { @@ -210,7 +219,9 @@ describe('ContributionForm.vue', () => { }) it('sets language equal to contribution language', () => { - expect(wrapper.vm.form.language).toEqual({ value: propsData.contribution.language }) + expect(wrapper.vm.form.language).toEqual({ + value: propsData.contribution.language, + }) }) it('calls the UpdatePost apollo mutation', async () => { diff --git a/webapp/components/ContributionForm/index.vue b/webapp/components/ContributionForm/index.vue index 11d6553f8..4e775caaf 100644 --- a/webapp/components/ContributionForm/index.vue +++ b/webapp/components/ContributionForm/index.vue @@ -12,17 +12,6 @@ /> - - - {{ tag }} - @@ -82,8 +71,6 @@ export default { content: '', language: null, languageOptions: [], - tagValue: null, - tags: [], }, formSchema: { title: { required: true, min: 3, max: 64 }, @@ -135,7 +122,6 @@ export default { title: this.form.title, content: this.form.content, language: this.form.language ? this.form.language.value : this.$i18n.locale(), - tags: this.form.tags, }, }) .then(res => { @@ -165,16 +151,6 @@ export default { this.form.languageOptions.push({ label: locale.name, value: locale.code }) }) }, - removeTag(index) { - this.form.tags.splice(index, 1) - }, - handleInput(e) { - this.form.tagValue = e.target ? e.target.value.trim() : '' - }, - addTag(tag) { - this.form.tags.push(tag) - this.form.tagValue = '' - }, }, apollo: { User: { diff --git a/webapp/components/Editor/index.vue b/webapp/components/Editor/index.vue index dbb30a42e..98a5bc3df 100644 --- a/webapp/components/Editor/index.vue +++ b/webapp/components/Editor/index.vue @@ -12,10 +12,19 @@
@{{ item.slug }}
#{{ item.name }}
+
+ {{ $t('editor.hashtag.addHashtag') }} +
{{ $t('editor.mention.noUsersFound') }}
-
{{ $t('editor.hashtag.noHashtagsFound') }}
+
+
{{ $t('editor.hashtag.noHashtagsFound') }}
+
{{ $t('editor.hashtag.addHashtag') }}
+
@@ -271,7 +280,7 @@ export default { } // pressing enter if (event.keyCode === 13) { - this.enterHandler(this.mentionSuggestionType) + this.enterHandler() return true } return false @@ -340,9 +349,14 @@ export default { this.downHandler() return true } - // pressing enter or pressing space - if (event.keyCode === 13 || event.keyCode === 32) { - this.enterHandler(this.hashtagSuggestionType) + // pressing enter + if (event.keyCode === 13) { + this.enterHandler() + return true + } + // pressing space + if (event.keyCode === 32) { + this.spaceHandler() return true } return false @@ -357,7 +371,7 @@ export default { } const fuse = new Fuse(items, { threshold: 0.2, - keys: ['slug'], + keys: ['name'], }) return fuse.search(query) }, @@ -434,13 +448,17 @@ export default { downHandler() { this.navigatedItemIndex = (this.navigatedItemIndex + 1) % this.filteredItems.length }, - // For hashtags handles pressing of space as enter. + // Handles pressing of enter. enterHandler() { const item = this.filteredItems[this.navigatedItemIndex] if (item) { this.selectItem(item) - } else if (this.suggestionType === this.hashtagSuggestionType && this.query !== '') { - this.selectItem({ name: this.query }, this.hashtagSuggestionType) + } + }, + // For hashtags handles pressing of space. + spaceHandler() { + if (this.suggestionType === this.hashtagSuggestionType && this.query !== '') { + this.selectItem({ name: this.query }) } }, // we have to replace our suggestion text with a mention diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 9dbcd0971..c7d19c39a 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -27,7 +27,7 @@ "code": "Code eingeben", "description": "Öffne dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.", "next": "Weiter", - "change-password":{ + "change-password": { "success": "Änderung des Passworts war erfolgreich!", "error": "Passwort Änderung fehlgeschlagen. Möglicherweise falscher Sicherheitscode?", "help": "Falls Probleme auftreten, schreib uns gerne eine Mail an:" @@ -40,7 +40,8 @@ "noUsersFound": "Keine Benutzer gefunden" }, "hashtag": { - "noHashtagsFound": "Keine Hashtags gefunden" + "noHashtagsFound": "Keine Hashtags gefunden", + "addHashtag": "Neuer Hashtag" } }, "profile": { @@ -338,9 +339,7 @@ "filterFollow": "Beiträge filtern von Usern denen ich folge", "filterALL": "Alle Beiträge anzeigen", "success": "Gespeichert!", - "languageSelectLabel": "Sprache", - "tagsInputLabel": "Tags", - "tagsInputPlaceholder": "Hinzufügen ein Tag" + "languageSelectLabel": "Sprache" } } diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 305bc6cc6..cb64c8eb8 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -40,7 +40,8 @@ "noUsersFound": "No users found" }, "hashtag": { - "noHashtagsFound": "No hashtags found" + "noHashtagsFound": "No hashtags found", + "addHashtag": "New hashtag" } }, "profile": { @@ -337,8 +338,6 @@ "filterFollow": "Filter contributions from users I follow", "filterALL": "View all contributions", "success": "Saved!", - "languageSelectLabel": "Language", - "tagsInputLabel": "Tags", - "tagsInputPlaceholder": "Add a tag" + "languageSelectLabel": "Language" } }