Split social media page and list component

- Rename variables.
- Implement callbacks.
- Fix tests.
This commit is contained in:
Wolfgang Huß 2021-11-11 11:53:56 +01:00
parent 280f0f5a78
commit b7400339ab
5 changed files with 473 additions and 330 deletions

View File

@ -1,20 +1,26 @@
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import flushPromises from 'flush-promises' // Wolle import flushPromises from 'flush-promises'
import MySomethingList from './MySomethingList.vue' import MySomethingList from './MySomethingList.vue'
import Vuex from 'vuex' // Wolle import Vuex from 'vuex'
import Vue from 'vue' import Vue from 'vue'
const localVue = global.localVue const localVue = global.localVue
describe('MySomethingList.vue', () => { describe('MySomethingList.vue', () => {
let wrapper let wrapper
let propsData
let data let data
let mocks let mocks
let getters // let getters
const socialMediaUrl = 'https://freeradical.zone/@mattwr18' // Wolle const socialMediaUrl = 'https://freeradical.zone/@mattwr18'
// const newSocialMediaUrl = 'https://twitter.com/mattwr18' // const newSocialMediaUrl = 'https://twitter.com/mattwr18'
beforeEach(() => { beforeEach(() => {
propsData = {
useItems: [{ id: 'id', dummy: 'dummy' }],
namePropertyKey: 'dummy',
callbacks: { edit: jest.fn(), submit: jest.fn(), delete: jest.fn() },
}
data = () => { data = () => {
return {} return {}
} }
@ -28,22 +34,32 @@ describe('MySomethingList.vue', () => {
success: jest.fn(), success: jest.fn(),
}, },
} }
getters = { // getters = {
'auth/user': () => { // 'auth/user': () => {
return {} // return {}
}, // },
} // }
}) })
describe('mount', () => { describe('mount', () => {
// Wolle let form, input, slots, submitButton // Wolle let form, input, slots, submitButton
let slots let form, slots
const Wrapper = () => { const Wrapper = () => {
const store = new Vuex.Store({ // const store = new Vuex.Store({
getters, // getters,
// })
slots = {
'list-item': '<div class="list-item"></div>',
'edit-item': '<div class="edit-item"></div>',
}
return mount(MySomethingList, {
propsData,
data,
// store,
mocks,
localVue,
slots,
}) })
slots = { 'list-item': '<div class="list-item"></div>' }
return mount(MySomethingList, { data, store, mocks, localVue, slots })
} }
// describe('adding social media link', () => { // describe('adding social media link', () => {
@ -108,11 +124,11 @@ describe('MySomethingList.vue', () => {
describe('given existing social media links', () => { describe('given existing social media links', () => {
beforeEach(() => { beforeEach(() => {
getters = { // getters = {
'auth/user': () => ({ // 'auth/user': () => ({
socialMedia: [{ id: 's1', url: socialMediaUrl }], // socialMedia: [{ id: 's1', url: socialMediaUrl }],
}), // }),
} // }
// Wolle propsData = { editingLink: { id: 's1', url: socialMediaUrl } } // Wolle propsData = { editingLink: { id: 's1', url: socialMediaUrl } }
// data = () => { // data = () => {
// return { // return {
@ -137,67 +153,56 @@ describe('MySomethingList.vue', () => {
}) })
}) })
// Wolle it('does not accept a duplicate url', async () => { describe('editing item', () => {
// // wrapper.find('input#addSocialMedia').setValue(socialMediaUrl)
// wrapper.find('input#editSocialMedia').setValue(socialMediaUrl)
// form.trigger('submit')
// await Vue.nextTick()
// expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
// })
// describe('editing social media link', () => {
// beforeEach(async () => {
// const editButton = wrapper.find('.base-button[data-test="edit-button"]')
// editButton.trigger('click')
// await Vue.nextTick()
// input = wrapper.find('input#editSocialMedia')
// })
// it('disables adding new links while editing', () => {
// const addInput = wrapper.find('input#addSocialMedia')
// wrapper.find('.base-button[data-test="add-save-button"]').text().
// expect(addInput.exists()).toBe(false)
// const submitButton = wrapper.find('.base-button[data-test="add-save-button"]')
// expect(submitButton.text()).not.toContain('settings.social-media.submit')
// })
// Wolle remove? or test here abstract? it('sends the new url to the backend', async () => {
// const expected = expect.objectContaining({
// variables: { id: 's1', url: newSocialMediaUrl },
// })
// input.setValue(newSocialMediaUrl)
// form.trigger('submit')
// await Vue.nextTick()
// expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
// })
// it('allows the user to cancel editing', async () => {
// const cancelButton = wrapper.find('button#cancel')
// cancelButton.trigger('click')
// await Vue.nextTick()
// expect(wrapper.find('input#editSocialMedia').exists()).toBe(false)
// })
// })
describe('deleting social media link', () => {
beforeEach(async () => { beforeEach(async () => {
const editButton = wrapper.find('.base-button[data-test="edit-button"]')
editButton.trigger('click')
await Vue.nextTick()
// Wolle input = wrapper.find('input#editSocialMedia')
})
it('disables adding items while editing', () => {
const submitButton = wrapper.find('.base-button[data-test="add-save-button"]')
expect(submitButton.text()).not.toContain('settings.social-media.submit')
})
it('allows the user to cancel editing', async () => {
expect(wrapper.find('.edit-item').exists()).toBeTruthy()
const cancelButton = wrapper.find('button#cancel')
cancelButton.trigger('click')
await Vue.nextTick()
expect(wrapper.find('.edit-item').exists()).not.toBeTruthy()
})
})
describe('calls callback functions', () => {
it('call edit', async () => {
const editButton = wrapper.find('.base-button[data-test="edit-button"]')
editButton.trigger('click')
await Vue.nextTick()
const expectedItem = expect.objectContaining({ id: 'id', dummy: 'dummy' })
expect(propsData.callbacks.edit).toHaveBeenCalledTimes(1)
expect(propsData.callbacks.edit).toHaveBeenCalledWith(expect.any(Object), expectedItem)
})
it('call edit', async () => {
form = wrapper.find('form')
form.trigger('submit')
await Vue.nextTick()
form.trigger('submit')
await Vue.nextTick()
const expectedItem = expect.objectContaining({ id: '' })
expect(propsData.callbacks.edit).toHaveBeenCalledTimes(1)
expect(propsData.callbacks.edit).toHaveBeenCalledWith(expect.any(Object), expectedItem)
})
it('call delete', async () => {
const deleteButton = wrapper.find('.base-button[data-test="delete-button"]') const deleteButton = wrapper.find('.base-button[data-test="delete-button"]')
deleteButton.trigger('click') deleteButton.trigger('click')
await Vue.nextTick() await Vue.nextTick()
}) const expectedItem = expect.objectContaining({ id: 'id', dummy: 'dummy' })
expect(propsData.callbacks.delete).toHaveBeenCalledTimes(1)
it('sends the link id to the backend', () => { expect(propsData.callbacks.delete).toHaveBeenCalledWith(expect.any(Object), expectedItem)
const expected = expect.objectContaining({
variables: { id: 's1' },
})
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
})
it('displays a success message', async () => {
await flushPromises()
expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
}) })
}) })
}) })

View File

@ -1,6 +1,4 @@
<template> <template>
<base-card>
<ds-heading tag="h2" class="title">{{ $t('settings.social-media.name') }}</ds-heading>
<ds-form <ds-form
v-model="formData" v-model="formData"
:schema="formSchema" :schema="formSchema"
@ -13,13 +11,13 @@
<ds-space margin="base"> <ds-space margin="base">
<ds-heading tag="h3" class="undertitle"> <ds-heading tag="h3" class="undertitle">
{{ {{
/* $t('settings.social-media.name') */ editingLink.id === '' /* $t('settings.social-media.name') */ isCreation
? 'Add new one' ? 'Add new'
: 'Edit "' + editingLink.url + '"' : 'Edit "' + editingItem[namePropertyKey] + '"'
}} }}
</ds-heading> </ds-heading>
</ds-space> </ds-space>
<ds-space v-if="socialMediaLinks" margin-top="base" margin="base"> <ds-space v-if="items" margin-top="base" margin="base">
<!-- Wolle <ds-input <!-- Wolle <ds-input
id="editSocialMedia" id="editSocialMedia"
model="socialMediaUrl" model="socialMediaUrl"
@ -30,9 +28,9 @@
</ds-space> </ds-space>
</div> </div>
<div v-else> <div v-else>
<ds-space v-if="socialMediaLinks" margin-top="base" margin="small"> <ds-space v-if="items" margin-top="base" margin="small">
<ds-list> <ds-list>
<ds-list-item v-for="link in socialMediaLinks" :key="link.id" class="list-item--high"> <ds-list-item v-for="item in items" :key="item.id" class="list-item--high">
<!-- Wolle remove template tag? --> <!-- Wolle remove template tag? -->
<template> <template>
<!-- Wolle <a :href="link.url" target="_blank"> <!-- Wolle <a :href="link.url" target="_blank">
@ -40,13 +38,13 @@
{{ link.url }} {{ link.url }}
</a> --> </a> -->
<!-- Wolle <slot name="list-item" :link="link" data-test="item-slot" /> --> <!-- Wolle <slot name="list-item" :link="link" data-test="item-slot" /> -->
<slot name="list-item" :link="link" /> <slot name="list-item" :item="item" />
<span class="divider">|</span> <span class="divider">|</span>
<base-button <base-button
icon="edit" icon="edit"
circle circle
ghost ghost
@click="handleEditSocialMedia(link)" @click="handleEditSocialMedia(item)"
:title="$t('actions.edit')" :title="$t('actions.edit')"
data-test="edit-button" data-test="edit-button"
/> />
@ -54,7 +52,7 @@
icon="trash" icon="trash"
circle circle
ghost ghost
@click="handleDeleteSocialMedia(link)" @click="handleDeleteSocialMedia(item)"
:title="$t('actions.delete')" :title="$t('actions.delete')"
data-test="delete-button" data-test="delete-button"
/> />
@ -87,13 +85,12 @@
</ds-space> </ds-space>
</ds-space> </ds-space>
</ds-form> </ds-form>
</base-card>
</template> </template>
<script> <script>
import unionBy from 'lodash/unionBy' // Wolle import unionBy from 'lodash/unionBy'
import gql from 'graphql-tag' // import gql from 'graphql-tag'
import { mapGetters, mapMutations } from 'vuex' // Wolle import { mapGetters, mapMutations } from 'vuex'
export default { export default {
name: 'MySomethingList', name: 'MySomethingList',
@ -106,12 +103,25 @@ export default {
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },
callbackEdit: { useItems: {
type: Function, type: Array,
default: () => {}, default: () => [],
},
defaultItem: {
type: Object,
default: () => ({}),
},
namePropertyKey: {
type: String,
required: true,
},
callbacks: {
type: Object,
default: () => ({ edit: () => {}, submit: () => {}, delete: () => {} }),
}, },
}, },
data() { data() {
// Wolle console.log(this.useItems)
return { return {
// Wolle formData: { // Wolle formData: {
// socialMediaUrl: '', // socialMediaUrl: '',
@ -124,44 +134,56 @@ export default {
// }, // },
formData: this.useFormData, formData: this.useFormData,
formSchema: this.useFormSchema, formSchema: this.useFormSchema,
items: this.useItems,
disabled: true, disabled: true,
editingLink: null, editingItem: null,
} }
}, },
computed: { computed: {
...mapGetters({ // Wolle ...mapGetters({
currentUser: 'auth/user', // currentUser: 'auth/user',
}), // }),
isEditing() { isEditing() {
return this.editingLink !== null return this.editingItem !== null
}, },
isCreation() { isCreation() {
return this.editingLink !== null && this.editingLink.id === '' return this.editingItem !== null && this.editingItem.id === ''
}, },
socialMediaLinks() { // Wolle socialMediaLinks() {
const domainRegex = /^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:/\n?]+)/g // const domainRegex = /^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:/\n?]+)/g
const { socialMedia = [] } = this.currentUser // const { socialMedia = [] } = this.currentUser
return socialMedia.map(({ id, url }) => { // return socialMedia.map(({ id, url }) => {
const [domain] = url.match(domainRegex) || [] // const [domain] = url.match(domainRegex) || []
const favicon = domain ? `${domain}/favicon.ico` : null // const favicon = domain ? `${domain}/favicon.ico` : null
return { id, url, favicon } // return { id, url, favicon }
}) // })
// },
},
watch: {
// useFormData(newFormData) {
// this.formData = newFormData
// },
// useFormSchema(newFormSchema) {
// this.formSchema = newFormSchema
// },
useItems(newItems) {
this.items = newItems
}, },
}, },
methods: { methods: {
...mapMutations({ // Wolle ...mapMutations({
setCurrentUser: 'auth/SET_USER', // setCurrentUser: 'auth/SET_USER',
}), // }),
handleCancel() { handleCancel() {
this.editingLink = null this.editingItem = null
this.formData.socialMediaUrl = '' // Wolle ??? this.formData.socialMediaUrl = ''
this.disabled = true this.disabled = true
}, },
handleEditSocialMedia(link) { handleEditSocialMedia(item) {
this.editingLink = link this.editingItem = item
// Wolle this.formData.socialMediaUrl = link.url // Wolle this.formData.socialMediaUrl = link.url
// Wolle this.$refs.socialMediaUrl.$el.focus() // Wolle this.$refs.socialMediaUrl.$el.focus()
this.callbackEdit(this, link) this.callbacks.edit(this, item)
}, },
handleInput(data) { handleInput(data) {
this.disabled = true this.disabled = true
@ -173,99 +195,105 @@ export default {
this.disabled = false this.disabled = false
} }
}, },
async handleDeleteSocialMedia(link) { async handleDeleteSocialMedia(item) {
try { // Wolle try {
await this.$apollo.mutate({ // await this.$apollo.mutate({
mutation: gql` // mutation: gql`
mutation($id: ID!) { // mutation($id: ID!) {
DeleteSocialMedia(id: $id) { // DeleteSocialMedia(id: $id) {
id // id
url // url
} // }
} // }
`, // `,
variables: { // variables: {
id: link.id, // id: item.id,
}, // },
update: (store, { data }) => { // update: (store, { data }) => {
const socialMedia = this.currentUser.socialMedia.filter( // const socialMedia = this.currentUser.socialMedia.filter(
(element) => element.id !== link.id, // (element) => element.id !== item.id,
) // )
this.setCurrentUser({ // this.setCurrentUser({
...this.currentUser, // ...this.currentUser,
socialMedia, // socialMedia,
}) // })
}, // },
}) // })
this.$toast.success(this.$t('settings.social-media.successDelete')) // this.$toast.success(this.$t('settings.social-media.successDelete'))
} catch (err) { // } catch (err) {
this.$toast.error(err.message) // this.$toast.error(err.message)
} // }
await this.callbacks.delete(this, item)
}, },
async handleSubmitSocialMedia() { async handleSubmitSocialMedia() {
// Wolle const isEditing = (this.editingLink !== null) // Wolle const isEditing = (this.editingLink !== null)
if (!this.isEditing) { if (!this.isEditing) {
// Wolle this.editingLink = { id: '', url: '' } // Wolle this.editingLink = { id: '', url: '' }
this.handleEditSocialMedia({ id: '', url: '' }) // this.handleEditSocialMedia({ id: '', url: '' })
this.handleEditSocialMedia({ ...this.defaultItem, id: '' })
} else { } else {
// Wolle const url = this.formData.socialMediaUrl // // Wolle const url = this.formData.socialMediaUrl
this.editingLink.url = this.formData.socialMediaUrl // this.editingLink.url = this.formData.socialMediaUrl
const duplicateUrl = this.socialMediaLinks.find((link) => link.url === this.editingLink.url) // const duplicateUrl = this.items.find((item) => item.url === this.editingLink.url)
// Wolle console.log('duplicateUrl: ', duplicateUrl) // // Wolle console.log('duplicateUrl: ', duplicateUrl)
// console.log('this.isEditing: ', this.isEditing) // // console.log('this.isEditing: ', this.isEditing)
// console.log('this.editingLink: ', this.editingLink) // // console.log('this.editingLink: ', this.editingLink)
if (duplicateUrl && this.isEditing && duplicateUrl.id !== this.editingLink.id) { // if (duplicateUrl && this.isEditing && duplicateUrl.id !== this.editingLink.id) {
return this.$toast.error(this.$t('settings.social-media.requireUnique')) // return this.$toast.error(this.$t('settings.social-media.requireUnique'))
} // }
let mutation, variables, successMessage // let mutation, variables, successMessage
if (this.isCreation) { // if (this.isCreation) {
mutation = gql` // mutation = gql`
mutation($url: String!) { // mutation($url: String!) {
CreateSocialMedia(url: $url) { // CreateSocialMedia(url: $url) {
id // id
url // url
} // }
} // }
` // `
variables = { url: this.editingLink.url } // variables = { url: this.editingLink.url }
successMessage = this.$t('settings.social-media.successAdd') // successMessage = this.$t('settings.social-media.successAdd')
} else { // } else {
mutation = gql` // mutation = gql`
mutation($id: ID!, $url: String!) { // mutation($id: ID!, $url: String!) {
UpdateSocialMedia(id: $id, url: $url) { // UpdateSocialMedia(id: $id, url: $url) {
id // id
url // url
} // }
} // }
` // `
variables = { id: this.editingLink.id, url: this.editingLink.url } // variables = { id: this.editingLink.id, url: this.editingLink.url }
successMessage = this.$t('settings.data.success') // successMessage = this.$t('settings.data.success')
} // }
try { // try {
await this.$apollo.mutate({ // await this.$apollo.mutate({
mutation, // mutation,
variables, // variables,
update: (_store, { data }) => { // update: (_store, { data }) => {
const newSocialMedia = !this.isCreation // const newSocialMedia = !this.isCreation
? data.UpdateSocialMedia // ? data.UpdateSocialMedia
: data.CreateSocialMedia // : data.CreateSocialMedia
this.setCurrentUser({ // this.setCurrentUser({
...this.currentUser, // ...this.currentUser,
socialMedia: unionBy([newSocialMedia], this.currentUser.socialMedia, 'id'), // socialMedia: unionBy([newSocialMedia], this.currentUser.socialMedia, 'id'),
}) // })
}, // },
}) // })
this.$toast.success(successMessage) // this.$toast.success(successMessage)
this.formData.socialMediaUrl = '' // this.formData.socialMediaUrl = ''
// this.disabled = true
// this.editingLink = null
// } catch (err) {
// this.$toast.error(err.message)
// }
if (await this.callbacks.submit(this, this.isCreation, this.editingItem, this.formData)) {
this.disabled = true this.disabled = true
this.editingLink = null this.editingItem = null
} catch (err) {
this.$toast.error(err.message)
} }
} }
}, },

View File

@ -1,7 +1,7 @@
<template> <template>
<a :href="link.url" target="_blank"> <a :href="item.url" target="_blank">
<img :src="link.favicon" alt="Link:" height="16" width="16" /> <img :src="item.favicon" alt="Link:" height="16" width="16" />
{{ link.url }} {{ item.url }}
</a> </a>
</template> </template>
@ -9,7 +9,7 @@
export default { export default {
name: 'SocialMediaListItem', name: 'SocialMediaListItem',
props: { props: {
link: { item: {
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },

View File

@ -112,7 +112,6 @@ describe('my-social-media.vue', () => {
socialMedia: [{ id: 's1', url: socialMediaUrl }], socialMedia: [{ id: 's1', url: socialMediaUrl }],
}), }),
} }
wrapper = Wrapper() wrapper = Wrapper()
form = wrapper.find('form') form = wrapper.find('form')
}) })
@ -152,13 +151,6 @@ describe('my-social-media.vue', () => {
input = wrapper.find('input#editSocialMedia') input = wrapper.find('input#editSocialMedia')
}) })
it('disables adding new links while editing', () => {
// Wolle const addInput = wrapper.find('input#addSocialMedia')
// expect(addInput.exists()).toBe(false)
const submitButton = wrapper.find('.base-button[data-test="add-save-button"]')
expect(submitButton.text()).not.toContain('settings.social-media.submit')
})
it('sends the new url to the backend', async () => { it('sends the new url to the backend', async () => {
const expected = expect.objectContaining({ const expected = expect.objectContaining({
variables: { id: 's1', url: newSocialMediaUrl }, variables: { id: 's1', url: newSocialMediaUrl },
@ -168,36 +160,28 @@ describe('my-social-media.vue', () => {
await Vue.nextTick() await Vue.nextTick()
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected) expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
}) })
// it('allows the user to cancel editing', async () => {
// const cancelButton = wrapper.find('button#cancel')
// cancelButton.trigger('click')
// await Vue.nextTick()
// expect(wrapper.find('input#editSocialMedia').exists()).toBe(false)
// })
}) })
// describe('deleting social media link', () => { describe('deleting social media link', () => {
// beforeEach(async () => { beforeEach(async () => {
// const deleteButton = wrapper.find('.base-button[data-test="delete-button"]') const deleteButton = wrapper.find('.base-button[data-test="delete-button"]')
// deleteButton.trigger('click') deleteButton.trigger('click')
// await Vue.nextTick() await Vue.nextTick()
// }) })
// it('sends the link id to the backend', () => { it('sends the link id to the backend', () => {
// const expected = expect.objectContaining({ const expected = expect.objectContaining({
// variables: { id: 's1' }, variables: { id: 's1' },
// }) })
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
})
// expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1) it('displays a success message', async () => {
// expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected) await flushPromises()
// }) expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
})
// it('displays a success message', async () => { })
// await flushPromises()
// expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
// })
// })
}) })
}) })
}) })

