mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Refactoring and second approach to change the database
This commit is contained in:
parent
1d1959561b
commit
28e4433b87
@ -1,57 +1,34 @@
|
|||||||
import extractMentionedUsers from './notifications/extractMentionedUsers'
|
import extractMentionedUsers from './notifications/extractMentionedUsers'
|
||||||
import extractHashtags from './hashtags/extractHashtags'
|
import extractHashtags from './hashtags/extractHashtags'
|
||||||
|
|
||||||
const notify = async (resolve, root, args, context, resolveInfo) => {
|
const notify = async (postId, idsOfMentionedUsers, context) => {
|
||||||
// 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 session = context.driver.session()
|
const session = context.driver.session()
|
||||||
const {
|
|
||||||
id: postId
|
|
||||||
} = post
|
|
||||||
const createdAt = new Date().toISOString()
|
const createdAt = new Date().toISOString()
|
||||||
const cypher = `
|
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
|
match(p:Post) where p.id = $postId
|
||||||
create(n:Notification{id: apoc.create.uuid(), read: false, createdAt: $createdAt})
|
create(n:Notification{id: apoc.create.uuid(), read: false, createdAt: $createdAt})
|
||||||
merge (n)-[:NOTIFIED]->(u)
|
merge (n)-[:NOTIFIED]->(u)
|
||||||
merge (p)-[:NOTIFIED]->(n)
|
merge (p)-[:NOTIFIED]->(n)
|
||||||
`
|
`
|
||||||
await session.run(cypher, {
|
await session.run(cypher, {
|
||||||
ids,
|
idsOfMentionedUsers,
|
||||||
createdAt,
|
createdAt,
|
||||||
postId
|
postId
|
||||||
})
|
})
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
return post
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateHashtagsOfPost = async (postId, resolve, root, args, context, resolveInfo) => {
|
const updateHashtagsOfPost = async (postId, hashtags, context) => {
|
||||||
// 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 session = context.driver.session()
|
const session = context.driver.session()
|
||||||
// const {
|
|
||||||
// id: postId
|
|
||||||
// } = post
|
|
||||||
// const createdAt = new Date().toISOString()
|
|
||||||
const cypher = `
|
const cypher = `
|
||||||
MATCH (p:Post { id: $postId })-[oldRelations: TAGGED]->(oldTags: Tag)
|
MATCH (p:Post { id: $postId })-[oldRelations:TAGGED]->(oldTags:Tag)
|
||||||
DELETE oldRelations
|
DELETE oldRelations
|
||||||
WITH p
|
WITH p
|
||||||
UNWIND $hashtags AS tagName
|
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)
|
MERGE (p)-[:TAGGED]->(t)
|
||||||
RETURN t
|
RETURN p, t
|
||||||
`
|
`
|
||||||
await session.run(cypher, {
|
await session.run(cypher, {
|
||||||
postId,
|
postId,
|
||||||
@ -61,10 +38,20 @@ const updateHashtagsOfPost = async (postId, resolve, root, args, context, resolv
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleContentData = async (resolve, root, args, context, resolveInfo) => {
|
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)
|
// removes classes from the content
|
||||||
await updateHashtagsOfPost(post.id, resolve, root, args, context, resolveInfo)
|
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
|
return post
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import cheerio from 'cheerio'
|
import cheerio from 'cheerio'
|
||||||
const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g
|
const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g
|
||||||
|
|
||||||
export default function(content) {
|
export default function (content) {
|
||||||
if (!content) return []
|
if (!content) return []
|
||||||
const $ = cheerio.load(content)
|
const $ = cheerio.load(content)
|
||||||
const urls = $('.mention')
|
const urls = $('.mention')
|
||||||
@ -11,10 +11,11 @@ export default function(content) {
|
|||||||
.get()
|
.get()
|
||||||
const ids = []
|
const ids = []
|
||||||
urls.forEach(url => {
|
urls.forEach(url => {
|
||||||
|
console.log('url: ', url)
|
||||||
let match
|
let match
|
||||||
while ((match = ID_REGEX.exec(url)) != null) {
|
while ((match = ID_REGEX.exec(url)) != null) {
|
||||||
ids.push(match[1])
|
ids.push(match[1])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
@ -39,7 +39,9 @@ describe('ContributionForm.vue', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.mockRejectedValue({ message: 'Not Authorised!' }),
|
.mockRejectedValue({
|
||||||
|
message: 'Not Authorised!',
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
$toast: {
|
$toast: {
|
||||||
error: jest.fn(),
|
error: jest.fn(),
|
||||||
@ -66,12 +68,26 @@ describe('ContributionForm.vue', () => {
|
|||||||
getters,
|
getters,
|
||||||
})
|
})
|
||||||
const Wrapper = () => {
|
const Wrapper = () => {
|
||||||
return mount(ContributionForm, { mocks, localVue, store, propsData })
|
return mount(ContributionForm, {
|
||||||
|
mocks,
|
||||||
|
localVue,
|
||||||
|
store,
|
||||||
|
propsData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
wrapper.setData({ form: { languageOptions: [{ label: 'Deutsch', value: 'de' }] } })
|
wrapper.setData({
|
||||||
|
form: {
|
||||||
|
languageOptions: [
|
||||||
|
{
|
||||||
|
label: 'Deutsch',
|
||||||
|
value: 'de',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('CreatePost', () => {
|
describe('CreatePost', () => {
|
||||||
@ -100,7 +116,12 @@ describe('ContributionForm.vue', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
expectedParams = {
|
expectedParams = {
|
||||||
mutation: PostMutations().CreatePost,
|
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 = wrapper.find('.ds-input')
|
||||||
postTitleInput.setValue(postTitle)
|
postTitleInput.setValue(postTitle)
|
||||||
@ -124,25 +145,13 @@ describe('ContributionForm.vue', () => {
|
|||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('supports adding tags', async () => {
|
it.skip('supports adding tags', async () => {
|
||||||
expectedParams.variables.tags = ['Frieden']
|
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))
|
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']
|
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 () => {
|
it("pushes the user to the post's page", async () => {
|
||||||
@ -210,7 +219,9 @@ describe('ContributionForm.vue', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('sets language equal to contribution language', () => {
|
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 () => {
|
it('calls the UpdatePost apollo mutation', async () => {
|
||||||
|
|||||||
@ -12,17 +12,6 @@
|
|||||||
/>
|
/>
|
||||||
</no-ssr>
|
</no-ssr>
|
||||||
<ds-space margin-bottom="xxx-large" />
|
<ds-space margin-bottom="xxx-large" />
|
||||||
<ds-input
|
|
||||||
model="tagValue"
|
|
||||||
:label="$t('contribution.tagsInputLabel')"
|
|
||||||
:placeholder="$t('contribution.tagsInputPlaceholder')"
|
|
||||||
@input.native="handleInput"
|
|
||||||
@keyup.enter.native="addTag(form.tagValue)"
|
|
||||||
:disabled="form.tags.length >= 5"
|
|
||||||
></ds-input>
|
|
||||||
<ds-chip v-for="(tag, index) in form.tags" @remove="removeTag(index)" removable :key="tag">
|
|
||||||
{{ tag }}
|
|
||||||
</ds-chip>
|
|
||||||
<ds-flex class="contribution-form-footer">
|
<ds-flex class="contribution-form-footer">
|
||||||
<ds-flex-item :width="{ base: '10%', sm: '10%', md: '10%', lg: '15%' }" />
|
<ds-flex-item :width="{ base: '10%', sm: '10%', md: '10%', lg: '15%' }" />
|
||||||
<ds-flex-item :width="{ base: '80%', sm: '30%', md: '30%', lg: '20%' }">
|
<ds-flex-item :width="{ base: '80%', sm: '30%', md: '30%', lg: '20%' }">
|
||||||
@ -82,8 +71,6 @@ export default {
|
|||||||
content: '',
|
content: '',
|
||||||
language: null,
|
language: null,
|
||||||
languageOptions: [],
|
languageOptions: [],
|
||||||
tagValue: null,
|
|
||||||
tags: [],
|
|
||||||
},
|
},
|
||||||
formSchema: {
|
formSchema: {
|
||||||
title: { required: true, min: 3, max: 64 },
|
title: { required: true, min: 3, max: 64 },
|
||||||
@ -135,7 +122,6 @@ export default {
|
|||||||
title: this.form.title,
|
title: this.form.title,
|
||||||
content: this.form.content,
|
content: this.form.content,
|
||||||
language: this.form.language ? this.form.language.value : this.$i18n.locale(),
|
language: this.form.language ? this.form.language.value : this.$i18n.locale(),
|
||||||
tags: this.form.tags,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
@ -165,16 +151,6 @@ export default {
|
|||||||
this.form.languageOptions.push({ label: locale.name, value: locale.code })
|
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: {
|
apollo: {
|
||||||
User: {
|
User: {
|
||||||
|
|||||||
@ -12,10 +12,19 @@
|
|||||||
<div v-if="isMention">@{{ item.slug }}</div>
|
<div v-if="isMention">@{{ item.slug }}</div>
|
||||||
<div v-if="isHashtag">#{{ item.name }}</div>
|
<div v-if="isHashtag">#{{ item.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isHashtag && query && !filteredItems.find(el => el.name === query)"
|
||||||
|
class="suggestion-list__item is-empty"
|
||||||
|
>
|
||||||
|
{{ $t('editor.hashtag.addHashtag') }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="suggestion-list__item is-empty">
|
<div v-else class="suggestion-list__item is-empty">
|
||||||
<div v-if="isMention">{{ $t('editor.mention.noUsersFound') }}</div>
|
<div v-if="isMention">{{ $t('editor.mention.noUsersFound') }}</div>
|
||||||
<div v-if="isHashtag">{{ $t('editor.hashtag.noHashtagsFound') }}</div>
|
<div v-if="isHashtag">
|
||||||
|
<div v-if="query === ''">{{ $t('editor.hashtag.noHashtagsFound') }}</div>
|
||||||
|
<div v-else>{{ $t('editor.hashtag.addHashtag') }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -271,7 +280,7 @@ export default {
|
|||||||
}
|
}
|
||||||
// pressing enter
|
// pressing enter
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
this.enterHandler(this.mentionSuggestionType)
|
this.enterHandler()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -340,9 +349,14 @@ export default {
|
|||||||
this.downHandler()
|
this.downHandler()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// pressing enter or pressing space
|
// pressing enter
|
||||||
if (event.keyCode === 13 || event.keyCode === 32) {
|
if (event.keyCode === 13) {
|
||||||
this.enterHandler(this.hashtagSuggestionType)
|
this.enterHandler()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// pressing space
|
||||||
|
if (event.keyCode === 32) {
|
||||||
|
this.spaceHandler()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -357,7 +371,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const fuse = new Fuse(items, {
|
const fuse = new Fuse(items, {
|
||||||
threshold: 0.2,
|
threshold: 0.2,
|
||||||
keys: ['slug'],
|
keys: ['name'],
|
||||||
})
|
})
|
||||||
return fuse.search(query)
|
return fuse.search(query)
|
||||||
},
|
},
|
||||||
@ -434,13 +448,17 @@ export default {
|
|||||||
downHandler() {
|
downHandler() {
|
||||||
this.navigatedItemIndex = (this.navigatedItemIndex + 1) % this.filteredItems.length
|
this.navigatedItemIndex = (this.navigatedItemIndex + 1) % this.filteredItems.length
|
||||||
},
|
},
|
||||||
// For hashtags handles pressing of space as enter.
|
// Handles pressing of enter.
|
||||||
enterHandler() {
|
enterHandler() {
|
||||||
const item = this.filteredItems[this.navigatedItemIndex]
|
const item = this.filteredItems[this.navigatedItemIndex]
|
||||||
if (item) {
|
if (item) {
|
||||||
this.selectItem(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
|
// we have to replace our suggestion text with a mention
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
"code": "Code eingeben",
|
"code": "Code eingeben",
|
||||||
"description": "Öffne dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.",
|
"description": "Öffne dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.",
|
||||||
"next": "Weiter",
|
"next": "Weiter",
|
||||||
"change-password":{
|
"change-password": {
|
||||||
"success": "Änderung des Passworts war erfolgreich!",
|
"success": "Änderung des Passworts war erfolgreich!",
|
||||||
"error": "Passwort Änderung fehlgeschlagen. Möglicherweise falscher Sicherheitscode?",
|
"error": "Passwort Änderung fehlgeschlagen. Möglicherweise falscher Sicherheitscode?",
|
||||||
"help": "Falls Probleme auftreten, schreib uns gerne eine Mail an:"
|
"help": "Falls Probleme auftreten, schreib uns gerne eine Mail an:"
|
||||||
@ -40,7 +40,8 @@
|
|||||||
"noUsersFound": "Keine Benutzer gefunden"
|
"noUsersFound": "Keine Benutzer gefunden"
|
||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"noHashtagsFound": "Keine Hashtags gefunden"
|
"noHashtagsFound": "Keine Hashtags gefunden",
|
||||||
|
"addHashtag": "Neuer Hashtag"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
@ -338,9 +339,7 @@
|
|||||||
"filterFollow": "Beiträge filtern von Usern denen ich folge",
|
"filterFollow": "Beiträge filtern von Usern denen ich folge",
|
||||||
"filterALL": "Alle Beiträge anzeigen",
|
"filterALL": "Alle Beiträge anzeigen",
|
||||||
"success": "Gespeichert!",
|
"success": "Gespeichert!",
|
||||||
"languageSelectLabel": "Sprache",
|
"languageSelectLabel": "Sprache"
|
||||||
"tagsInputLabel": "Tags",
|
|
||||||
"tagsInputPlaceholder": "Hinzufügen ein Tag"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,8 @@
|
|||||||
"noUsersFound": "No users found"
|
"noUsersFound": "No users found"
|
||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"noHashtagsFound": "No hashtags found"
|
"noHashtagsFound": "No hashtags found",
|
||||||
|
"addHashtag": "New hashtag"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
@ -337,8 +338,6 @@
|
|||||||
"filterFollow": "Filter contributions from users I follow",
|
"filterFollow": "Filter contributions from users I follow",
|
||||||
"filterALL": "View all contributions",
|
"filterALL": "View all contributions",
|
||||||
"success": "Saved!",
|
"success": "Saved!",
|
||||||
"languageSelectLabel": "Language",
|
"languageSelectLabel": "Language"
|
||||||
"tagsInputLabel": "Tags",
|
|
||||||
"tagsInputPlaceholder": "Add a tag"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user