mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge pull request #1852 from Human-Connection/Allow_embedded_code_in_posts_permanent_memory-II
Save user setting to show embed code II
This commit is contained in:
commit
6955323f51
257
backend/public/providers.json
Normal file
257
backend/public/providers.json
Normal file
@ -0,0 +1,257 @@
|
||||
[
|
||||
{
|
||||
"provider_name": "Codepen",
|
||||
"provider_url": "https:\/\/codepen.io",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/codepen.io\/*",
|
||||
"https:\/\/codepen.io\/*"
|
||||
],
|
||||
"url": "http:\/\/codepen.io\/api\/oembed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "DTube",
|
||||
"provider_url": "https:\/\/d.tube\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/d.tube\/v\/*"
|
||||
],
|
||||
"url": "https:\/\/api.d.tube\/oembed",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Facebook (Post)",
|
||||
"provider_url": "https:\/\/www.facebook.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/www.facebook.com\/*\/posts\/*",
|
||||
"https:\/\/www.facebook.com\/photos\/*",
|
||||
"https:\/\/www.facebook.com\/*\/photos\/*",
|
||||
"https:\/\/www.facebook.com\/photo.php*",
|
||||
"https:\/\/www.facebook.com\/photo.php",
|
||||
"https:\/\/www.facebook.com\/*\/activity\/*",
|
||||
"https:\/\/www.facebook.com\/permalink.php",
|
||||
"https:\/\/www.facebook.com\/media\/set?set=*",
|
||||
"https:\/\/www.facebook.com\/questions\/*",
|
||||
"https:\/\/www.facebook.com\/notes\/*\/*\/*"
|
||||
],
|
||||
"url": "https:\/\/www.facebook.com\/plugins\/post\/oembed.json",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Facebook (Video)",
|
||||
"provider_url": "https:\/\/www.facebook.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/www.facebook.com\/*\/videos\/*",
|
||||
"https:\/\/www.facebook.com\/video.php"
|
||||
],
|
||||
"url": "https:\/\/www.facebook.com\/plugins\/video\/oembed.json",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Flickr",
|
||||
"provider_url": "https:\/\/www.flickr.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/*.flickr.com\/photos\/*",
|
||||
"http:\/\/flic.kr\/p\/*",
|
||||
"https:\/\/*.flickr.com\/photos\/*",
|
||||
"https:\/\/flic.kr\/p\/*"
|
||||
],
|
||||
"url": "https:\/\/www.flickr.com\/services\/oembed\/",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "GIPHY",
|
||||
"provider_url": "https:\/\/giphy.com",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/giphy.com\/gifs\/*",
|
||||
"http:\/\/gph.is\/*",
|
||||
"https:\/\/media.giphy.com\/media\/*\/giphy.gif"
|
||||
],
|
||||
"url": "https:\/\/giphy.com\/services\/oembed",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Instagram",
|
||||
"provider_url": "https:\/\/instagram.com",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/instagram.com\/p\/*",
|
||||
"http:\/\/instagr.am\/p\/*",
|
||||
"http:\/\/www.instagram.com\/p\/*",
|
||||
"http:\/\/www.instagr.am\/p\/*",
|
||||
"https:\/\/instagram.com\/p\/*",
|
||||
"https:\/\/instagr.am\/p\/*",
|
||||
"https:\/\/www.instagram.com\/p\/*",
|
||||
"https:\/\/www.instagr.am\/p\/*"
|
||||
],
|
||||
"url": "https:\/\/api.instagram.com\/oembed",
|
||||
"formats": [
|
||||
"json"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Meetup",
|
||||
"provider_url": "http:\/\/www.meetup.com",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/meetup.com\/*",
|
||||
"https:\/\/www.meetup.com\/*",
|
||||
"https:\/\/meetup.com\/*",
|
||||
"http:\/\/meetu.ps\/*"
|
||||
],
|
||||
"url": "https:\/\/api.meetup.com\/oembed",
|
||||
"formats": [
|
||||
"json"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "MixCloud",
|
||||
"provider_url": "https:\/\/mixcloud.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/www.mixcloud.com\/*\/*\/",
|
||||
"https:\/\/www.mixcloud.com\/*\/*\/"
|
||||
],
|
||||
"url": "https:\/\/www.mixcloud.com\/oembed\/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Reddit",
|
||||
"provider_url": "https:\/\/reddit.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/reddit.com\/r\/*\/comments\/*\/*",
|
||||
"https:\/\/www.reddit.com\/r\/*\/comments\/*\/*"
|
||||
],
|
||||
"url": "https:\/\/www.reddit.com\/oembed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "SlideShare",
|
||||
"provider_url": "http:\/\/www.slideshare.net\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/www.slideshare.net\/*\/*",
|
||||
"http:\/\/fr.slideshare.net\/*\/*",
|
||||
"http:\/\/de.slideshare.net\/*\/*",
|
||||
"http:\/\/es.slideshare.net\/*\/*",
|
||||
"http:\/\/pt.slideshare.net\/*\/*"
|
||||
],
|
||||
"url": "http:\/\/www.slideshare.net\/api\/oembed\/2",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "SoundCloud",
|
||||
"provider_url": "http:\/\/soundcloud.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/soundcloud.com\/*",
|
||||
"https:\/\/soundcloud.com\/*"
|
||||
],
|
||||
"url": "https:\/\/soundcloud.com\/oembed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Twitch",
|
||||
"provider_url": "https:\/\/www.twitch.tv",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"http:\/\/clips.twitch.tv\/*",
|
||||
"https:\/\/clips.twitch.tv\/*",
|
||||
"http:\/\/www.twitch.tv\/*",
|
||||
"https:\/\/www.twitch.tv\/*",
|
||||
"http:\/\/twitch.tv\/*",
|
||||
"https:\/\/twitch.tv\/*"
|
||||
],
|
||||
"url": "https:\/\/api.twitch.tv\/v4\/oembed",
|
||||
"formats": [
|
||||
"json"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Twitter",
|
||||
"provider_url": "http:\/\/www.twitter.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/twitter.com\/*\/status\/*",
|
||||
"https:\/\/*.twitter.com\/*\/status\/*"
|
||||
],
|
||||
"url": "https:\/\/publish.twitter.com\/oembed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "Vimeo",
|
||||
"provider_url": "https:\/\/vimeo.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/vimeo.com\/*",
|
||||
"https:\/\/vimeo.com\/album\/*\/video\/*",
|
||||
"https:\/\/vimeo.com\/channels\/*\/*",
|
||||
"https:\/\/vimeo.com\/groups\/*\/videos\/*",
|
||||
"https:\/\/vimeo.com\/ondemand\/*\/*",
|
||||
"https:\/\/player.vimeo.com\/video\/*"
|
||||
],
|
||||
"url": "https:\/\/vimeo.com\/api\/oembed.{format}",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"provider_name": "YouTube",
|
||||
"provider_url": "https:\/\/www.youtube.com\/",
|
||||
"endpoints": [
|
||||
{
|
||||
"schemes": [
|
||||
"https:\/\/*.youtube.com\/watch*",
|
||||
"https:\/\/*.youtube.com\/v\/*",
|
||||
"https:\/\/youtu.be\/*"
|
||||
],
|
||||
"url": "https:\/\/www.youtube.com\/oembed",
|
||||
"discovery": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -105,4 +105,8 @@ module.exports = {
|
||||
target: 'Location',
|
||||
direction: 'out',
|
||||
},
|
||||
allowEmbedIframes: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import path from 'path'
|
||||
import minimatch from 'minimatch'
|
||||
|
||||
let oEmbedProvidersFile = fs.readFileSync(path.join(__dirname, './providers.json'), 'utf8')
|
||||
|
||||
// some providers allow a format parameter
|
||||
// we need JSON
|
||||
oEmbedProvidersFile = oEmbedProvidersFile.replace(/\{format\}/g, 'json')
|
||||
|
||||
@ -176,6 +176,7 @@ export default {
|
||||
'about',
|
||||
'termsAndConditionsAgreedVersion',
|
||||
'termsAndConditionsAgreedAt',
|
||||
'allowEmbedIframes',
|
||||
],
|
||||
boolean: {
|
||||
followedByCurrentUser:
|
||||
|
||||
@ -86,6 +86,7 @@ describe('UpdateUser', () => {
|
||||
name: 'John Doe',
|
||||
termsAndConditionsAgreedVersion: null,
|
||||
termsAndConditionsAgreedAt: null,
|
||||
allowEmbedIframes: false,
|
||||
}
|
||||
|
||||
variables = {
|
||||
|
||||
@ -27,6 +27,8 @@ type User {
|
||||
termsAndConditionsAgreedVersion: String
|
||||
termsAndConditionsAgreedAt: String
|
||||
|
||||
allowEmbedIframes: Boolean
|
||||
|
||||
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
||||
friendsCount: Int! @cypher(statement: "MATCH (this)<-[: FRIENDS]->(r: User) RETURN COUNT(DISTINCT r)")
|
||||
|
||||
@ -166,6 +168,7 @@ type Mutation {
|
||||
about: String
|
||||
termsAndConditionsAgreedVersion: String
|
||||
termsAndConditionsAgreedAt: String
|
||||
allowEmbedIframes: Boolean
|
||||
): User
|
||||
|
||||
DeleteUser(id: ID!, resource: [Deletable]): User
|
||||
|
||||
@ -16,6 +16,7 @@ export default function create() {
|
||||
about: faker.lorem.paragraph(),
|
||||
termsAndConditionsAgreedVersion: '0.0.1',
|
||||
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
|
||||
allowEmbedIframes: false,
|
||||
}
|
||||
defaults.slug = slugify(defaults.name, { lower: true })
|
||||
args = {
|
||||
|
||||
@ -5,8 +5,12 @@ import helpers from '~/storybook/helpers'
|
||||
import Vue from 'vue'
|
||||
|
||||
const embed = {
|
||||
image: 'https://i.ytimg.com/vi/ptCcgLM-p8k/maxresdefault_live.jpg',
|
||||
title: 'Video Titel',
|
||||
// html: null,
|
||||
description: 'Video Description',
|
||||
html:
|
||||
'<iframe width="480" height="270" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
|
||||
'<iframe width="auto" height="250" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
|
||||
}
|
||||
|
||||
const plugins = [
|
||||
@ -114,15 +118,12 @@ storiesOf('Editor', module)
|
||||
}),
|
||||
template: `<hc-editor :users="users" :value="content" />`,
|
||||
}))
|
||||
.add('Embeds', () => ({
|
||||
.add('Embeds with iframe', () => ({
|
||||
components: { HcEditor },
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
users,
|
||||
content: `
|
||||
<p>
|
||||
The following link should render a youtube video in addition to the link.
|
||||
</p>
|
||||
<a class="embed" href="https://www.youtube.com/watch?v=qkdXAtO40Fo">
|
||||
<em>https://www.youtube.com/watch?v=qkdXAtO40Fo</em>
|
||||
</a>
|
||||
@ -130,3 +131,16 @@ storiesOf('Editor', module)
|
||||
}),
|
||||
template: `<hc-editor :users="users" :value="content" />`,
|
||||
}))
|
||||
.add('Embeds with plain link', () => ({
|
||||
components: { HcEditor },
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
users,
|
||||
content: `
|
||||
<a class="embed" href="https://telegram.org/">
|
||||
<em>https://telegram.org/</em>
|
||||
</a>
|
||||
`,
|
||||
}),
|
||||
template: `<hc-editor :users="users" :value="content" />`,
|
||||
}))
|
||||
|
||||
@ -342,4 +342,84 @@ li > p {
|
||||
margin: 0 0 $space-x-small;
|
||||
}
|
||||
}
|
||||
|
||||
.ProseMirror[contenteditable='false'] {
|
||||
.embed-close-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.embed-container {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
margin: $space-small auto;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius-base;
|
||||
border: 1px solid $color-neutral-70;
|
||||
background-color: $color-neutral-90;
|
||||
}
|
||||
|
||||
.embed-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
h4 {
|
||||
margin: $space-small 0 0 $space-small;
|
||||
}
|
||||
|
||||
p,
|
||||
a {
|
||||
display: block;
|
||||
margin: 0 0 0 $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
.embed-preview-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.embed-preview-image--clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.embed-html {
|
||||
width: 100%;
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.embed-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
padding: $space-large;
|
||||
background-color: $color-neutral-100;
|
||||
}
|
||||
|
||||
.embed-buttons {
|
||||
button {
|
||||
margin-right: $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
.embed-checkbox {
|
||||
display: flex;
|
||||
|
||||
input {
|
||||
margin-right: $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
.embed-close-button {
|
||||
position: absolute;
|
||||
top: $space-x-small;
|
||||
right: $space-x-small;
|
||||
background-color: rgba(250, 249, 250, 0.6);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -35,7 +35,7 @@ describe('defaultExtensions', () => {
|
||||
it('renders mentioning as link', () => {
|
||||
const editor = createEditor()
|
||||
const expected =
|
||||
'<p>This is a post content mentioning <a href="/profile/f0628376-e692-4167-bdb4-d521de5a014f" rel="noopener noreferrer nofollow">@alicia-luettgen</a>.</p>'
|
||||
'<p>This is a post content mentioning <a href="/profile/f0628376-e692-4167-bdb4-d521de5a014f" rel="noopener noreferrer nofollow" target="_blank">@alicia-luettgen</a>.</p>'
|
||||
expect(editor.getHTML()).toEqual(expected)
|
||||
})
|
||||
})
|
||||
@ -49,7 +49,7 @@ describe('defaultExtensions', () => {
|
||||
it('renders hashtag as link', () => {
|
||||
const editor = createEditor()
|
||||
const expected =
|
||||
'<p>This is a post content with a hashtag <a href="/search/hashtag/metoo" rel="noopener noreferrer nofollow">#metoo</a>.</p>'
|
||||
'<p>This is a post content with a hashtag <a href="/search/hashtag/metoo" rel="noopener noreferrer nofollow" target="_blank">#metoo</a>.</p>'
|
||||
expect(editor.getHTML()).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import { Node } from 'tiptap'
|
||||
import pasteRule from '../commands/pasteRule'
|
||||
import { compileToFunctions } from 'vue-template-compiler'
|
||||
import Vue from 'vue'
|
||||
import EmbedComponent from '~/components/Embed/EmbedComponent'
|
||||
|
||||
Vue.component(EmbedComponent)
|
||||
const template = `<component :dataEmbedUrl="dataEmbedUrl" :embedData="embedData" :is="componentType" />`
|
||||
|
||||
const template = `
|
||||
<a class="embed" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
||||
<div v-if="embedHtml" v-html="embedHtml" />
|
||||
<em> {{ dataEmbedUrl }} </em>
|
||||
</a>
|
||||
`
|
||||
const compiledTemplate = compileToFunctions(template)
|
||||
|
||||
export default class Embed extends Node {
|
||||
@ -67,16 +66,13 @@ export default class Embed extends Node {
|
||||
embedData: {},
|
||||
}),
|
||||
async created() {
|
||||
if (!this.options) return {}
|
||||
this.embedData = await this.options.onEmbed({ url: this.dataEmbedUrl })
|
||||
if (this.options) {
|
||||
this.embedData = await this.options.onEmbed({ url: this.dataEmbedUrl })
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
embedClass() {
|
||||
return this.embedHtml ? 'embed' : ''
|
||||
},
|
||||
embedHtml() {
|
||||
const { html = '' } = this.embedData
|
||||
return html
|
||||
componentType() {
|
||||
return EmbedComponent
|
||||
},
|
||||
dataEmbedUrl: {
|
||||
get() {
|
||||
|
||||
@ -1,31 +1,30 @@
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils'
|
||||
import Vuex from 'vuex'
|
||||
import Styleguide from '@human-connection/styleguide'
|
||||
import Embed from './Embed'
|
||||
|
||||
let Wrapper
|
||||
let propsData
|
||||
let Wrapper, propsData, component
|
||||
const someUrl = 'https://www.youtube.com/watch?v=qkdXAtO40Fo'
|
||||
const localVue = createLocalVue()
|
||||
|
||||
localVue.use(Vuex)
|
||||
localVue.use(Styleguide)
|
||||
|
||||
describe('Embed.vue', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {}
|
||||
const component = new Embed()
|
||||
Wrapper = ({ mocks, propsData }) => {
|
||||
component = new Embed()
|
||||
Wrapper = ({ propsData }) => {
|
||||
return shallowMount(component.view, { propsData })
|
||||
}
|
||||
})
|
||||
|
||||
it('renders anchor', () => {
|
||||
propsData = {
|
||||
node: { attrs: { href: someUrl } },
|
||||
}
|
||||
expect(Wrapper({ propsData }).is('a')).toBe(true)
|
||||
})
|
||||
|
||||
describe('given a href', () => {
|
||||
describe('onEmbed returned embed data', () => {
|
||||
beforeEach(() => {
|
||||
propsData.options = {
|
||||
onEmbed: () => ({
|
||||
__typename: 'Embed',
|
||||
type: 'video',
|
||||
title: 'Baby Loves Cat',
|
||||
author: 'Merkley Family',
|
||||
@ -49,9 +48,7 @@ describe('Embed.vue', () => {
|
||||
propsData.node = { attrs: { href: 'https://www.youtube.com/watch?v=qkdXAtO40Fo' } }
|
||||
const wrapper = Wrapper({ propsData })
|
||||
await wrapper.html()
|
||||
expect(wrapper.find('div iframe').attributes('src')).toEqual(
|
||||
'https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed',
|
||||
)
|
||||
expect(wrapper.contains('embed-component-stub')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ export default class Link extends TipTapLink {
|
||||
{
|
||||
...node.attrs,
|
||||
rel: 'noopener noreferrer nofollow',
|
||||
target: '_blank',
|
||||
},
|
||||
0,
|
||||
],
|
||||
|
||||
@ -10,7 +10,6 @@ export default class EventHandler extends Extension {
|
||||
new Plugin({
|
||||
props: {
|
||||
transformPastedText(text) {
|
||||
// console.log('#### transformPastedText', text)
|
||||
return text.trim()
|
||||
},
|
||||
transformPastedHTML(html) {
|
||||
@ -33,7 +32,6 @@ export default class EventHandler extends Extension {
|
||||
.replace(/<p>(\s*<br ?\/?>\s*)+/gim, '<p>')
|
||||
// remove additional linebreaks when last child inside p tags
|
||||
.replace(/(\s*<br ?\/?>\s*)+<\/p>/gim, '</p>')
|
||||
// console.log('#### transformPastedHTML', html)
|
||||
return html
|
||||
},
|
||||
// transformPasted(slice) {
|
||||
|
||||
206
webapp/components/Embed/EmbedComponent.spec.js
Normal file
206
webapp/components/Embed/EmbedComponent.spec.js
Normal file
@ -0,0 +1,206 @@
|
||||
import { mount, createLocalVue } from '@vue/test-utils'
|
||||
import Vuex from 'vuex'
|
||||
import Styleguide from '@human-connection/styleguide'
|
||||
import EmbedComponent from './EmbedComponent'
|
||||
|
||||
let wrapper, propsData, getters, mocks
|
||||
const someUrl = 'https://www.youtube.com/watch?v=qkdXAtO40Fo'
|
||||
const localVue = createLocalVue()
|
||||
|
||||
localVue.use(Vuex)
|
||||
localVue.use(Styleguide)
|
||||
|
||||
describe('EmbedComponent.vue', () => {
|
||||
const Wrapper = () => {
|
||||
const store = new Vuex.Store({
|
||||
getters,
|
||||
})
|
||||
return mount(EmbedComponent, { propsData, localVue, store, mocks })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = {
|
||||
$t: a => a,
|
||||
$apollo: {
|
||||
mutate: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({ data: { UpdateUser: { allowEmbedIframes: true } } }),
|
||||
},
|
||||
$toast: {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
},
|
||||
}
|
||||
propsData = {}
|
||||
getters = {
|
||||
'auth/user': () => {
|
||||
return { id: 'u5', allowEmbedIframes: false }
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
describe('given a href only for a link ', () => {
|
||||
beforeEach(() => {
|
||||
propsData.embedData = {
|
||||
__typename: 'Embed',
|
||||
type: 'link',
|
||||
title: '👻 ✉️ Bruno... le ciel sur répondeur ! 🔮 🧠 - Clément FREZE',
|
||||
author: null,
|
||||
publisher: 'PeerTube.social',
|
||||
date: null,
|
||||
description:
|
||||
'Salut tout le monde ! Aujourd’hui, une vidéo sur le scepticisme, nous allons parler médiumnité avec le cas de Bruno CHARVET : « Bruno, un nouveau message ». Merci de rester respectueux dans les commentaires : SOURCES : Les sources des vi...',
|
||||
url: 'https://peertube.social/videos/watch/f3cb1945-a8f7-481f-a465-946c6f884e50',
|
||||
image: 'https://peertube.social/static/thumbnails/f3cb1945-a8f7-481f-a465-946c6f884e50.jpg',
|
||||
audio: null,
|
||||
video: null,
|
||||
lang: 'fr',
|
||||
sources: ['resource', 'oembed'],
|
||||
html: null,
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('shows the title', () => {
|
||||
expect(wrapper.find('h4').text()).toBe(
|
||||
'👻 ✉️ Bruno... le ciel sur répondeur ! 🔮 🧠 - Clément FREZE',
|
||||
)
|
||||
})
|
||||
|
||||
it('shows the description', () => {
|
||||
expect(wrapper.find('.embed-content p').text()).toBe(
|
||||
'Salut tout le monde ! Aujourd’hui, une vidéo sur le scepticisme, nous allons parler médiumnité avec le cas de Bruno CHARVET : « Bruno, un nouveau message ». Merci de rester respectueux dans les commentaires : SOURCES : Les sources des vi...',
|
||||
)
|
||||
})
|
||||
|
||||
it('shows preview Images for link', () => {
|
||||
expect(wrapper.find('.embed-preview-image').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given a href with embed html', () => {
|
||||
describe('onEmbed returned title and description', () => {
|
||||
beforeEach(() => {
|
||||
propsData.embedData = {
|
||||
__typename: 'Embed',
|
||||
title: 'Baby Loves Cat',
|
||||
description:
|
||||
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('show the title', () => {
|
||||
expect(wrapper.find('h4').text()).toBe('Baby Loves Cat')
|
||||
})
|
||||
|
||||
it('show the desciption', () => {
|
||||
expect(wrapper.find('.embed-content p').text()).toBe(
|
||||
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||
)
|
||||
})
|
||||
|
||||
describe('onEmbed returned embed data with html', () => {
|
||||
beforeEach(() => {
|
||||
propsData.embedData = {
|
||||
__typename: 'Embed',
|
||||
type: 'video',
|
||||
title: 'Baby Loves Cat',
|
||||
author: 'Merkley Family',
|
||||
publisher: 'YouTube',
|
||||
date: '2015-08-16T00:00:00.000Z',
|
||||
description:
|
||||
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||
url: someUrl,
|
||||
image: 'https://i.ytimg.com/vi/qkdXAtO40Fo/maxresdefault.jpg',
|
||||
audio: null,
|
||||
video: null,
|
||||
lang: 'de',
|
||||
sources: ['resource', 'oembed'],
|
||||
html:
|
||||
'<iframe width="480" height="270" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>',
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('shows a simple link when a user closes the embed preview', () => {
|
||||
wrapper.find('.embed-close-button').trigger('click')
|
||||
expect(wrapper.vm.showLinkOnly).toBe(true)
|
||||
})
|
||||
|
||||
it('opens the data privacy overlay when a user clicks on the preview image', () => {
|
||||
wrapper.find('.embed-preview-image--clickable').trigger('click')
|
||||
expect(wrapper.vm.showOverlay).toBe(true)
|
||||
})
|
||||
|
||||
describe('shows iframe', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.setData({ showOverlay: true })
|
||||
})
|
||||
|
||||
it('when user agress', () => {
|
||||
wrapper.find('.ds-button-primary').trigger('click')
|
||||
expect(wrapper.vm.showEmbed).toBe(true)
|
||||
})
|
||||
|
||||
it('does not show iframe when user clicks to cancel', () => {
|
||||
wrapper.find('.ds-button-ghost').trigger('click')
|
||||
expect(wrapper.vm.showEmbed).toBe(false)
|
||||
})
|
||||
|
||||
describe("doesn't set permanently", () => {
|
||||
beforeEach(() => {
|
||||
wrapper.find('.ds-button-primary').trigger('click')
|
||||
})
|
||||
|
||||
it("if user doesn't give consent", () => {
|
||||
expect(wrapper.vm.checkedAlwaysAllowEmbeds).toBe(false)
|
||||
})
|
||||
|
||||
it("doesn't update the user's profile", () => {
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('sets permanently', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.find('input[type=checkbox]').trigger('click')
|
||||
wrapper.find('.ds-button-primary').trigger('click')
|
||||
})
|
||||
|
||||
it('changes setting permanetly when user requests', () => {
|
||||
expect(wrapper.vm.checkedAlwaysAllowEmbeds).toBe(true)
|
||||
})
|
||||
|
||||
it("updates the user's profile", () => {
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('immediately shows', () => {
|
||||
beforeEach(() => {
|
||||
getters = {
|
||||
'auth/user': () => {
|
||||
return { id: 'u5', allowEmbedIframes: true }
|
||||
},
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('sets showEmbed to true', () => {
|
||||
expect(wrapper.vm.showEmbed).toBe(true)
|
||||
})
|
||||
|
||||
it('the iframe returned from oEmbed', () => {
|
||||
expect(wrapper.find('iframe').html()).toEqual(propsData.embedData.html)
|
||||
})
|
||||
|
||||
it('does not display image to click', () => {
|
||||
expect(wrapper.find('.embed-preview-image--clickable').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
153
webapp/components/Embed/EmbedComponent.vue
Normal file
153
webapp/components/Embed/EmbedComponent.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<a v-if="showLinkOnly" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
||||
{{ dataEmbedUrl }}
|
||||
</a>
|
||||
<ds-container v-else width="small" class="embed-container">
|
||||
<section class="embed-content">
|
||||
<div v-if="showEmbed" v-html="embedHtml" class="embed-html" />
|
||||
<template v-else>
|
||||
<img
|
||||
v-if="embedHtml && embedImage"
|
||||
:src="embedImage"
|
||||
class="embed-preview-image embed-preview-image--clickable"
|
||||
@click.prevent="openOverlay()"
|
||||
/>
|
||||
<img v-else-if="embedImage" :src="embedImage" class="embed-preview-image" />
|
||||
</template>
|
||||
<h4 v-if="embedTitle">{{ embedTitle }}</h4>
|
||||
<p v-if="embedDescription">{{ embedDescription }}</p>
|
||||
<a class="embed" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
||||
{{ dataEmbedUrl }}
|
||||
</a>
|
||||
</section>
|
||||
<aside v-if="showOverlay" class="embed-overlay">
|
||||
<h3>{{ $t('editor.embed.data_privacy_warning') }}</h3>
|
||||
<ds-text>{{ $t('editor.embed.data_privacy_info') }} {{ embedPublisher }}</ds-text>
|
||||
<div class="embed-buttons">
|
||||
<ds-button primary @click.prevent="allowEmbed()">
|
||||
{{ $t('editor.embed.play_now') }}
|
||||
</ds-button>
|
||||
<ds-button ghost @click.prevent="closeOverlay()">{{ $t('actions.cancel') }}</ds-button>
|
||||
</div>
|
||||
<label class="embed-checkbox">
|
||||
<input type="checkbox" v-model="checkedAlwaysAllowEmbeds" />
|
||||
<span>{{ $t('editor.embed.always_allow') }}</span>
|
||||
</label>
|
||||
</aside>
|
||||
<ds-button
|
||||
icon="close"
|
||||
ghost
|
||||
size="small"
|
||||
class="embed-close-button"
|
||||
@click.prevent="removeEmbed()"
|
||||
/>
|
||||
</ds-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { allowEmbedIframesMutation } from '~/graphql/User.js'
|
||||
|
||||
export default {
|
||||
name: 'embed-component',
|
||||
props: {
|
||||
dataEmbedUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
embedData: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
checkedAlwaysAllowEmbeds: false,
|
||||
showEmbed: false,
|
||||
showOverlay: false,
|
||||
showLinkOnly: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.currentUser.allowEmbedIframes) {
|
||||
this.showEmbed = this.currentUser.allowEmbedIframes
|
||||
this.checkedAlwaysAllowEmbeds = this.currentUser.allowEmbedIframes
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
embedHtml() {
|
||||
const { html = '' } = this.embedData
|
||||
return html
|
||||
},
|
||||
embedImage() {
|
||||
const { image = '' } = this.embedData
|
||||
return image
|
||||
},
|
||||
embedPublisher() {
|
||||
const { publisher = '' } = this.embedData
|
||||
return publisher
|
||||
},
|
||||
embedTitle() {
|
||||
const { title = '' } = this.embedData
|
||||
return title
|
||||
},
|
||||
embedAuthor() {
|
||||
const { author = '' } = this.embedData
|
||||
return author
|
||||
},
|
||||
embedDescription() {
|
||||
const { description = '' } = this.embedData
|
||||
return description
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setCurrentUser: 'auth/SET_USER',
|
||||
}),
|
||||
openOverlay() {
|
||||
this.showOverlay = true
|
||||
},
|
||||
closeOverlay() {
|
||||
this.showOverlay = false
|
||||
},
|
||||
allowEmbed() {
|
||||
this.showEmbed = true
|
||||
this.closeOverlay()
|
||||
|
||||
if (this.checkedAlwaysAllowEmbeds !== this.currentUser.allowEmbedIframes) {
|
||||
this.updateEmbedSettings(this.checkedAlwaysAllowEmbeds)
|
||||
}
|
||||
},
|
||||
removeEmbed() {
|
||||
this.showLinkOnly = true
|
||||
},
|
||||
async updateEmbedSettings(allowEmbedIframes) {
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: allowEmbedIframesMutation(),
|
||||
variables: {
|
||||
id: this.currentUser.id,
|
||||
allowEmbedIframes,
|
||||
},
|
||||
update: (store, { data: { UpdateUser } }) => {
|
||||
const { allowEmbedIframes } = UpdateUser
|
||||
this.setCurrentUser({
|
||||
...this.currentUser,
|
||||
allowEmbedIframes,
|
||||
})
|
||||
},
|
||||
})
|
||||
this.$toast.success(this.$t('contribution.success'))
|
||||
this.showEmbed = this.currentUser.allowEmbedIframes
|
||||
} catch (err) {
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -135,6 +135,17 @@ export const unfollowUserMutation = i18n => {
|
||||
`
|
||||
}
|
||||
|
||||
export const allowEmbedIframesMutation = () => {
|
||||
return gql`
|
||||
mutation($id: ID!, $allowEmbedIframes: Boolean) {
|
||||
UpdateUser(id: $id, allowEmbedIframes: $allowEmbedIframes) {
|
||||
id
|
||||
allowEmbedIframes
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export const checkSlugAvailableQuery = gql`
|
||||
query($slug: String!) {
|
||||
User(slug: $slug) {
|
||||
|
||||
@ -108,6 +108,12 @@
|
||||
"noHashtagsFound": "Keine Hashtags gefunden",
|
||||
"addHashtag": "Neuer Hashtag",
|
||||
"addLetter": "Tippe einen Buchstaben"
|
||||
},
|
||||
"embed": {
|
||||
"data_privacy_warning": "Achte auf deine Daten!",
|
||||
"data_privacy_info": "Deine Daten wurden noch nicht an Drittanbieter weitergegeben. Wenn du dieses Video jetzt abspielst, registriert der folgende Anbieter wahrscheinlich deine Nutzerdaten:",
|
||||
"play_now": "Jetzt ansehen",
|
||||
"always_allow": "Inhalte von Drittanbietern immer anzeigen (diese Einstellung kannst du jederzeit ändern)"
|
||||
}
|
||||
},
|
||||
"profile": {
|
||||
@ -337,6 +343,19 @@
|
||||
"submitted": "Kommentar Gesendet",
|
||||
"updated": "Änderungen gespeichert"
|
||||
},
|
||||
"allowEmbeds": {
|
||||
"name": "Drittanbieter",
|
||||
"info-description": "Wenn du zustimmst werden in den Beiträgen aus der folgenden Liste an Providern Fremdcode von anderen Anbietern (Drittanbietern) in Form von eingebundenen Videos, Bilder oder Text automatisch eingebunden werden.",
|
||||
"description": "Du hast zugestimmt das in den Beiträgen aus der folgenden Liste an Providern Fremdcode von anderen Anbietern (Drittanbietern) in Form von eingebundenen Videos, Bilder oder Text automatisch eingebunden werden.",
|
||||
"statustext": "Momentan ist das automatische einbinden:",
|
||||
"statuschange": "Einstellung ändern",
|
||||
"false": "Abgestellt",
|
||||
"true": "Zugelassen",
|
||||
"button-tofalse": "Abstellen",
|
||||
"button-totrue": "dauerhaft zulassen",
|
||||
"third-party-false": "Es wird <b style='color:red'>kein</b> Service von Drittanbietern automatisch eingebunden.",
|
||||
"third-party-true": "Das einbinden der Services von Drittanbietern ist <b style='color:red'>dauerhaft zugelassen</b> und gespeichert für komende Sitzungen."
|
||||
},
|
||||
"edited": "bearbeitet"
|
||||
},
|
||||
"comment": {
|
||||
|
||||
@ -109,6 +109,12 @@
|
||||
"noHashtagsFound": "No hashtags found",
|
||||
"addHashtag": "New hashtag",
|
||||
"addLetter": "Type a letter"
|
||||
},
|
||||
"embed": {
|
||||
"data_privacy_warning": "Data Privacy Warning!",
|
||||
"data_privacy_info": "Your data has not yet been shared with any third party providers. If you proceed to watch this video the following provider will likely collect user data:",
|
||||
"play_now": "Watch now",
|
||||
"always_allow": "Always allow embedded content by third party providers (this setting can be changed any time)"
|
||||
}
|
||||
},
|
||||
"profile": {
|
||||
@ -338,6 +344,19 @@
|
||||
"submitted": "Comment Submitted",
|
||||
"updated": "Changes Saved"
|
||||
},
|
||||
"allowEmbeds": {
|
||||
"name": "Third party providers",
|
||||
"info-description": "If you agree, the posts from the following list of providers will automatically include third-party code from other providers (third parties) in the form of embedded videos, images, or text.",
|
||||
"description": "You have agreed that in the contributions from the following list of providers, foreign code from other providers (third parties) in the form of embedded videos, images or text automatically are embedded.",
|
||||
"statustext": "At the moment this is automatic embedding:",
|
||||
"statuschange": "Change setting",
|
||||
"false": "Turned off",
|
||||
"true": "Admitted",
|
||||
"button-tofalse": "turn-off",
|
||||
"button-totrue": "allow permanently",
|
||||
"third-party-false": "It automatically integrates <b style='color:red'>no </b> third-party providers' service.",
|
||||
"third-party-true": "The inclusion of third-party services is <b style='color:red'>permanently allowed</b> and stored for future sessions."
|
||||
},
|
||||
"edited": "edited"
|
||||
},
|
||||
"comment": {
|
||||
|
||||
@ -6,6 +6,7 @@ export default async ({ store, env, route, redirect }) => {
|
||||
if (publicPages.indexOf(route.name) >= 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (route.name === 'terms-and-conditions-confirm') return true // avoid endless loop
|
||||
|
||||
if (store.getters['auth/termsAndConditionsAgreed']) return true
|
||||
|
||||
@ -133,4 +133,4 @@
|
||||
"vue-svg-loader": "~0.12.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,6 +39,10 @@ export default {
|
||||
name: this.$t('settings.blocked-users.name'),
|
||||
path: `/settings/blocked-users`,
|
||||
},
|
||||
{
|
||||
name: this.$t('post.allowEmbeds.name'),
|
||||
path: `/settings/allow-embeds`,
|
||||
},
|
||||
{
|
||||
name: this.$t('settings.deleteUserAccount.name'),
|
||||
path: `/settings/delete-account`,
|
||||
|
||||
117
webapp/pages/settings/allow-embeds.vue
Normal file
117
webapp/pages/settings/allow-embeds.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<ds-card :header="$t('post.allowEmbeds.name')">
|
||||
<p>{{ $t('post.allowEmbeds.statustext') }}</p>
|
||||
<ds-container width="large">
|
||||
<h3 v-html="allowEmbeds_h3" />
|
||||
<div v-html="allowEmbeds_desc" />
|
||||
</ds-container>
|
||||
<div>
|
||||
<ds-space />
|
||||
<ds-space />
|
||||
<p>{{ $t('post.allowEmbeds.statuschange') }}</p>
|
||||
<ds-container width="large">
|
||||
<ds-flex>
|
||||
<ds-flex-item>
|
||||
<ds-button @click="toFalse" :disabled="!disabled">
|
||||
{{ $t('post.allowEmbeds.button-tofalse') }}
|
||||
</ds-button>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item>
|
||||
<ds-button @click="toTrue" secondary :disabled="disabled">
|
||||
{{ $t('post.allowEmbeds.button-totrue') }}
|
||||
</ds-button>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-container>
|
||||
</div>
|
||||
<ds-space />
|
||||
<ds-space />
|
||||
|
||||
<div>
|
||||
<p v-if="disabled">
|
||||
<b>{{ $t('post.allowEmbeds.description') }}</b>
|
||||
</p>
|
||||
<p v-else>{{ $t('post.allowEmbeds.info-description') }}</p>
|
||||
<ds-container>
|
||||
<ds-placeholder>
|
||||
<ul>
|
||||
<li v-for="provider in providers" :key="provider.provider_name">
|
||||
{{ provider.provider_name }},
|
||||
<small>{{ provider.provider_url }}</small>
|
||||
</li>
|
||||
</ul>
|
||||
</ds-placeholder>
|
||||
</ds-container>
|
||||
</div>
|
||||
</ds-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { allowEmbedIframesMutation } from '~/graphql/User.js'
|
||||
|
||||
export default {
|
||||
head() {
|
||||
return {
|
||||
title: this.$t('post.allowEmbeds.name'),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
allowEmbeds_h3: this.$t('post.allowEmbeds.false'),
|
||||
allowEmbeds_desc: this.$t('post.allowEmbeds.third-party-false'),
|
||||
disabled: null,
|
||||
providers: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios.get('../api/providers.json').then(response => {
|
||||
this.providers = response.data
|
||||
})
|
||||
this.disabled = this.currentUser.allowEmbedIframes
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setCurrentUser: 'auth/SET_USER',
|
||||
}),
|
||||
toFalse() {
|
||||
this.allowEmbeds_h3 = this.$t('post.allowEmbeds.false')
|
||||
this.allowEmbeds_desc = this.$t('post.allowEmbeds.third-party-false')
|
||||
this.submit()
|
||||
},
|
||||
toTrue() {
|
||||
this.allowEmbeds_h3 = this.$t('post.allowEmbeds.true')
|
||||
this.allowEmbeds_desc = this.$t('post.allowEmbeds.third-party-true')
|
||||
this.submit()
|
||||
},
|
||||
async submit() {
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: allowEmbedIframesMutation(),
|
||||
variables: {
|
||||
id: this.currentUser.id,
|
||||
allowEmbedIframes: !this.disabled,
|
||||
},
|
||||
update: (store, { data: { UpdateUser } }) => {
|
||||
const { allowEmbedIframes } = UpdateUser
|
||||
this.setCurrentUser({
|
||||
...this.currentUser,
|
||||
allowEmbedIframes,
|
||||
})
|
||||
},
|
||||
})
|
||||
this.$toast.success(this.$t('site.thanks') + ' ' + this.allowEmbeds_h3)
|
||||
this.disabled = !this.disabled
|
||||
} catch (err) {
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -86,6 +86,7 @@ export const actions = {
|
||||
locationName
|
||||
contributionsCount
|
||||
commentedCount
|
||||
allowEmbedIframes
|
||||
termsAndConditionsAgreedVersion
|
||||
socialMedia {
|
||||
id
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user