Merge branch 'develop' into 'iss-149/profile-fields-setting'
# Conflicts: # src/components/settings_modal/tabs/profile_tab.vue
This commit is contained in:
commit
ea0a12f604
50 changed files with 570 additions and 286 deletions
|
@ -3,6 +3,7 @@
|
|||
<Popover
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
:bound-to="{ x: 'container' }"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
|
|
|
@ -5,9 +5,20 @@ const DomainMuteCard = {
|
|||
components: {
|
||||
ProgressButton
|
||||
},
|
||||
computed: {
|
||||
user () {
|
||||
return this.$store.state.users.currentUser
|
||||
},
|
||||
muted () {
|
||||
return this.user.domainMutes.includes(this.domain)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
unmuteDomain () {
|
||||
return this.$store.dispatch('unmuteDomain', this.domain)
|
||||
},
|
||||
muteDomain () {
|
||||
return this.$store.dispatch('muteDomain', this.domain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{{ domain }}
|
||||
</div>
|
||||
<ProgressButton
|
||||
v-if="muted"
|
||||
:click="unmuteDomain"
|
||||
class="btn btn-default"
|
||||
>
|
||||
|
@ -12,6 +13,16 @@
|
|||
{{ $t('domain_mute_card.unmute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
<ProgressButton
|
||||
v-else
|
||||
:click="muteDomain"
|
||||
class="btn btn-default"
|
||||
>
|
||||
{{ $t('domain_mute_card.mute') }}
|
||||
<template slot="progress">
|
||||
{{ $t('domain_mute_card.mute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -34,5 +45,9 @@
|
|||
button {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.autosuggest-results & {
|
||||
padding-left: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -13,7 +13,7 @@ import { debounce } from 'lodash'
|
|||
|
||||
const debounceUserSearch = debounce((data, input) => {
|
||||
data.updateUsersList(input)
|
||||
}, 500, { leading: true, trailing: false })
|
||||
}, 500)
|
||||
|
||||
export default data => input => {
|
||||
const firstChar = input[0]
|
||||
|
@ -97,8 +97,8 @@ export const suggestUsers = data => input => {
|
|||
replacement: '@' + screen_name + ' '
|
||||
}))
|
||||
|
||||
// BE search users if there are no matches
|
||||
if (newUsers.length === 0 && data.updateUsersList) {
|
||||
// BE search users to get more comprehensive results
|
||||
if (data.updateUsersList) {
|
||||
debounceUserSearch(data, noPrefix)
|
||||
}
|
||||
return newUsers
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
trigger="click"
|
||||
placement="top"
|
||||
class="extra-button-popover"
|
||||
:bound-to="{ x: 'container' }"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
video,
|
||||
canvas {
|
||||
object-fit: contain;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,20 +45,6 @@ const mediaUpload = {
|
|||
this.$emit('all-uploaded')
|
||||
}
|
||||
},
|
||||
fileDrop (e) {
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
e.preventDefault() // allow dropping text like before
|
||||
this.multiUpload(e.dataTransfer.files)
|
||||
}
|
||||
},
|
||||
fileDrag (e) {
|
||||
let types = e.dataTransfer.types
|
||||
if (types.contains('Files')) {
|
||||
e.dataTransfer.dropEffect = 'copy'
|
||||
} else {
|
||||
e.dataTransfer.dropEffect = 'none'
|
||||
}
|
||||
},
|
||||
clearFile () {
|
||||
this.uploadReady = false
|
||||
this.$nextTick(() => {
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
<template>
|
||||
<div
|
||||
class="media-upload"
|
||||
@drop.prevent
|
||||
@dragover.prevent="fileDrag"
|
||||
@drop="fileDrop"
|
||||
>
|
||||
<div class="media-upload">
|
||||
<label
|
||||
class="label"
|
||||
:title="$t('tool_tip.media_upload')"
|
||||
|
|
|
@ -54,25 +54,20 @@
|
|||
flex-wrap: nowrap;
|
||||
padding: 0.6em;
|
||||
min-width: 0;
|
||||
|
||||
.avatar-container {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.status-el {
|
||||
.status {
|
||||
padding: 0.25em 0;
|
||||
color: $fallback--faint;
|
||||
color: var(--faint, $fallback--faint);
|
||||
a {
|
||||
color: var(--faintLink);
|
||||
}
|
||||
.status-content a {
|
||||
color: var(--postFaintLink);
|
||||
}
|
||||
|
||||
.status-body {
|
||||
color: $fallback--faint;
|
||||
color: var(--faint, $fallback--faint);
|
||||
a {
|
||||
color: var(--faintLink);
|
||||
}
|
||||
padding: 0;
|
||||
.media-body {
|
||||
margin: 0;
|
||||
.status-content a {
|
||||
color: var(--postFaintLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<span class="result-percentage">
|
||||
{{ percentageForOption(option.votes_count) }}%
|
||||
</span>
|
||||
<span>{{ option.title }}</span>
|
||||
<span v-html="option.title_html"></span>
|
||||
</div>
|
||||
<div
|
||||
class="result-fill"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
const Popover = {
|
||||
name: 'Popover',
|
||||
props: {
|
||||
|
@ -10,6 +9,9 @@ const Popover = {
|
|||
// 'container' for using offsetParent as boundaries for either axis
|
||||
// or 'viewport'
|
||||
boundTo: Object,
|
||||
// Takes a selector to use as a replacement for the parent container
|
||||
// for getting boundaries for x an y axis
|
||||
boundToSelector: String,
|
||||
// Takes a top/bottom/left/right object, how much space to leave
|
||||
// between boundary and popover element
|
||||
margin: Object,
|
||||
|
@ -27,6 +29,10 @@ const Popover = {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
containerBoundingClientRect () {
|
||||
const container = this.boundToSelector ? this.$el.closest(this.boundToSelector) : this.$el.offsetParent
|
||||
return container.getBoundingClientRect()
|
||||
},
|
||||
updateStyles () {
|
||||
if (this.hidden) {
|
||||
this.styles = {
|
||||
|
@ -45,7 +51,8 @@ const Popover = {
|
|||
// Minor optimization, don't call a slow reflow call if we don't have to
|
||||
const parentBounds = this.boundTo &&
|
||||
(this.boundTo.x === 'container' || this.boundTo.y === 'container') &&
|
||||
this.$el.offsetParent.getBoundingClientRect()
|
||||
this.containerBoundingClientRect()
|
||||
|
||||
const margin = this.margin || {}
|
||||
|
||||
// What are the screen bounds for the popover? Viewport vs container
|
||||
|
|
|
@ -82,7 +82,9 @@ const PostStatusForm = {
|
|||
contentType
|
||||
},
|
||||
caret: 0,
|
||||
pollFormVisible: false
|
||||
pollFormVisible: false,
|
||||
showDropIcon: 'hide',
|
||||
dropStopTimeout: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -248,13 +250,27 @@ const PostStatusForm = {
|
|||
}
|
||||
},
|
||||
fileDrop (e) {
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||
e.preventDefault() // allow dropping text like before
|
||||
this.dropFiles = e.dataTransfer.files
|
||||
clearTimeout(this.dropStopTimeout)
|
||||
this.showDropIcon = 'hide'
|
||||
}
|
||||
},
|
||||
fileDragStop (e) {
|
||||
// The false-setting is done with delay because just using leave-events
|
||||
// directly caused unwanted flickering, this is not perfect either but
|
||||
// much less noticable.
|
||||
clearTimeout(this.dropStopTimeout)
|
||||
this.showDropIcon = 'fade'
|
||||
this.dropStopTimeout = setTimeout(() => (this.showDropIcon = 'hide'), 500)
|
||||
},
|
||||
fileDrag (e) {
|
||||
e.dataTransfer.dropEffect = 'copy'
|
||||
if (e.dataTransfer && e.dataTransfer.types.includes('Files')) {
|
||||
clearTimeout(this.dropStopTimeout)
|
||||
this.showDropIcon = 'show'
|
||||
}
|
||||
},
|
||||
onEmojiInputInput (e) {
|
||||
this.$nextTick(() => {
|
||||
|
|
|
@ -6,7 +6,15 @@
|
|||
<form
|
||||
autocomplete="off"
|
||||
@submit.prevent="postStatus(newStatus)"
|
||||
@dragover.prevent="fileDrag"
|
||||
>
|
||||
<div
|
||||
v-show="showDropIcon !== 'hide'"
|
||||
:style="{ animation: showDropIcon === 'show' ? 'fade-in 0.25s' : 'fade-out 0.5s' }"
|
||||
class="drop-indicator icon-upload"
|
||||
@dragleave="fileDragStop"
|
||||
@drop.stop="fileDrop"
|
||||
/>
|
||||
<div class="form-group">
|
||||
<i18n
|
||||
v-if="!$store.state.users.currentUser.locked && newStatus.visibility == 'private'"
|
||||
|
@ -73,6 +81,7 @@
|
|||
v-model="newStatus.spoilerText"
|
||||
type="text"
|
||||
:placeholder="$t('post_status.content_warning')"
|
||||
:disabled="posting"
|
||||
class="form-post-subject"
|
||||
>
|
||||
</EmojiInput>
|
||||
|
@ -96,9 +105,7 @@
|
|||
:disabled="posting"
|
||||
class="form-post-body"
|
||||
@keydown.meta.enter="postStatus(newStatus)"
|
||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
||||
@drop="fileDrop"
|
||||
@dragover.prevent="fileDrag"
|
||||
@keydown.ctrl.enter="postStatus(newStatus)"
|
||||
@input="resize"
|
||||
@compositionupdate="resize"
|
||||
@paste="paste"
|
||||
|
@ -447,7 +454,8 @@
|
|||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.6em;
|
||||
margin: 0.6em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
|
@ -505,5 +513,35 @@
|
|||
cursor: pointer;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 0.6; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 0.6; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
.drop-indicator {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0.6;
|
||||
color: $fallback--text;
|
||||
color: var(--text, $fallback--text);
|
||||
background-color: $fallback--bg;
|
||||
background-color: var(--bg, $fallback--bg);
|
||||
border-radius: $fallback--tooltipRadius;
|
||||
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
|
||||
border: 2px dashed $fallback--text;
|
||||
border: 2px dashed var(--text, $fallback--text);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -13,6 +13,9 @@ const PostStatusModal = {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
isLoggedIn () {
|
||||
return !!this.$store.state.users.currentUser
|
||||
},
|
||||
modalActivated () {
|
||||
return this.$store.state.postStatus.modalActivated
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<Modal
|
||||
v-if="isLoggedIn && !resettingForm"
|
||||
:is-open="modalActivated"
|
||||
class="post-form-modal-view"
|
||||
@backdropClicked="closeModal"
|
||||
|
|
|
@ -32,12 +32,12 @@ const DomainMuteList = withSubscription({
|
|||
const MutesAndBlocks = {
|
||||
data () {
|
||||
return {
|
||||
activeTab: 'profile',
|
||||
newDomainToMute: ''
|
||||
activeTab: 'profile'
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.$store.dispatch('fetchTokens')
|
||||
this.$store.dispatch('getKnownDomains')
|
||||
},
|
||||
components: {
|
||||
TabSwitcher,
|
||||
|
@ -51,6 +51,14 @@ const MutesAndBlocks = {
|
|||
Autosuggest,
|
||||
Checkbox
|
||||
},
|
||||
computed: {
|
||||
knownDomains () {
|
||||
return this.$store.state.instance.knownDomains
|
||||
},
|
||||
user () {
|
||||
return this.$store.state.users.currentUser
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
importFollows (file) {
|
||||
return this.$store.state.api.backendInteractor.importFollows({ file })
|
||||
|
@ -86,13 +94,13 @@ const MutesAndBlocks = {
|
|||
filterUnblockedUsers (userIds) {
|
||||
return reject(userIds, (userId) => {
|
||||
const relationship = this.$store.getters.relationship(this.userId)
|
||||
return relationship.blocking || userId === this.$store.state.users.currentUser.id
|
||||
return relationship.blocking || userId === this.user.id
|
||||
})
|
||||
},
|
||||
filterUnMutedUsers (userIds) {
|
||||
return reject(userIds, (userId) => {
|
||||
const relationship = this.$store.getters.relationship(this.userId)
|
||||
return relationship.muting || userId === this.$store.state.users.currentUser.id
|
||||
return relationship.muting || userId === this.user.id
|
||||
})
|
||||
},
|
||||
queryUserIds (query) {
|
||||
|
@ -111,12 +119,16 @@ const MutesAndBlocks = {
|
|||
unmuteUsers (ids) {
|
||||
return this.$store.dispatch('unmuteUsers', ids)
|
||||
},
|
||||
filterUnMutedDomains (urls) {
|
||||
return urls.filter(url => !this.user.domainMutes.includes(url))
|
||||
},
|
||||
queryKnownDomains (query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(this.knownDomains.filter(url => url.toLowerCase().includes(query)))
|
||||
})
|
||||
},
|
||||
unmuteDomains (domains) {
|
||||
return this.$store.dispatch('unmuteDomains', domains)
|
||||
},
|
||||
muteDomain () {
|
||||
return this.$store.dispatch('muteDomain', this.newDomainToMute)
|
||||
.then(() => { this.newDomainToMute = '' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,21 +119,16 @@
|
|||
|
||||
<div :label="$t('settings.domain_mutes')">
|
||||
<div class="domain-mute-form">
|
||||
<input
|
||||
v-model="newDomainToMute"
|
||||
<Autosuggest
|
||||
:filter="filterUnMutedDomains"
|
||||
:query="queryKnownDomains"
|
||||
:placeholder="$t('settings.type_domains_to_mute')"
|
||||
type="text"
|
||||
@keyup.enter="muteDomain"
|
||||
>
|
||||
<ProgressButton
|
||||
class="btn btn-default domain-mute-button"
|
||||
:click="muteDomain"
|
||||
>
|
||||
{{ $t('domain_mute_card.mute') }}
|
||||
<template slot="progress">
|
||||
{{ $t('domain_mute_card.mute_progress') }}
|
||||
</template>
|
||||
</ProgressButton>
|
||||
<DomainMuteCard
|
||||
slot-scope="row"
|
||||
:domain="row.item"
|
||||
/>
|
||||
</Autosuggest>
|
||||
</div>
|
||||
<DomainMuteList
|
||||
:refresh="true"
|
||||
|
|
|
@ -25,6 +25,7 @@ const ProfileTab = {
|
|||
showRole: this.$store.state.users.currentUser.show_role,
|
||||
role: this.$store.state.users.currentUser.role,
|
||||
discoverable: this.$store.state.users.currentUser.discoverable,
|
||||
bot: this.$store.state.users.currentUser.bot,
|
||||
allowFollowingMove: this.$store.state.users.currentUser.allow_following_move,
|
||||
pickAvatarBtnVisible: true,
|
||||
bannerUploading: false,
|
||||
|
@ -94,6 +95,7 @@ const ProfileTab = {
|
|||
hide_follows: this.hideFollows,
|
||||
hide_followers: this.hideFollowers,
|
||||
discoverable: this.discoverable,
|
||||
bot: this.bot,
|
||||
allow_following_move: this.allowFollowingMove,
|
||||
hide_follows_count: this.hideFollowsCount,
|
||||
hide_followers_count: this.hideFollowersCount,
|
||||
|
|
|
@ -143,6 +143,11 @@
|
|||
{{ $t("settings.profile_fields.add_field") }}
|
||||
</a>
|
||||
</div>
|
||||
<p>
|
||||
<Checkbox v-model="bot">
|
||||
{{ $t('settings.bot') }}
|
||||
</Checkbox>
|
||||
</p>
|
||||
<button
|
||||
:disabled="newName && newName.length === 0"
|
||||
class="btn btn-default"
|
||||
|
|
|
@ -256,6 +256,13 @@
|
|||
:label="$t('settings.links')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.postLink" />
|
||||
<ColorInput
|
||||
v-model="postGreentextColorLocal"
|
||||
name="postGreentextColor"
|
||||
:fallback="previewTheme.colors.cGreen"
|
||||
:label="$t('settings.greentext')"
|
||||
/>
|
||||
<ContrastRatio :contrast="previewContrast.postGreentext" />
|
||||
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
||||
<ColorInput
|
||||
v-model="alertErrorColorLocal"
|
||||
|
|
|
@ -418,7 +418,7 @@ $status-margin: 0.75em;
|
|||
max-width: 85%;
|
||||
font-weight: bold;
|
||||
|
||||
img {
|
||||
img.emoji {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -164,23 +164,23 @@ $status-margin: 0.75em;
|
|||
word-break: break-all;
|
||||
}
|
||||
|
||||
img, video {
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
vertical-align: middle;
|
||||
object-fit: contain;
|
||||
|
||||
&.emoji {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.status-content {
|
||||
font-family: var(--postFont, sans-serif);
|
||||
line-height: 1.4em;
|
||||
white-space: pre-wrap;
|
||||
|
||||
img, video {
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
vertical-align: middle;
|
||||
object-fit: contain;
|
||||
|
||||
&.emoji {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0.2em 0 0.2em 2em;
|
||||
font-style: italic;
|
||||
|
@ -226,7 +226,7 @@ $status-margin: 0.75em;
|
|||
|
||||
.greentext {
|
||||
color: $fallback--cGreen;
|
||||
color: var(--cGreen, $fallback--cGreen);
|
||||
color: var(--postGreentext, $fallback--cGreen);
|
||||
}
|
||||
|
||||
.timeline :not(.panel-disabled) > {
|
||||
|
|
|
@ -23,13 +23,6 @@
|
|||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
.contain-fit {
|
||||
.still-image {
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.still-image {
|
||||
position: relative;
|
||||
|
@ -38,6 +31,7 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover canvas {
|
||||
display: none;
|
||||
|
@ -45,8 +39,8 @@
|
|||
|
||||
img {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
object-fit: contain;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&.animated {
|
||||
|
|
|
@ -70,10 +70,20 @@
|
|||
>
|
||||
@{{ user.screen_name }}
|
||||
</router-link>
|
||||
<span
|
||||
v-if="!hideBio && !!visibleRole"
|
||||
class="alert staff"
|
||||
>{{ visibleRole }}</span>
|
||||
<template v-if="!hideBio">
|
||||
<span
|
||||
v-if="!!visibleRole"
|
||||
class="alert user-role"
|
||||
>
|
||||
{{ visibleRole }}
|
||||
</span>
|
||||
<span
|
||||
v-if="user.bot"
|
||||
class="alert user-role"
|
||||
>
|
||||
bot
|
||||
</span>
|
||||
</template>
|
||||
<span v-if="user.locked"><i class="icon icon-lock" /></span>
|
||||
<span
|
||||
v-if="!mergedConfig.hideUserStats && !hideBio"
|
||||
|
@ -458,7 +468,7 @@
|
|||
color: var(--text, $fallback--text);
|
||||
}
|
||||
|
||||
.staff {
|
||||
.user-role {
|
||||
flex: none;
|
||||
text-transform: capitalize;
|
||||
color: $fallback--text;
|
||||
|
|
|
@ -124,6 +124,14 @@ const UserProfile = {
|
|||
onTabSwitch (tab) {
|
||||
this.tab = tab
|
||||
this.$router.replace({ query: { tab } })
|
||||
},
|
||||
linkClicked ({ target }) {
|
||||
if (target.tagName === 'SPAN') {
|
||||
target = target.parentNode
|
||||
}
|
||||
if (target.tagName === 'A') {
|
||||
window.open(target.href, '_blank')
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -11,6 +11,31 @@
|
|||
:allow-zooming-avatar="true"
|
||||
rounded="top"
|
||||
/>
|
||||
<div
|
||||
v-if="user.fields_html && user.fields_html.length > 0"
|
||||
class="user-profile-fields"
|
||||
>
|
||||
<dl
|
||||
v-for="(field, index) in user.fields_html"
|
||||
:key="index"
|
||||
class="user-profile-field"
|
||||
>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<dt
|
||||
:title="user.fields_text[index].name"
|
||||
class="user-profile-field-name"
|
||||
@click.prevent="linkClicked"
|
||||
v-html="field.name"
|
||||
/>
|
||||
<dd
|
||||
:title="user.fields_text[index].value"
|
||||
class="user-profile-field-value"
|
||||
@click.prevent="linkClicked"
|
||||
v-html="field.value"
|
||||
/>
|
||||
<!-- eslint-enable vue/no-v-html -->
|
||||
</dl>
|
||||
</div>
|
||||
<tab-switcher
|
||||
:active-tab="tab"
|
||||
:render-only-focused="true"
|
||||
|
@ -108,11 +133,60 @@
|
|||
<script src="./user_profile.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.user-profile {
|
||||
flex: 2;
|
||||
flex-basis: 500px;
|
||||
|
||||
.user-profile-fields {
|
||||
margin: 0 0.5em;
|
||||
img {
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
max-height: 400px;
|
||||
|
||||
&.emoji {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile-field {
|
||||
display: flex;
|
||||
margin: 0.25em auto;
|
||||
max-width: 32em;
|
||||
border: 1px solid var(--border, $fallback--border);
|
||||
border-radius: $fallback--inputRadius;
|
||||
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||
|
||||
.user-profile-field-name {
|
||||
flex: 0 1 30%;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
color: var(--lightText);
|
||||
min-width: 120px;
|
||||
border-right: 1px solid var(--border, $fallback--border);
|
||||
}
|
||||
|
||||
.user-profile-field-value {
|
||||
flex: 1 1 70%;
|
||||
color: var(--text);
|
||||
margin: 0 0 0 0.25em;
|
||||
}
|
||||
|
||||
.user-profile-field-name, .user-profile-field-value {
|
||||
line-height: 18px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0.5em 1.5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.userlist-placeholder {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue