Merge branch 'iss-149/profile-fields-setting' into 'develop'
Profile fields setting See merge request pleroma/pleroma-fe!997
This commit is contained in:
commit
c658f57abb
@ -207,6 +207,8 @@ const getNodeInfo = async ({ store }) => {
|
||||
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
|
||||
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
|
||||
|
||||
store.dispatch('setInstanceOption', { name: 'fieldsLimits', value: metadata.fieldsLimits })
|
||||
|
||||
store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
|
||||
store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
|
||||
|
||||
|
@ -431,6 +431,7 @@ const EmojiInput = {
|
||||
const offsetBottom = offsetTop + offsetHeight
|
||||
|
||||
panel.style.top = offsetBottom + 'px'
|
||||
if (!picker) return
|
||||
picker.$el.style.top = offsetBottom + 'px'
|
||||
picker.$el.style.bottom = 'auto'
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import unescape from 'lodash/unescape'
|
||||
import merge from 'lodash/merge'
|
||||
import ImageCropper from 'src/components/image_cropper/image_cropper.vue'
|
||||
import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
|
||||
import fileSizeFormatService from 'src/components/../services/file_size_format/file_size_format.js'
|
||||
@ -16,6 +17,7 @@ const ProfileTab = {
|
||||
newLocked: this.$store.state.users.currentUser.locked,
|
||||
newNoRichText: this.$store.state.users.currentUser.no_rich_text,
|
||||
newDefaultScope: this.$store.state.users.currentUser.default_scope,
|
||||
newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })),
|
||||
hideFollows: this.$store.state.users.currentUser.hide_follows,
|
||||
hideFollowers: this.$store.state.users.currentUser.hide_followers,
|
||||
hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count,
|
||||
@ -63,6 +65,18 @@ const ProfileTab = {
|
||||
...this.$store.state.instance.emoji,
|
||||
...this.$store.state.instance.customEmoji
|
||||
] })
|
||||
},
|
||||
userSuggestor () {
|
||||
return suggestor({
|
||||
users: this.$store.state.users.users,
|
||||
updateUsersList: (query) => this.$store.dispatch('searchUsers', { query })
|
||||
})
|
||||
},
|
||||
fieldsLimits () {
|
||||
return this.$store.state.instance.fieldsLimits
|
||||
},
|
||||
maxFields () {
|
||||
return this.fieldsLimits ? this.fieldsLimits.maxFields : 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -75,6 +89,7 @@ const ProfileTab = {
|
||||
// Backend notation.
|
||||
/* eslint-disable camelcase */
|
||||
display_name: this.newName,
|
||||
fields_attributes: this.newFields.filter(el => el != null),
|
||||
default_scope: this.newDefaultScope,
|
||||
no_rich_text: this.newNoRichText,
|
||||
hide_follows: this.hideFollows,
|
||||
@ -87,6 +102,8 @@ const ProfileTab = {
|
||||
show_role: this.showRole
|
||||
/* eslint-enable camelcase */
|
||||
} }).then((user) => {
|
||||
this.newFields.splice(user.fields.length)
|
||||
merge(this.newFields, user.fields)
|
||||
this.$store.commit('addNewUsers', [user])
|
||||
this.$store.commit('setCurrentUser', user)
|
||||
})
|
||||
@ -94,6 +111,16 @@ const ProfileTab = {
|
||||
changeVis (visibility) {
|
||||
this.newDefaultScope = visibility
|
||||
},
|
||||
addField () {
|
||||
if (this.newFields.length < this.maxFields) {
|
||||
this.newFields.push({ name: '', value: '' })
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
deleteField (index, event) {
|
||||
this.$delete(this.newFields, index)
|
||||
},
|
||||
uploadFile (slot, e) {
|
||||
const file = e.target.files[0]
|
||||
if (!file) { return }
|
||||
|
@ -79,4 +79,21 @@
|
||||
.setting-subitem {
|
||||
margin-left: 1.75em;
|
||||
}
|
||||
|
||||
.profile-fields {
|
||||
display: flex;
|
||||
|
||||
&>.emoji-input {
|
||||
flex: 1 1 auto;
|
||||
margin: 0 .2em .5em;
|
||||
}
|
||||
|
||||
&>.icon-container {
|
||||
width: 20px;
|
||||
|
||||
&>.icon-cancel {
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,54 @@
|
||||
{{ $t('settings.discoverable') }}
|
||||
</Checkbox>
|
||||
</p>
|
||||
<div v-if="maxFields > 0">
|
||||
<p>{{ $t('settings.profile_fields.label') }}</p>
|
||||
<div
|
||||
v-for="(_, i) in newFields"
|
||||
:key="i"
|
||||
class="profile-fields"
|
||||
>
|
||||
<EmojiInput
|
||||
v-model="newFields[i].name"
|
||||
enable-emoji-picker
|
||||
hide-emoji-button
|
||||
:suggest="userSuggestor"
|
||||
>
|
||||
<input
|
||||
v-model="newFields[i].name"
|
||||
:placeholder="$t('settings.profile_fields.name')"
|
||||
>
|
||||
</EmojiInput>
|
||||
<EmojiInput
|
||||
v-model="newFields[i].value"
|
||||
enable-emoji-picker
|
||||
hide-emoji-button
|
||||
:suggest="userSuggestor"
|
||||
>
|
||||
<input
|
||||
v-model="newFields[i].value"
|
||||
:placeholder="$t('settings.profile_fields.value')"
|
||||
>
|
||||
</EmojiInput>
|
||||
<div
|
||||
class="icon-container"
|
||||
>
|
||||
<i
|
||||
v-show="newFields.length > 1"
|
||||
class="icon-cancel"
|
||||
@click="deleteField(i)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
v-if="newFields.length < maxFields"
|
||||
class="add-field faint"
|
||||
@click="addField"
|
||||
>
|
||||
<i class="icon-plus" />
|
||||
{{ $t("settings.profile_fields.add_field") }}
|
||||
</a>
|
||||
</div>
|
||||
<p>
|
||||
<Checkbox v-model="bot">
|
||||
{{ $t('settings.bot') }}
|
||||
|
@ -334,6 +334,12 @@
|
||||
"loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")",
|
||||
"mutes_tab": "Mutes",
|
||||
"play_videos_in_modal": "Play videos in a popup frame",
|
||||
"profile_fields": {
|
||||
"label": "Profile metadata",
|
||||
"add_field": "Add Field",
|
||||
"name": "Label",
|
||||
"value": "Content"
|
||||
},
|
||||
"use_contain_fit": "Don't crop the attachment in thumbnails",
|
||||
"name": "Name",
|
||||
"name_bio": "Name & Bio",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
||||
import oauthApi from '../services/new_api/oauth.js'
|
||||
import { compact, map, each, merge, last, concat, uniq } from 'lodash'
|
||||
import { compact, map, each, mergeWith, last, concat, uniq, isArray } from 'lodash'
|
||||
import { set } from 'vue'
|
||||
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
|
||||
|
||||
@ -10,7 +10,7 @@ export const mergeOrAdd = (arr, obj, item) => {
|
||||
const oldItem = obj[item.id]
|
||||
if (oldItem) {
|
||||
// We already have this, so only merge the new info.
|
||||
merge(oldItem, item)
|
||||
mergeWith(oldItem, item, mergeArrayLength)
|
||||
return { item: oldItem, new: false }
|
||||
} else {
|
||||
// This is a new item, prepare it
|
||||
@ -23,6 +23,13 @@ export const mergeOrAdd = (arr, obj, item) => {
|
||||
}
|
||||
}
|
||||
|
||||
const mergeArrayLength = (oldValue, newValue) => {
|
||||
if (isArray(oldValue) && isArray(newValue)) {
|
||||
oldValue.length = newValue.length
|
||||
return mergeWith(oldValue, newValue, mergeArrayLength)
|
||||
}
|
||||
}
|
||||
|
||||
const getNotificationPermission = () => {
|
||||
const Notification = window.Notification
|
||||
|
||||
@ -116,7 +123,7 @@ export const mutations = {
|
||||
},
|
||||
setCurrentUser (state, user) {
|
||||
state.lastLoginName = user.screen_name
|
||||
state.currentUser = merge(state.currentUser || {}, user)
|
||||
state.currentUser = mergeWith(state.currentUser || {}, user, mergeArrayLength)
|
||||
},
|
||||
clearCurrentUser (state) {
|
||||
state.currentUser = false
|
||||
|
@ -18,6 +18,42 @@ describe('The users module', () => {
|
||||
expect(state.users).to.eql([user])
|
||||
expect(state.users[0].name).to.eql('Dude')
|
||||
})
|
||||
|
||||
it('merging array field in new information for old users', () => {
|
||||
const state = cloneDeep(defaultState)
|
||||
const user = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 1', value: 'Content 1' }
|
||||
]
|
||||
}
|
||||
const firstModUser = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 2', value: 'Content 2' },
|
||||
{ name: 'Label 3', value: 'Content 3' }
|
||||
]
|
||||
}
|
||||
const secondModUser = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 4', value: 'Content 4' }
|
||||
]
|
||||
}
|
||||
|
||||
mutations.addNewUsers(state, [user])
|
||||
expect(state.users[0].fields).to.have.length(1)
|
||||
expect(state.users[0].fields[0].name).to.eql('Label 1')
|
||||
|
||||
mutations.addNewUsers(state, [firstModUser])
|
||||
expect(state.users[0].fields).to.have.length(2)
|
||||
expect(state.users[0].fields[0].name).to.eql('Label 2')
|
||||
expect(state.users[0].fields[1].name).to.eql('Label 3')
|
||||
|
||||
mutations.addNewUsers(state, [secondModUser])
|
||||
expect(state.users[0].fields).to.have.length(1)
|
||||
expect(state.users[0].fields[0].name).to.eql('Label 4')
|
||||
})
|
||||
})
|
||||
|
||||
describe('findUser', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user