sforkowany z mirror/social
rodzic
a2fca565a1
commit
ee1b2945bb
|
@ -81,10 +81,16 @@ return [
|
|||
['name' => 'Api#savedSearches', 'url' => '/api/saved_searches/list.json', 'verb' => 'GET'],
|
||||
['name' => 'Api#timelines', 'url' => '/api/v1/timelines/{timeline}/', 'verb' => 'GET'],
|
||||
['name' => 'Api#notifications', 'url' => '/api/v1/notifications', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'MediaApi#uploadMedia', 'url' => '/api/v1/media', 'verb' => 'POST'],
|
||||
['name' => 'MediaApi#updateMedia', 'url' => '/api/v1/media/{id}', 'verb' => 'PUT'],
|
||||
['name' => 'MediaApi#deleteMedia', 'url' => '/api/v1/media/{id}', 'verb' => 'DELETE'],
|
||||
['name' => 'MediaApi#getMedia', 'url' => '/media/{shortcode}.{extension}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'StatusApi#publishStatus', 'url' => '/api/v1/statuses', 'verb' => 'POST'],
|
||||
['name' => 'StatusApi#getStatus', 'url' => '/api/v1/statuses/{id}', 'verb' => 'GET'],
|
||||
['name' => 'StatusApi#deleteStatus', 'url' => '/api/v1/statuses/{id}', 'verb' => 'DELETE'],
|
||||
['name' => 'StatusApi#contextStatus', 'url' => '/api/v1/statuses/{id}/context', 'verb' => 'GET'],
|
||||
['name' => 'StatusApi#reblogedBy', 'url' => '/api/v1/statuses/{id}/reblogged_by', 'verb' => 'GET'],
|
||||
|
||||
// Api for local front-end
|
||||
// TODO: front-end should be using the new ApiController
|
||||
|
|
|
@ -118,7 +118,7 @@ export default {
|
|||
AppContent,
|
||||
AppNavigation,
|
||||
AppNavigationItem,
|
||||
Search,
|
||||
Search
|
||||
},
|
||||
mixins: [currentuserMixin],
|
||||
data: function() {
|
||||
|
|
|
@ -25,12 +25,12 @@
|
|||
<div class="new-post" data-id="">
|
||||
<input id="file-upload"
|
||||
ref="fileUploadInput"
|
||||
@change="handleFileChange($event)"
|
||||
multiple
|
||||
type="file"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
class="hidden-visually">
|
||||
class="hidden-visually"
|
||||
@change="handleFileChange($event)">
|
||||
<div class="new-post-author">
|
||||
<avatar :user="currentUser.uid" :display-name="currentUser.displayName" :disable-tooltip="true"
|
||||
:size="32" />
|
||||
|
@ -62,13 +62,13 @@
|
|||
@tribute-replaced="updatePostFromTribute" />
|
||||
</vue-tribute>
|
||||
|
||||
<PreviewGrid :uploading="false" :uploadProgress="0.4" :miniatures="previewUrls" />
|
||||
<PreviewGrid :uploading="false" :upload-progress="0.4" :miniatures="previewUrls" />
|
||||
|
||||
<div class="options">
|
||||
<Button type="tertiary"
|
||||
@click.prevent="clickImportInput"
|
||||
<Button v-tooltip="t('social', 'Add attachment')"
|
||||
type="tertiary"
|
||||
:aria-label="t('social', 'Add attachment')"
|
||||
v-tooltip="t('social', 'Add attachment')">
|
||||
@click.prevent="clickImportInput">
|
||||
<template #icon>
|
||||
<FileUpload :size="22" decorative title="" />
|
||||
</template>
|
||||
|
@ -78,10 +78,10 @@
|
|||
<EmojiPicker ref="emojiPicker" :search="search" :close-on-select="false"
|
||||
:container="container"
|
||||
@select="insert">
|
||||
<Button type="tertiary"
|
||||
<Button v-tooltip="t('social', 'Add emoji')"
|
||||
type="tertiary"
|
||||
:aria-haspopup="true"
|
||||
:aria-label="t('social', 'Add emoji')"
|
||||
v-tooltip="t('social', 'Add emoji')">
|
||||
:aria-label="t('social', 'Add emoji')">
|
||||
<template #icon>
|
||||
<EmoticonOutline :size="22" decorative title="" />
|
||||
</template>
|
||||
|
@ -90,10 +90,10 @@
|
|||
</div>
|
||||
|
||||
<div v-click-outside="hidePopoverMenu" class="popovermenu-parent">
|
||||
<Button type="tertiary"
|
||||
<Button v-tooltip="t('social', 'Visibility')"
|
||||
type="tertiary"
|
||||
:class="currentVisibilityIconClass"
|
||||
@click.prevent="togglePopoverMenu"
|
||||
v-tooltip="t('social', 'Visibility')" />
|
||||
@click.prevent="togglePopoverMenu" />
|
||||
<div :class="{open: menuOpened}" class="popovermenu">
|
||||
<popover-menu :menu="visibilityPopover" />
|
||||
</div>
|
||||
|
@ -142,10 +142,10 @@ export default {
|
|||
EmoticonOutline,
|
||||
Button,
|
||||
Send,
|
||||
PreviewGrid,
|
||||
PreviewGrid
|
||||
},
|
||||
directives: {
|
||||
FocusOnCreate,
|
||||
FocusOnCreate
|
||||
},
|
||||
mixins: [CurrentUserMixin],
|
||||
props: {},
|
||||
|
@ -288,6 +288,14 @@ export default {
|
|||
currentVisibilityPostLabel() {
|
||||
return this.visibilityPostLabel(this.type)
|
||||
},
|
||||
message: {
|
||||
get() {
|
||||
return this.$store.state.obj.message
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('updateStatus', value)
|
||||
}
|
||||
},
|
||||
visibilityPostLabel() {
|
||||
return (type) => {
|
||||
if (typeof type === 'undefined') {
|
||||
|
@ -362,7 +370,7 @@ export default {
|
|||
},
|
||||
canPost() {
|
||||
if (this.previewUrls.length > 0) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
return this.post.length !== 0 && this.post !== '<br>'
|
||||
}
|
||||
|
@ -407,13 +415,17 @@ export default {
|
|||
this.menuOpened = false
|
||||
localStorage.setItem('social.lastPostType', type)
|
||||
},
|
||||
getPostData() {
|
||||
keyup(event) {
|
||||
if (event.shiftKey || event.ctrlKey) {
|
||||
this.createPost(event)
|
||||
}
|
||||
},
|
||||
updatePostFromTribute(event) {
|
||||
// Trick to let vue-contenteditable know that tribute replaced a mention or hashtag
|
||||
this.$refs.composerInput.oninput(event)
|
||||
},
|
||||
createPost: async function(event) {
|
||||
let element = this.$refs.composerInput.cloneNode(true)
|
||||
Array.from(element.getElementsByClassName('emoji')).forEach((emoji) => {
|
||||
var em = document.createTextNode(emoji.getAttribute('alt'))
|
||||
emoji.replaceWith(em)
|
||||
})
|
||||
|
||||
let contentHtml = element.innerHTML
|
||||
|
||||
// Extract mentions from content and create an array out of them
|
||||
|
@ -427,67 +439,26 @@ export default {
|
|||
}
|
||||
} while (match)
|
||||
|
||||
// Add author of original post in case of reply
|
||||
if (this.replyTo !== null) {
|
||||
to.push(this.replyTo.actor_info.account)
|
||||
}
|
||||
|
||||
// Extract hashtags from content and create an array ot of them
|
||||
const hashtagRegex = />#([^<]+)</g
|
||||
let hashtags = []
|
||||
match = null
|
||||
do {
|
||||
match = hashtagRegex.exec(contentHtml)
|
||||
if (match) {
|
||||
hashtags.push(match[1])
|
||||
}
|
||||
} while (match)
|
||||
|
||||
// Remove all html tags but </div> (wich we turn in newlines) and decode the remaining html entities
|
||||
let content = contentHtml.replace(/<(?!\/div)[^>]+>/gi, '').replace(/<\/div>/gi, '\n').trim()
|
||||
content = he.decode(content)
|
||||
|
||||
let data = {
|
||||
content: content,
|
||||
to: to,
|
||||
hashtags: hashtags,
|
||||
type: this.type,
|
||||
attachments: this.previewUrls.map(preview => preview.result), // TODO send the summary and other props too
|
||||
}
|
||||
|
||||
if (this.replyTo) {
|
||||
data.replyTo = this.replyTo.id
|
||||
}
|
||||
|
||||
return data
|
||||
},
|
||||
keyup(event) {
|
||||
if (event.shiftKey || event.ctrlKey) {
|
||||
this.createPost(event)
|
||||
}
|
||||
},
|
||||
updatePostFromTribute(event) {
|
||||
// Trick to let vue-contenteditable know that tribute replaced a mention or hashtag
|
||||
this.$refs.composerInput.oninput(event)
|
||||
},
|
||||
createPost: async function(event) {
|
||||
|
||||
let postData = this.getPostData()
|
||||
|
||||
// Trick to validate last mention when the user directly clicks on the "post" button without validating it.
|
||||
let regex = /@([-\w]+)$/
|
||||
let lastMention = postData.content.match(regex)
|
||||
if (lastMention) {
|
||||
|
||||
// Ask the server for matching accounts, and wait for the results
|
||||
let result = await this.remoteSearchAccounts(lastMention[1])
|
||||
|
||||
// Validate the last mention only when it matches a single account
|
||||
if (result.data.result.accounts.length === 1) {
|
||||
postData.content = postData.content.replace(regex, '@' + result.data.result.accounts[0].account)
|
||||
postData.to.push(result.data.result.accounts[0].account)
|
||||
}
|
||||
}
|
||||
console.debug(content)
|
||||
this.$store.dispatch('postStatus', content)
|
||||
//
|
||||
// // Trick to validate last mention when the user directly clicks on the "post" button without validating it.
|
||||
// let regex = /@([-\w]+)$/
|
||||
// let lastMention = postData.content.match(regex)
|
||||
// if (lastMention) {
|
||||
//
|
||||
// // Ask the server for matching accounts, and wait for the results
|
||||
// let result = await this.remoteSearchAccounts(lastMention[1])
|
||||
//
|
||||
// // Validate the last mention only when it matches a single account
|
||||
// if (result.data.result.accounts.length === 1) {
|
||||
// postData.content = postData.content.replace(regex, '@' + result.data.result.accounts[0].account)
|
||||
// postData.to.push(result.data.result.accounts[0].account)
|
||||
// }
|
||||
// }
|
||||
|
||||
// Abort if the post is a direct message and no valid mentions were found
|
||||
// if (this.type === 'direct' && postData.to.length === 0) {
|
||||
|
@ -495,17 +466,6 @@ export default {
|
|||
// return
|
||||
// }
|
||||
|
||||
// Post message
|
||||
this.loading = true
|
||||
this.$store.dispatch('post', postData).then((response) => {
|
||||
this.loading = false
|
||||
this.replyTo = null
|
||||
this.post = ''
|
||||
this.$refs.composerInput.innerText = this.post
|
||||
this.previewUrls = []
|
||||
this.$store.dispatch('refreshTimeline')
|
||||
})
|
||||
|
||||
},
|
||||
closeReply() {
|
||||
this.replyTo = null
|
||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
|
||||
<template>
|
||||
<div class="upload-form">
|
||||
<div class="upload-progress" v-if="false">
|
||||
<div v-if="false" class="upload-progress">
|
||||
<div class="upload-progress__icon">
|
||||
<FileUpload :size="32" />
|
||||
</div>
|
||||
|
@ -19,7 +19,8 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
</div>
|
||||
</div>
|
||||
<div class="preview-grid">
|
||||
<PreviewGridItem v-for="(item, index) in draft.attachements" :key="index" :preview="item" :index="index" />
|
||||
<PreviewGridItem v-for="(item, index) in draft.attachements" :key="index" :preview="item"
|
||||
:index="index" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -33,27 +34,27 @@ export default {
|
|||
name: 'PreviewGrid',
|
||||
components: {
|
||||
PreviewGridItem,
|
||||
FileUpload,
|
||||
FileUpload
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
'draft': state => state.timeline.draft,
|
||||
}),
|
||||
'draft': state => state.timeline.draft
|
||||
})
|
||||
},
|
||||
props: {
|
||||
uploadProgress: {
|
||||
type: Number,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
uploading: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
miniatures: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,30 +4,31 @@
|
|||
<div class="preview-item__actions">
|
||||
<Button type="tertiary-no-background" @click="deletePreview">
|
||||
<template #icon>
|
||||
<Close :size="16" fillColor="white" />
|
||||
<Close :size="16" fill-color="white" />
|
||||
</template>
|
||||
<span>{{ t('social', 'Delete') }}</span>
|
||||
</Button>
|
||||
<Button type="tertiary-no-background" @click="showModal">
|
||||
<template #icon>
|
||||
<Edit :size="16" fillColor="white" />
|
||||
<Edit :size="16" fill-color="white" />
|
||||
</template>
|
||||
<span>{{ t('social', 'Edit') }}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="description-warning" v-if="preview.description.length === 0">
|
||||
<div v-if="preview.description.length === 0" class="description-warning">
|
||||
{{ t('social', 'No description added') }}
|
||||
</div>
|
||||
|
||||
<Modal v-if="modal" @close="closeModal" size="small">
|
||||
<Modal v-if="modal" size="small" @close="closeModal">
|
||||
<div class="modal__content">
|
||||
<label :for="`image-description-${index}`">
|
||||
{{ t('social', 'Describe for the visually impaired') }}
|
||||
</label>
|
||||
<textarea :id="`image-description-${index}`" v-model="internalDescription">
|
||||
</textarea>
|
||||
<Button type="primary" @click="closeModal">{{ t('social', 'Close') }}</Button>
|
||||
<textarea :id="`image-description-${index}`" v-model="internalDescription" />
|
||||
<Button type="primary" @click="closeModal">
|
||||
{{ t('social', 'Close') }}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
|
@ -46,12 +47,29 @@ export default {
|
|||
Close,
|
||||
Edit,
|
||||
Button,
|
||||
Modal,
|
||||
Modal
|
||||
},
|
||||
props: {
|
||||
preview: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal: false,
|
||||
internalDescription: '',
|
||||
internalDescription: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
backgroundStyle() {
|
||||
return {
|
||||
backgroundImage: `url("${this.preview.preview_url}")`
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -60,7 +78,7 @@ export default {
|
|||
methods: {
|
||||
deletePreview() {
|
||||
this.$store.dispatch('deleteAttachement', {
|
||||
id: this.preview.id,
|
||||
id: this.preview.id
|
||||
})
|
||||
},
|
||||
showModal() {
|
||||
|
@ -70,27 +88,10 @@ export default {
|
|||
this.modal = false
|
||||
this.$store.dispatch('updateAttachement', {
|
||||
id: this.preview.id,
|
||||
description: this.internalDescription,
|
||||
description: this.internalDescription
|
||||
})
|
||||
}
|
||||
},
|
||||
props: {
|
||||
preview: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
backgroundStyle() {
|
||||
return {
|
||||
backgroundImage: `url("${this.preview.preview_url}")`,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@ import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
|||
export default {
|
||||
name: 'TimelineAvatar',
|
||||
components: {
|
||||
Avatar,
|
||||
Avatar
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
userTest() {
|
||||
|
@ -33,8 +33,8 @@ export default {
|
|||
},
|
||||
avatarUrl() {
|
||||
return OC.generateUrl('/apps/social/api/v1/global/actor/avatar?id=' + this.item.attributedTo)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -33,31 +33,31 @@
|
|||
<post-attachment :attachments="item.attachment" />
|
||||
</div>
|
||||
<div v-if="this.$route.params.type !== 'notifications' && !serverData.public" class="post-actions">
|
||||
<Button type="tertiary-no-background"
|
||||
v-tooltip="t('social', 'Reply')"
|
||||
<Button v-tooltip="t('social', 'Reply')"
|
||||
type="tertiary-no-background"
|
||||
@click="reply">
|
||||
<template #icon>
|
||||
<Reply :size="20" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button type="tertiary-no-background"
|
||||
v-tooltip="t('social', 'Boost')"
|
||||
<Button v-tooltip="t('social', 'Boost')"
|
||||
type="tertiary-no-background"
|
||||
@click="boost">
|
||||
<template #icon>
|
||||
<Repeat :size="20" :fill-color="isBoosted ? 'blue' : 'black'" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button v-if="!isLiked"
|
||||
type="tertiary-no-background"
|
||||
v-tooltip="t('social', 'Like')"
|
||||
type="tertiary-no-background"
|
||||
@click="like">
|
||||
<template #icon>
|
||||
<HeartOutline :size="20" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button v-if="isLiked"
|
||||
type="tertiary-no-background"
|
||||
v-tooltip="t('social', 'Undo Like')"
|
||||
type="tertiary-no-background"
|
||||
@click="like">
|
||||
<template #icon>
|
||||
<Heart :size="20" :fill-color="'var(--color-error)'" />
|
||||
|
@ -65,8 +65,8 @@
|
|||
</Button>
|
||||
<Actions>
|
||||
<ActionButton v-if="item.actor_info.account === cloudId"
|
||||
@click="remove()"
|
||||
icon="icon-delete">
|
||||
icon="icon-delete"
|
||||
@click="remove()">
|
||||
{{ t('social', 'Delete') }}
|
||||
</ActionButton>
|
||||
</Actions>
|
||||
|
@ -105,7 +105,7 @@ export default {
|
|||
Repeat,
|
||||
Reply,
|
||||
Heart,
|
||||
HeartOutline,
|
||||
HeartOutline
|
||||
},
|
||||
mixins: [currentUser],
|
||||
props: {
|
||||
|
|
|
@ -22,5 +22,5 @@ Vue.prototype.OCA = OCA
|
|||
|
||||
/* eslint-disable-next-line no-new */
|
||||
new Vue({
|
||||
render: h => h(App),
|
||||
render: h => h(App)
|
||||
}).$mount('#settings-personal')
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
const state = {
|
||||
attachements: [],
|
||||
status: '',
|
||||
sensitive: false
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
addAttachement(state, { id, description, url, preview_url }) {
|
||||
state.attachements.push({ id, description, url, preview_url })
|
||||
},
|
||||
updateAttachement(state, { id, description, url, preview_url }) {
|
||||
const index = state.attachements.findIndex(item => {
|
||||
return id === item.id
|
||||
})
|
||||
state.attachements.splice(index, 1, { id, description, url, preview_url })
|
||||
},
|
||||
deleteAttachement(state, { id }) {
|
||||
const index = state.attachements.findIndex(item => {
|
||||
return id === item.id
|
||||
})
|
||||
state.attachements.splice(index, 1)
|
||||
},
|
||||
clearAttachements(state) {
|
||||
state.attachements.splice(0)
|
||||
},
|
||||
updateSensitive(sensitive, status) {
|
||||
state.sensitive = sensitive
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
async uploadAttachement(context, formData) {
|
||||
const res = await axios.post(generateUrl('apps/social/api/v1/media'), formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
context.commit('addAttachement', {
|
||||
id: res.data.id,
|
||||
description: res.data.description,
|
||||
url: res.data.url,
|
||||
preview_url: res.data.preview_url
|
||||
})
|
||||
},
|
||||
async updateAttachement(context, { id, description }) {
|
||||
const res = await axios.put(generateUrl('apps/social/api/v1/media/' + id), {
|
||||
description
|
||||
})
|
||||
context.commit('updateAttachement', {
|
||||
id: res.data.id,
|
||||
description: res.data.description,
|
||||
url: res.data.url,
|
||||
preview_url: res.data.preview_url
|
||||
})
|
||||
},
|
||||
async deleteAttachement(context, { id }) {
|
||||
const res = await axios.delete(generateUrl('apps/social/api/v1/media/' + id))
|
||||
context.commit('deleteAttachement', {
|
||||
id: res.data.id
|
||||
})
|
||||
},
|
||||
async postStatus({ commit, state }, text) {
|
||||
const data = {
|
||||
status: text,
|
||||
media_ids: state.attachements.map(attachement => attachement.id),
|
||||
sensitive: state.sensitive
|
||||
}
|
||||
try {
|
||||
const response = await axios.post(generateUrl('apps/social/api/v1/statuses'), data)
|
||||
} catch (error) {
|
||||
OC.Notification.showTemporary('Failed to create a post')
|
||||
Logger.error('Failed to create a post', { 'error': error.response })
|
||||
}
|
||||
commit('clearAttachements')
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import Vuex from 'vuex'
|
|||
import timeline from './timeline'
|
||||
import account from './account'
|
||||
import settings from './settings'
|
||||
import composer from './composer'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
|
@ -35,7 +36,8 @@ export default new Vuex.Store({
|
|||
modules: {
|
||||
timeline,
|
||||
account,
|
||||
settings
|
||||
settings,
|
||||
composer
|
||||
},
|
||||
strict: debug
|
||||
})
|
||||
|
|
|
@ -55,7 +55,7 @@ const state = {
|
|||
composerDisplayStatus: false,
|
||||
draft: {
|
||||
attachements: []
|
||||
},
|
||||
}
|
||||
}
|
||||
const mutations = {
|
||||
addToTimeline(state, data) {
|
||||
|
@ -115,21 +115,24 @@ const mutations = {
|
|||
Vue.set(state.timeline[parentAnnounce.id].cache[parentAnnounce.object].object.action.values, 'boosted', false)
|
||||
}
|
||||
},
|
||||
addAttachement(state, {id, description, url, preview_url}) {
|
||||
state.draft.attachements.push({id, description, url, preview_url})
|
||||
addAttachement(state, { id, description, url, preview_url }) {
|
||||
state.draft.attachements.push({ id, description, url, preview_url })
|
||||
},
|
||||
updateAttachement(state, {id, description, url, preview_url}) {
|
||||
updateAttachement(state, { id, description, url, preview_url }) {
|
||||
const index = state.draft.attachements.findIndex(item => {
|
||||
return id === item.id
|
||||
})
|
||||
state.draft.attachements.splice(index, 1, {id, description, url, preview_url})
|
||||
state.draft.attachements.splice(index, 1, { id, description, url, preview_url })
|
||||
},
|
||||
deleteAttachement(state, {id}) {
|
||||
deleteAttachement(state, { id }) {
|
||||
const index = state.draft.attachements.findIndex(item => {
|
||||
return id === item.id
|
||||
})
|
||||
state.draft.attachements.splice(index, 1)
|
||||
},
|
||||
clearAttachements(state) {
|
||||
state.draft.attachements.splice(0)
|
||||
}
|
||||
}
|
||||
const getters = {
|
||||
getComposerDisplayStatus(state) {
|
||||
|
@ -166,43 +169,44 @@ const actions = {
|
|||
const res = await axios.post(generateUrl('apps/social/api/v1/media'), formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
}
|
||||
})
|
||||
context.commit('addAttachement', {
|
||||
id: res.data.id,
|
||||
description: res.data.description,
|
||||
url: res.data.url,
|
||||
preview_url: res.data.preview_url,
|
||||
preview_url: res.data.preview_url
|
||||
})
|
||||
},
|
||||
async updateAttachement(context, {id, description}) {
|
||||
async updateAttachement(context, { id, description }) {
|
||||
const res = await axios.put(generateUrl('apps/social/api/v1/media/' + id), {
|
||||
description,
|
||||
description
|
||||
})
|
||||
context.commit('updateAttachement', {
|
||||
id: res.data.id,
|
||||
description: res.data.description,
|
||||
url: res.data.url,
|
||||
preview_url: res.data.preview_url,
|
||||
preview_url: res.data.preview_url
|
||||
})
|
||||
},
|
||||
async deleteAttachement(context, {id}) {
|
||||
async deleteAttachement(context, { id }) {
|
||||
const res = await axios.delete(generateUrl('apps/social/api/v1/media/' + id))
|
||||
context.commit('deleteAttachement', {
|
||||
id: res.data.id,
|
||||
id: res.data.id
|
||||
})
|
||||
},
|
||||
post(context, post) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.post(generateUrl('apps/social/api/v1/post'), { data: post }).then((response) => {
|
||||
Logger.info('Post created with token ' + response.data.result.token)
|
||||
resolve(response)
|
||||
}).catch((error) => {
|
||||
async postStatus({ commit, state }, text) {
|
||||
const data = {
|
||||
status: text,
|
||||
media_ids: state.draft.attachements.map(attachement => attachement.id)
|
||||
}
|
||||
try {
|
||||
const response = axios.post(generateUrl('apps/social/api/v1/statuses'), data)
|
||||
} catch (error) {
|
||||
OC.Notification.showTemporary('Failed to create a post')
|
||||
Logger.error('Failed to create a post', { 'error': error.response })
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
commit('clearAttachements')
|
||||
},
|
||||
postDelete(context, post) {
|
||||
return axios.delete(generateUrl(`apps/social/api/v1/post?id=${post.id}`)).then((response) => {
|
||||
|
|
|
@ -51,7 +51,7 @@ export default {
|
|||
name: 'SetupUser',
|
||||
components: {
|
||||
CheckboxRadioSwitch,
|
||||
SettingsSection,
|
||||
SettingsSection
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
Ładowanie…
Reference in New Issue