View File

@ -1,11 +1,20 @@
<template> <template>
<base-card>
<ds-heading tag="h2" class="title">{{ $t('settings.social-media.name') }}</ds-heading>
<my-something-list <my-something-list
:useFormData="useFormData" :useFormData="useFormData"
:useFormSchema="useFormSchema" :useFormSchema="useFormSchema"
:callbackEdit="callbackEditSocialMedia" :useItems="socialMediaLinks"
:defaultItem="{ url: '' }"
:namePropertyKey="'url'"
:callbacks="{
edit: callbackEditSocialMedia,
submit: handleSubmitSocialMedia,
delete: callbackDeleteSocialMedia,
}"
> >
<template #list-item="{ link }"> <template #list-item="{ item }">
<social-media-list-item :link="link" /> <social-media-list-item :item="item" />
</template> </template>
<template #edit-item> <template #edit-item>
<ds-input <ds-input
@ -16,9 +25,13 @@
/> />
</template> </template>
</my-something-list> </my-something-list>
</base-card>
</template> </template>
<script> <script>
import { mapGetters, mapMutations } from 'vuex'
import unionBy from 'lodash/unionBy'
import gql from 'graphql-tag'
import MySomethingList from '~/components/_new/features/MySomethingList/MySomethingList.vue' import MySomethingList from '~/components/_new/features/MySomethingList/MySomethingList.vue'
import SocialMediaListItem from '~/components/_new/features/SocialMedia/SocialMediaListItem.vue' import SocialMediaListItem from '~/components/_new/features/SocialMedia/SocialMediaListItem.vue'
@ -40,17 +53,130 @@ export default {
}, },
} }
}, },
computed: {
...mapGetters({
currentUser: 'auth/user',
}),
currentSocialMediaLinks() {
const domainRegex = /^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:/\n?]+)/g
const { socialMedia = [] } = this.currentUser
return socialMedia.map(({ id, url }) => {
const [domain] = url.match(domainRegex) || []
const favicon = domain ? `${domain}/favicon.ico` : null
return { id, url, favicon }
})
},
socialMediaLinks() {
const domainRegex = /^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:/\n?]+)/g
const { socialMedia = [] } = this.currentUser
return socialMedia.map(({ id, url }) => {
const [domain] = url.match(domainRegex) || []
const favicon = domain ? `${domain}/favicon.ico` : null
return { id, url, favicon }
})
},
},
methods: { methods: {
callbackEditSocialMedia(thisMySomethingList, link) { ...mapMutations({
setCurrentUser: 'auth/SET_USER',
}),
callbackEditSocialMedia(thisList, link) {
// Wolle this.editingLink = link // Wolle this.editingLink = link
thisMySomethingList.formData.socialMediaUrl = link.url thisList.formData.socialMediaUrl = link.url
// thisMySomethingList.$refs.socialMediaUrl.$el.focus() // thisList.$refs.socialMediaUrl.$el.focus()
// !!! Check for existenz // !!! Check for existenz
// this.$scopedSlots.default()[0].context.$refs // this.$scopedSlots.default()[0].context.$refs
// thisMySomethingList.$scopedSlots['edit-item']()[0].$el.focus() // thisList.$scopedSlots['edit-item']()[0].$el.focus()
// console.log(thisMySomethingList.$scopedSlots['edit-item']()[0].context.$refs) // console.log(thisList.$scopedSlots['edit-item']()[0].context.$refs)
// console.log(thisMySomethingList.$scopedSlots['edit-item']()[0].context.$refs) // console.log(thisList.$scopedSlots['edit-item']()[0].context.$refs)
// console.log(thisMySomethingList.$refs) // console.log(thisList.$refs)
},
async handleSubmitSocialMedia(thisList, isCreation, item, formData) {
item.url = formData.socialMediaUrl
const items = this.socialMediaLinks
const duplicateUrl = items.find((eleItem) => eleItem.url === item.url)
if (duplicateUrl && duplicateUrl.id !== item.id) {
return thisList.$toast.error(thisList.$t('settings.social-media.requireUnique'))
}
let mutation, variables, successMessage
if (isCreation) {
mutation = gql`
mutation($url: String!) {
CreateSocialMedia(url: $url) {
id
url
}
}
`
variables = { url: item.url }
successMessage = thisList.$t('settings.social-media.successAdd')
} else {
mutation = gql`
mutation($id: ID!, $url: String!) {
UpdateSocialMedia(id: $id, url: $url) {
id
url
}
}
`
variables = { id: item.id, url: item.url }
successMessage = thisList.$t('settings.data.success')
}
try {
await thisList.$apollo.mutate({
mutation,
variables,
update: (_store, { data }) => {
const newSocialMedia = !isCreation ? data.UpdateSocialMedia : data.CreateSocialMedia
this.setCurrentUser({
...this.currentUser,
socialMedia: unionBy([newSocialMedia], this.currentUser.socialMedia, 'id'),
})
},
})
thisList.$toast.success(successMessage)
// Wolle ??? thisList.formData.socialMediaUrl = ''
return true
} catch (err) {
thisList.$toast.error(err.message)
return false
}
},
async callbackDeleteSocialMedia(thisList, item) {
try {
await thisList.$apollo.mutate({
mutation: gql`
mutation($id: ID!) {
DeleteSocialMedia(id: $id) {
id
url
}
}
`,
variables: {
id: item.id,
},
update: (store, { data }) => {
const socialMedia = thisList.currentUser.socialMedia.filter(
(element) => element.id !== item.id,
)
thisList.setCurrentUser({
...thisList.currentUser,
socialMedia,
})
},
})
thisList.$toast.success(thisList.$t('settings.social-media.successDelete'))
} catch (err) {
thisList.$toast.error(err.message)
}
}, },
}, },
} }