Merge pull request 'Add private note field to user profile' (#9) from sfr/pleroma-fe:notes into develop

Reviewed-on: AkkomaGang/pleroma-fe#9
This commit is contained in:
floatingghost 2022-06-23 14:33:18 +00:00
commit c71405ccad
5 changed files with 80 additions and 5 deletions

View file

@ -7,6 +7,7 @@ import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import RichContent from 'src/components/rich_content/rich_content.jsx' import RichContent from 'src/components/rich_content/rich_content.jsx'
import List from '../list/list.vue' import List from '../list/list.vue'
import withLoadMore from '../../hocs/with_load_more/with_load_more' import withLoadMore from '../../hocs/with_load_more/with_load_more'
import { debounce } from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faCircleNotch faCircleNotch
@ -40,7 +41,9 @@ const UserProfile = {
error: false, error: false,
userId: null, userId: null,
tab: defaultTabKey, tab: defaultTabKey,
footerRef: null footerRef: null,
note: null,
noteLoading: false
} }
}, },
created () { created () {
@ -110,9 +113,13 @@ const UserProfile = {
const user = this.$store.getters.findUser(userNameOrId) const user = this.$store.getters.findUser(userNameOrId)
if (user) { if (user) {
loadById(user.id) loadById(user.id)
this.note = user.relationship.note
} else { } else {
this.$store.dispatch('fetchUser', userNameOrId) this.$store.dispatch('fetchUser', userNameOrId)
.then(({ id }) => loadById(id)) .then(({ id, relationship }) => {
this.note = relationship.note
return loadById(id)
})
.catch((reason) => { .catch((reason) => {
const errorMessage = get(reason, 'error.error') const errorMessage = get(reason, 'error.error')
if (errorMessage === 'No user with such user_id') { // Known error if (errorMessage === 'No user with such user_id') { // Known error
@ -145,7 +152,15 @@ const UserProfile = {
if (target.tagName === 'A') { if (target.tagName === 'A') {
window.open(target.href, '_blank') window.open(target.href, '_blank')
} }
} },
setNote () {
this.noteLoading = true
this.debounceSetNote()
},
debounceSetNote: debounce(function () {
this.$store.dispatch('setNote', { id: this.userId, note: this.note })
this.noteLoading = false
}, 1500)
}, },
watch: { watch: {
'$route.params.id': function (newVal) { '$route.params.id': function (newVal) {

View file

@ -40,6 +40,27 @@
</dd> </dd>
</dl> </dl>
</div> </div>
<div
v-if="!isUs"
class="note"
>
<textarea
v-model="note"
class="resize-height"
:placeholder="$t('user_card.note')"
@input="setNote"
/>
<div
v-show="noteLoading"
class="preview-spinner"
>
<FAIcon
class="fa-old-padding"
spin
icon="circle-notch"
/>
</div>
</div>
<tab-switcher <tab-switcher
:active-tab="tab" :active-tab="tab"
:render-only-focused="true" :render-only-focused="true"
@ -202,6 +223,22 @@
align-items: middle; align-items: middle;
padding: 2em; padding: 2em;
} }
.note {
position: relative;
margin: 0.5em 0.75em;
textarea {
width: 100%;
}
.preview-spinner {
position: absolute;
top: 0;
right: 0;
margin: 0.5em 0.25em;
}
}
} }
.user-profile-placeholder { .user-profile-placeholder {
.panel-body { .panel-body {

View file

@ -845,6 +845,7 @@
"domain_muted": "Unblock domain", "domain_muted": "Unblock domain",
"mute_domain": "Block domain", "mute_domain": "Block domain",
"bot": "Bot", "bot": "Bot",
"note": "Private note",
"admin_menu": { "admin_menu": {
"moderation": "Moderation", "moderation": "Moderation",
"grant_admin": "Grant Admin", "grant_admin": "Grant Admin",

View file

@ -102,6 +102,11 @@ const unmuteDomain = (store, domain) => {
.then(() => store.commit('removeDomainMute', domain)) .then(() => store.commit('removeDomainMute', domain))
} }
const setNote = (store, { id, note }) => {
return store.rootState.api.backendInteractor.setNote({ id, note })
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
export const mutations = { export const mutations = {
tagUser (state, { user: { id }, tag }) { tagUser (state, { user: { id }, tag }) {
const user = state.usersObject[id] const user = state.usersObject[id]
@ -366,6 +371,9 @@ const users = {
unmuteDomains (store, domain = []) { unmuteDomains (store, domain = []) {
return Promise.all(domain.map(domain => unmuteDomain(store, domain))) return Promise.all(domain.map(domain => unmuteDomain(store, domain)))
}, },
setNote (store, { id, note }) {
return setNote(store, { id, note })
},
fetchFriends ({ rootState, commit }, id) { fetchFriends ({ rootState, commit }, id) {
const user = rootState.users.usersObject[id] const user = rootState.users.usersObject[id]
const maxId = last(user.friendIds) const maxId = last(user.friendIds)

View file

@ -47,7 +47,7 @@ const MASTODON_PUBLIC_TIMELINE = '/api/v1/timelines/public'
const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home' const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home'
const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}` const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}`
const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context` const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
const MASTODON_USER_URL = '/api/v1/accounts' const MASTODON_USER_URL = id => `/api/v1/accounts/${id}?with_relationships=true`
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships' const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses` const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
const MASTODON_LIST_URL = id => `/api/v1/lists/${id}` const MASTODON_LIST_URL = id => `/api/v1/lists/${id}`
@ -63,6 +63,7 @@ const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute` const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe` const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe`
const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe` const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe`
const MASTODON_SET_NOTE_URL = id => `/api/v1/accounts/${id}/note`
const MASTODON_BOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/bookmark` const MASTODON_BOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/bookmark`
const MASTODON_UNBOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/unbookmark` const MASTODON_UNBOOKMARK_STATUS_URL = id => `/api/v1/statuses/${id}/unbookmark`
const MASTODON_POST_STATUS_URL = '/api/v1/statuses' const MASTODON_POST_STATUS_URL = '/api/v1/statuses'
@ -310,7 +311,7 @@ const denyUser = ({ id, credentials }) => {
} }
const fetchUser = ({ id, credentials }) => { const fetchUser = ({ id, credentials }) => {
let url = `${MASTODON_USER_URL}/${id}` const url = MASTODON_USER_URL(id)
return promisedRequest({ url, credentials }) return promisedRequest({ url, credentials })
.then((data) => parseUser(data)) .then((data) => parseUser(data))
} }
@ -948,6 +949,18 @@ const unmuteUser = ({ id, credentials }) => {
return promisedRequest({ url: MASTODON_UNMUTE_USER_URL(id), credentials, method: 'POST' }) return promisedRequest({ url: MASTODON_UNMUTE_USER_URL(id), credentials, method: 'POST' })
} }
const setNote = ({ id, note, credentials }) => {
const form = new FormData()
form.append('comment', note)
return fetch(MASTODON_SET_NOTE_URL(id), {
body: form,
headers: authHeaders(credentials),
method: 'POST'
}).then((data) => data.json())
}
const fetchMascot = ({ credentials }) => { const fetchMascot = ({ credentials }) => {
return promisedRequest({ url: MASTODON_MASCOT_URL, credentials }) return promisedRequest({ url: MASTODON_MASCOT_URL, credentials })
} }
@ -1405,6 +1418,7 @@ const apiService = {
fetchMutes, fetchMutes,
muteUser, muteUser,
unmuteUser, unmuteUser,
setNote,
subscribeUser, subscribeUser,
unsubscribeUser, unsubscribeUser,
fetchBlocks, fetchBlocks,