forked from AkkomaGang/akkoma-fe
Merge branch 'develop' into brendenbice1222/pleroma-fe-issues/pleroma-fe-202-show-boosted-users
This commit is contained in:
commit
d417945427
41 changed files with 767 additions and 275 deletions
|
@ -27,9 +27,9 @@
|
||||||
"popper.js": "^1.14.7",
|
"popper.js": "^1.14.7",
|
||||||
"sanitize-html": "^1.13.0",
|
"sanitize-html": "^1.13.0",
|
||||||
"sass-loader": "^4.0.2",
|
"sass-loader": "^4.0.2",
|
||||||
|
"v-click-outside": "^2.1.1",
|
||||||
"vue": "^2.5.13",
|
"vue": "^2.5.13",
|
||||||
"vue-chat-scroll": "^1.2.1",
|
"vue-chat-scroll": "^1.2.1",
|
||||||
"vue-compose": "^0.7.1",
|
|
||||||
"vue-i18n": "^7.3.2",
|
"vue-i18n": "^7.3.2",
|
||||||
"vue-popperjs": "^2.0.3",
|
"vue-popperjs": "^2.0.3",
|
||||||
"vue-router": "^3.0.1",
|
"vue-router": "^3.0.1",
|
||||||
|
|
52
src/components/autosuggest/autosuggest.js
Normal file
52
src/components/autosuggest/autosuggest.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
const debounceMilliseconds = 500
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
query: { // function to query results and return a promise
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
filter: { // function to filter results in real time
|
||||||
|
type: Function
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: 'Search...'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
term: '',
|
||||||
|
timeout: null,
|
||||||
|
results: [],
|
||||||
|
resultsVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filtered () {
|
||||||
|
return this.filter ? this.filter(this.results) : this.results
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
term (val) {
|
||||||
|
this.fetchResults(val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchResults (term) {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.results = []
|
||||||
|
if (term) {
|
||||||
|
this.query(term).then((results) => { this.results = results })
|
||||||
|
}
|
||||||
|
}, debounceMilliseconds)
|
||||||
|
},
|
||||||
|
onInputClick () {
|
||||||
|
this.resultsVisible = true
|
||||||
|
},
|
||||||
|
onClickOutside () {
|
||||||
|
this.resultsVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/components/autosuggest/autosuggest.vue
Normal file
45
src/components/autosuggest/autosuggest.vue
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<template>
|
||||||
|
<div class="autosuggest" v-click-outside="onClickOutside">
|
||||||
|
<input v-model="term" :placeholder="placeholder" @click="onInputClick" class="autosuggest-input" />
|
||||||
|
<div class="autosuggest-results" v-if="resultsVisible && filtered.length > 0">
|
||||||
|
<slot v-for="item in filtered" :item="item" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./autosuggest.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.autosuggest {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&-input {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-results {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
max-height: 400px;
|
||||||
|
background-color: $fallback--lightBg;
|
||||||
|
background-color: var(--lightBg, $fallback--lightBg);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: $fallback--border;
|
||||||
|
border-color: var(--border, $fallback--border);
|
||||||
|
border-radius: $fallback--inputRadius;
|
||||||
|
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
|
||||||
|
box-shadow: var(--panelShadow);
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -24,19 +24,11 @@
|
||||||
<script src="./basic_user_card.js"></script>
|
<script src="./basic_user_card.js"></script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
|
||||||
|
|
||||||
.basic-user-card {
|
.basic-user-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 0;
|
flex: 1 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-top: 0.6em;
|
padding: 0.6em 1em;
|
||||||
padding-right: 1em;
|
|
||||||
padding-bottom: 0.6em;
|
|
||||||
padding-left: 1em;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
border-bottom-color: $fallback--border;
|
|
||||||
border-bottom-color: var(--border, $fallback--border);
|
|
||||||
|
|
||||||
&-collapsed-content {
|
&-collapsed-content {
|
||||||
margin-left: 0.7em;
|
margin-left: 0.7em;
|
||||||
|
|
75
src/components/checkbox/checkbox.vue
Normal file
75
src/components/checkbox/checkbox.vue
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" :indeterminate.prop="indeterminate">
|
||||||
|
<i class="checkbox-indicator" />
|
||||||
|
<span v-if="!!$slots.default"><slot></slot></span>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
model: {
|
||||||
|
prop: 'checked',
|
||||||
|
event: 'change'
|
||||||
|
},
|
||||||
|
props: ['checked', 'indeterminate']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 1.2em;
|
||||||
|
min-height: 1.2em;
|
||||||
|
|
||||||
|
&-indicator::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
display: block;
|
||||||
|
content: '✔';
|
||||||
|
transition: color 200ms;
|
||||||
|
width: 1.1em;
|
||||||
|
height: 1.1em;
|
||||||
|
border-radius: $fallback--checkboxRadius;
|
||||||
|
border-radius: var(--checkboxRadius, $fallback--checkboxRadius);
|
||||||
|
box-shadow: 0px 0px 2px black inset;
|
||||||
|
box-shadow: var(--inputShadow);
|
||||||
|
background-color: $fallback--fg;
|
||||||
|
background-color: var(--input, $fallback--fg);
|
||||||
|
vertical-align: top;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.1em;
|
||||||
|
font-size: 1.1em;
|
||||||
|
color: transparent;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=checkbox] {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:checked + .checkbox-indicator::before {
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:indeterminate + .checkbox-indicator::before {
|
||||||
|
content: '–';
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled + .checkbox-indicator::before {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
margin-left: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,7 +4,7 @@
|
||||||
{{$t('nav.friend_requests')}}
|
{{$t('nav.friend_requests')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<FollowRequestCard v-for="request in requests" :key="request.id" :user="request"/>
|
<FollowRequestCard v-for="request in requests" :key="request.id" :user="request" class="list-item"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
42
src/components/list/list.vue
Normal file
42
src/components/list/list.vue
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<template>
|
||||||
|
<div class="list">
|
||||||
|
<div v-for="item in items" class="list-item" :key="getKey(item)">
|
||||||
|
<slot name="item" :item="item" />
|
||||||
|
</div>
|
||||||
|
<div class="list-empty-content faint" v-if="items.length === 0 && !!$slots.empty">
|
||||||
|
<slot name="empty" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
getKey: {
|
||||||
|
type: Function,
|
||||||
|
default: item => item.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.list {
|
||||||
|
&-item:not(:last-child) {
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-bottom-color: $fallback--border;
|
||||||
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-empty-content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -23,7 +23,7 @@ const Notification = {
|
||||||
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
|
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
|
||||||
},
|
},
|
||||||
getUser (notification) {
|
getUser (notification) {
|
||||||
return this.$store.state.users.usersObject[notification.action.user.id]
|
return this.$store.state.users.usersObject[notification.from_profile.id]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
35
src/components/progress_button/progress_button.vue
Normal file
35
src/components/progress_button/progress_button.vue
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<button :disabled="progress || disabled" @click="onClick">
|
||||||
|
<template v-if="progress">
|
||||||
|
<slot name="progress" />
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<slot />
|
||||||
|
</template>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
disabled: {
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
click: { // click event handler. Must return a promise
|
||||||
|
type: Function,
|
||||||
|
default: () => Promise.resolve()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
progress: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick () {
|
||||||
|
this.progress = true
|
||||||
|
this.click().then(() => { this.progress = false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
66
src/components/selectable_list/selectable_list.js
Normal file
66
src/components/selectable_list/selectable_list.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import List from '../list/list.vue'
|
||||||
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
|
|
||||||
|
const SelectableList = {
|
||||||
|
components: {
|
||||||
|
List,
|
||||||
|
Checkbox
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
getKey: {
|
||||||
|
type: Function,
|
||||||
|
default: item => item.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
selected: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
allKeys () {
|
||||||
|
return this.items.map(this.getKey)
|
||||||
|
},
|
||||||
|
filteredSelected () {
|
||||||
|
return this.allKeys.filter(key => this.selected.indexOf(key) !== -1)
|
||||||
|
},
|
||||||
|
allSelected () {
|
||||||
|
return this.filteredSelected.length === this.items.length
|
||||||
|
},
|
||||||
|
noneSelected () {
|
||||||
|
return this.filteredSelected.length === 0
|
||||||
|
},
|
||||||
|
someSelected () {
|
||||||
|
return !this.allSelected && !this.noneSelected
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isSelected (item) {
|
||||||
|
return this.filteredSelected.indexOf(this.getKey(item)) !== -1
|
||||||
|
},
|
||||||
|
toggle (checked, item) {
|
||||||
|
const key = this.getKey(item)
|
||||||
|
const oldChecked = this.isSelected(key)
|
||||||
|
if (checked !== oldChecked) {
|
||||||
|
if (checked) {
|
||||||
|
this.selected.push(key)
|
||||||
|
} else {
|
||||||
|
this.selected.splice(this.selected.indexOf(key), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleAll (value) {
|
||||||
|
if (value) {
|
||||||
|
this.selected = this.allKeys.slice(0)
|
||||||
|
} else {
|
||||||
|
this.selected = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectableList
|
59
src/components/selectable_list/selectable_list.vue
Normal file
59
src/components/selectable_list/selectable_list.vue
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<div class="selectable-list">
|
||||||
|
<div class="selectable-list-header" v-if="items.length > 0">
|
||||||
|
<div class="selectable-list-checkbox-wrapper">
|
||||||
|
<Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="selectable-list-header-actions">
|
||||||
|
<slot name="header" :selected="filteredSelected" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<List :items="items" :getKey="getKey">
|
||||||
|
<template slot="item" slot-scope="{item}">
|
||||||
|
<div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }">
|
||||||
|
<div class="selectable-list-checkbox-wrapper">
|
||||||
|
<Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" />
|
||||||
|
</div>
|
||||||
|
<slot name="item" :item="item" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template slot="empty"><slot name="empty" /></template>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./selectable_list.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.selectable-list {
|
||||||
|
&-item-inner {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item-selected-inner {
|
||||||
|
background-color: $fallback--lightBg;
|
||||||
|
background-color: var(--lightBg, $fallback--lightBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.6em 0;
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
border-bottom-color: $fallback--border;
|
||||||
|
border-bottom-color: var(--border, $fallback--border);
|
||||||
|
|
||||||
|
&-actions {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-checkbox-wrapper {
|
||||||
|
padding: 0 10px;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -42,9 +42,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
<input type="checkbox" id="collapseMessageWithSubject" v-model="collapseMessageWithSubjectLocal">
|
||||||
<label for="collapseMessageWithSubject">
|
<label for="collapseMessageWithSubject">{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}</label>
|
||||||
{{$t('settings.collapse_subject')}} {{$t('settings.instance_default', { value: collapseMessageWithSubjectDefault })}}
|
|
||||||
</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="streaming" v-model="streamingLocal">
|
<input type="checkbox" id="streaming" v-model="streamingLocal">
|
||||||
|
@ -330,6 +328,7 @@
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
|
<div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
|
||||||
<div :title="user.name" class='user-name' v-else>{{user.name}}</div>
|
<div :title="user.name" class='user-name' v-else>{{user.name}}</div>
|
||||||
<router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser">
|
<router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser">
|
||||||
<i class="button-icon icon-pencil usersettings" :title="$t('tool_tip.user_settings')"></i>
|
<i class="button-icon icon-wrench usersettings" :title="$t('tool_tip.user_settings')"></i>
|
||||||
</router-link>
|
</router-link>
|
||||||
<a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local">
|
<a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local">
|
||||||
<i class="icon-link-ext usersettings"></i>
|
<i class="icon-link-ext usersettings"></i>
|
||||||
|
@ -162,7 +162,7 @@
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
|
|
||||||
.emoji {
|
&.emoji {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +1,37 @@
|
||||||
import { compose } from 'vue-compose'
|
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
import FollowCard from '../follow_card/follow_card.vue'
|
import FollowCard from '../follow_card/follow_card.vue'
|
||||||
import Timeline from '../timeline/timeline.vue'
|
import Timeline from '../timeline/timeline.vue'
|
||||||
import ModerationTools from '../moderation_tools/moderation_tools.vue'
|
import ModerationTools from '../moderation_tools/moderation_tools.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 withList from '../../hocs/with_list/with_list'
|
|
||||||
|
|
||||||
const FollowerList = compose(
|
const FollowerList = withLoadMore({
|
||||||
withLoadMore({
|
fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId),
|
||||||
fetch: (props, $store) => $store.dispatch('addFollowers', props.userId),
|
select: (props, $store) => get($store.getters.findUser(props.userId), 'followerIds', []).map(id => $store.getters.findUser(id)),
|
||||||
select: (props, $store) => get($store.getters.findUser(props.userId), 'followers', []),
|
destroy: (props, $store) => $store.dispatch('clearFollowers', props.userId),
|
||||||
destory: (props, $store) => $store.dispatch('clearFollowers', props.userId),
|
childPropName: 'items',
|
||||||
childPropName: 'entries',
|
|
||||||
additionalPropNames: ['userId']
|
additionalPropNames: ['userId']
|
||||||
}),
|
})(List)
|
||||||
withList({ getEntryProps: user => ({ user }) })
|
|
||||||
)(FollowCard)
|
|
||||||
|
|
||||||
const FriendList = compose(
|
const FriendList = withLoadMore({
|
||||||
withLoadMore({
|
fetch: (props, $store) => $store.dispatch('fetchFriends', props.userId),
|
||||||
fetch: (props, $store) => $store.dispatch('addFriends', props.userId),
|
select: (props, $store) => get($store.getters.findUser(props.userId), 'friendIds', []).map(id => $store.getters.findUser(id)),
|
||||||
select: (props, $store) => get($store.getters.findUser(props.userId), 'friends', []),
|
destroy: (props, $store) => $store.dispatch('clearFriends', props.userId),
|
||||||
destory: (props, $store) => $store.dispatch('clearFriends', props.userId),
|
childPropName: 'items',
|
||||||
childPropName: 'entries',
|
|
||||||
additionalPropNames: ['userId']
|
additionalPropNames: ['userId']
|
||||||
}),
|
})(List)
|
||||||
withList({ getEntryProps: user => ({ user }) })
|
|
||||||
)(FollowCard)
|
|
||||||
|
|
||||||
const UserProfile = {
|
const UserProfile = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
error: false,
|
error: false,
|
||||||
fetchedUserId: null
|
userId: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if (!this.user.id) {
|
const routeParams = this.$route.params
|
||||||
this.fetchUserId()
|
this.load(routeParams.name || routeParams.id)
|
||||||
.then(() => this.startUp())
|
|
||||||
} else {
|
|
||||||
this.startUp()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
destroyed () {
|
destroyed () {
|
||||||
this.cleanUp()
|
this.cleanUp()
|
||||||
|
@ -57,26 +46,12 @@ const UserProfile = {
|
||||||
media () {
|
media () {
|
||||||
return this.$store.state.statuses.timelines.media
|
return this.$store.state.statuses.timelines.media
|
||||||
},
|
},
|
||||||
userId () {
|
|
||||||
return this.$route.params.id || this.user.id || this.fetchedUserId
|
|
||||||
},
|
|
||||||
userName () {
|
|
||||||
return this.$route.params.name || this.user.screen_name
|
|
||||||
},
|
|
||||||
isUs () {
|
isUs () {
|
||||||
return this.userId && this.$store.state.users.currentUser.id &&
|
return this.userId && this.$store.state.users.currentUser.id &&
|
||||||
this.userId === this.$store.state.users.currentUser.id
|
this.userId === this.$store.state.users.currentUser.id
|
||||||
},
|
},
|
||||||
userInStore () {
|
|
||||||
const routeParams = this.$route.params
|
|
||||||
// This needs fetchedUserId so that computed will be refreshed when user is fetched
|
|
||||||
return this.$store.getters.findUser(this.fetchedUserId || routeParams.name || routeParams.id)
|
|
||||||
},
|
|
||||||
user () {
|
user () {
|
||||||
if (this.userInStore) {
|
return this.$store.getters.findUser(this.userId)
|
||||||
return this.userInStore
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
},
|
},
|
||||||
isExternal () {
|
isExternal () {
|
||||||
return this.$route.name === 'external-user-profile'
|
return this.$route.name === 'external-user-profile'
|
||||||
|
@ -89,22 +64,18 @@ const UserProfile = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startFetchFavorites () {
|
load (userNameOrId) {
|
||||||
if (this.isUs) {
|
// Check if user data is already loaded in store
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'favorites', userId: this.userId })
|
const user = this.$store.getters.findUser(userNameOrId)
|
||||||
}
|
if (user) {
|
||||||
},
|
this.userId = user.id
|
||||||
fetchUserId () {
|
this.fetchTimelines()
|
||||||
let fetchPromise
|
|
||||||
if (this.userId && !this.$route.params.name) {
|
|
||||||
fetchPromise = this.$store.dispatch('fetchUser', this.userId)
|
|
||||||
} else {
|
} else {
|
||||||
fetchPromise = this.$store.dispatch('fetchUser', this.userName)
|
this.$store.dispatch('fetchUser', userNameOrId)
|
||||||
.then(({ id }) => {
|
.then(({ id }) => {
|
||||||
this.fetchedUserId = id
|
this.userId = id
|
||||||
|
this.fetchTimelines()
|
||||||
})
|
})
|
||||||
}
|
|
||||||
return fetchPromise
|
|
||||||
.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
|
||||||
|
@ -115,13 +86,14 @@ const UserProfile = {
|
||||||
this.error = this.$t('user_profile.profile_loading_error')
|
this.error = this.$t('user_profile.profile_loading_error')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => this.startUp())
|
}
|
||||||
},
|
},
|
||||||
startUp () {
|
fetchTimelines () {
|
||||||
if (this.userId) {
|
const userId = this.userId
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'user', userId: this.userId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'user', userId })
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'media', userId: this.userId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'media', userId })
|
||||||
this.startFetchFavorites()
|
if (this.isUs) {
|
||||||
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'favorites', userId })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cleanUp () {
|
cleanUp () {
|
||||||
|
@ -134,18 +106,16 @@ const UserProfile = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
// userId can be undefined if we don't know it yet
|
'$route.params.id': function (newVal) {
|
||||||
userId (newVal) {
|
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
this.cleanUp()
|
this.cleanUp()
|
||||||
this.startUp()
|
this.load(newVal)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
userName () {
|
'$route.params.name': function (newVal) {
|
||||||
if (this.$route.params.name) {
|
if (newVal) {
|
||||||
this.fetchUserId()
|
|
||||||
this.cleanUp()
|
this.cleanUp()
|
||||||
this.startUp()
|
this.load(newVal)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
$route () {
|
$route () {
|
||||||
|
@ -157,7 +127,8 @@ const UserProfile = {
|
||||||
Timeline,
|
Timeline,
|
||||||
FollowerList,
|
FollowerList,
|
||||||
FriendList,
|
FriendList,
|
||||||
ModerationTools
|
ModerationTools,
|
||||||
|
FollowCard
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="user.id" class="user-profile panel panel-default">
|
<div v-if="user" class="user-profile panel panel-default">
|
||||||
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/>
|
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/>
|
||||||
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher">
|
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher">
|
||||||
<Timeline
|
<Timeline
|
||||||
|
@ -14,10 +14,18 @@
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
/>
|
/>
|
||||||
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
|
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
|
||||||
<FriendList :userId="userId" />
|
<FriendList :userId="userId">
|
||||||
|
<template slot="item" slot-scope="{item}">
|
||||||
|
<FollowCard :user="item" />
|
||||||
|
</template>
|
||||||
|
</FriendList>
|
||||||
</div>
|
</div>
|
||||||
<div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count">
|
<div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count">
|
||||||
<FollowerList :userId="userId" :entryProps="{noFollowsYou: isUs}" />
|
<FollowerList :userId="userId">
|
||||||
|
<template slot="item" slot-scope="{item}">
|
||||||
|
<FollowCard :user="item" :noFollowsYou="isUs" />
|
||||||
|
</template>
|
||||||
|
</FollowerList>
|
||||||
</div>
|
</div>
|
||||||
<Timeline
|
<Timeline
|
||||||
:label="$t('user_card.media')"
|
:label="$t('user_card.media')"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<i class="icon-spin3 animate-spin"/>
|
<i class="icon-spin3 animate-spin"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="panel-body">
|
<div v-else class="panel-body">
|
||||||
<FollowCard v-for="user in users" :key="user.id" :user="user"/>
|
<FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { compose } from 'vue-compose'
|
|
||||||
import unescape from 'lodash/unescape'
|
import unescape from 'lodash/unescape'
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
|
import map from 'lodash/map'
|
||||||
|
import reject from 'lodash/reject'
|
||||||
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
import TabSwitcher from '../tab_switcher/tab_switcher.js'
|
||||||
import ImageCropper from '../image_cropper/image_cropper.vue'
|
import ImageCropper from '../image_cropper/image_cropper.vue'
|
||||||
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
import StyleSwitcher from '../style_switcher/style_switcher.vue'
|
||||||
|
@ -8,27 +9,24 @@ import ScopeSelector from '../scope_selector/scope_selector.vue'
|
||||||
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
|
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
|
||||||
import BlockCard from '../block_card/block_card.vue'
|
import BlockCard from '../block_card/block_card.vue'
|
||||||
import MuteCard from '../mute_card/mute_card.vue'
|
import MuteCard from '../mute_card/mute_card.vue'
|
||||||
|
import SelectableList from '../selectable_list/selectable_list.vue'
|
||||||
|
import ProgressButton from '../progress_button/progress_button.vue'
|
||||||
import EmojiInput from '../emoji-input/emoji-input.vue'
|
import EmojiInput from '../emoji-input/emoji-input.vue'
|
||||||
|
import Autosuggest from '../autosuggest/autosuggest.vue'
|
||||||
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
import withSubscription from '../../hocs/with_subscription/with_subscription'
|
||||||
import withList from '../../hocs/with_list/with_list'
|
import userSearchApi from '../../services/new_api/user_search.js'
|
||||||
|
|
||||||
const BlockList = compose(
|
const BlockList = withSubscription({
|
||||||
withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
|
select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
|
||||||
childPropName: 'entries'
|
childPropName: 'items'
|
||||||
}),
|
})(SelectableList)
|
||||||
withList({ getEntryProps: userId => ({ userId }) })
|
|
||||||
)(BlockCard)
|
|
||||||
|
|
||||||
const MuteList = compose(
|
const MuteList = withSubscription({
|
||||||
withSubscription({
|
|
||||||
fetch: (props, $store) => $store.dispatch('fetchMutes'),
|
fetch: (props, $store) => $store.dispatch('fetchMutes'),
|
||||||
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
|
select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
|
||||||
childPropName: 'entries'
|
childPropName: 'items'
|
||||||
}),
|
})(SelectableList)
|
||||||
withList({ getEntryProps: userId => ({ userId }) })
|
|
||||||
)(MuteCard)
|
|
||||||
|
|
||||||
const UserSettings = {
|
const UserSettings = {
|
||||||
data () {
|
data () {
|
||||||
|
@ -73,7 +71,11 @@ const UserSettings = {
|
||||||
ImageCropper,
|
ImageCropper,
|
||||||
BlockList,
|
BlockList,
|
||||||
MuteList,
|
MuteList,
|
||||||
EmojiInput
|
EmojiInput,
|
||||||
|
Autosuggest,
|
||||||
|
BlockCard,
|
||||||
|
MuteCard,
|
||||||
|
ProgressButton
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user () {
|
user () {
|
||||||
|
@ -334,6 +336,40 @@ const UserSettings = {
|
||||||
if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
|
if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) {
|
||||||
this.$store.dispatch('revokeToken', id)
|
this.$store.dispatch('revokeToken', id)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
filterUnblockedUsers (userIds) {
|
||||||
|
return reject(userIds, (userId) => {
|
||||||
|
const user = this.$store.getters.findUser(userId)
|
||||||
|
return !user || user.statusnet_blocking || user.id === this.$store.state.users.currentUser.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
filterUnMutedUsers (userIds) {
|
||||||
|
return reject(userIds, (userId) => {
|
||||||
|
const user = this.$store.getters.findUser(userId)
|
||||||
|
return !user || user.muted || user.id === this.$store.state.users.currentUser.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
queryUserIds (query) {
|
||||||
|
return userSearchApi.search({query, store: this.$store})
|
||||||
|
.then((users) => {
|
||||||
|
this.$store.dispatch('addNewUsers', users)
|
||||||
|
return map(users, 'id')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
blockUsers (ids) {
|
||||||
|
return this.$store.dispatch('blockUsers', ids)
|
||||||
|
},
|
||||||
|
unblockUsers (ids) {
|
||||||
|
return this.$store.dispatch('unblockUsers', ids)
|
||||||
|
},
|
||||||
|
muteUsers (ids) {
|
||||||
|
return this.$store.dispatch('muteUsers', ids)
|
||||||
|
},
|
||||||
|
unmuteUsers (ids) {
|
||||||
|
return this.$store.dispatch('unmuteUsers', ids)
|
||||||
|
},
|
||||||
|
identity (value) {
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,15 +195,51 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :label="$t('settings.blocks_tab')">
|
<div :label="$t('settings.blocks_tab')">
|
||||||
<block-list :refresh="true">
|
<div class="profile-edit-usersearch-wrapper">
|
||||||
|
<Autosuggest :filter="filterUnblockedUsers" :query="queryUserIds" :placeholder="$t('settings.search_user_to_block')">
|
||||||
|
<BlockCard slot-scope="row" :userId="row.item"/>
|
||||||
|
</Autosuggest>
|
||||||
|
</div>
|
||||||
|
<BlockList :refresh="true" :getKey="identity">
|
||||||
|
<template slot="header" slot-scope="{selected}">
|
||||||
|
<div class="profile-edit-bulk-actions">
|
||||||
|
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => blockUsers(selected)">
|
||||||
|
{{ $t('user_card.block') }}
|
||||||
|
<template slot="progress">{{ $t('user_card.block_progress') }}</template>
|
||||||
|
</ProgressButton>
|
||||||
|
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unblockUsers(selected)">
|
||||||
|
{{ $t('user_card.unblock') }}
|
||||||
|
<template slot="progress">{{ $t('user_card.unblock_progress') }}</template>
|
||||||
|
</ProgressButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template slot="item" slot-scope="{item}"><BlockCard :userId="item" /></template>
|
||||||
<template slot="empty">{{$t('settings.no_blocks')}}</template>
|
<template slot="empty">{{$t('settings.no_blocks')}}</template>
|
||||||
</block-list>
|
</BlockList>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :label="$t('settings.mutes_tab')">
|
<div :label="$t('settings.mutes_tab')">
|
||||||
<mute-list :refresh="true">
|
<div class="profile-edit-usersearch-wrapper">
|
||||||
|
<Autosuggest :filter="filterUnMutedUsers" :query="queryUserIds" :placeholder="$t('settings.search_user_to_mute')">
|
||||||
|
<MuteCard slot-scope="row" :userId="row.item"/>
|
||||||
|
</Autosuggest>
|
||||||
|
</div>
|
||||||
|
<MuteList :refresh="true" :getKey="identity">
|
||||||
|
<template slot="header" slot-scope="{selected}">
|
||||||
|
<div class="profile-edit-bulk-actions">
|
||||||
|
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => muteUsers(selected)">
|
||||||
|
{{ $t('user_card.mute') }}
|
||||||
|
<template slot="progress">{{ $t('user_card.mute_progress') }}</template>
|
||||||
|
</ProgressButton>
|
||||||
|
<ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unmuteUsers(selected)">
|
||||||
|
{{ $t('user_card.unmute') }}
|
||||||
|
<template slot="progress">{{ $t('user_card.unmute_progress') }}</template>
|
||||||
|
</ProgressButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template slot="item" slot-scope="{item}"><MuteCard :userId="item" /></template>
|
||||||
<template slot="empty">{{$t('settings.no_mutes')}}</template>
|
<template slot="empty">{{$t('settings.no_mutes')}}</template>
|
||||||
</mute-list>
|
</MuteList>
|
||||||
</div>
|
</div>
|
||||||
</tab-switcher>
|
</tab-switcher>
|
||||||
</div>
|
</div>
|
||||||
|
@ -262,5 +298,19 @@
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-usersearch-wrapper {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-bulk-actions {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 1em;
|
||||||
|
min-height: 28px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{{$t('who_to_follow.who_to_follow')}}
|
{{$t('who_to_follow.who_to_follow')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<FollowCard v-for="user in users" :key="user.id" :user="user"/>
|
<FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import Vue from 'vue'
|
|
||||||
import map from 'lodash/map'
|
|
||||||
import isEmpty from 'lodash/isEmpty'
|
|
||||||
import './with_list.scss'
|
|
||||||
|
|
||||||
const defaultEntryPropsGetter = entry => ({ entry })
|
|
||||||
const defaultKeyGetter = entry => entry.id
|
|
||||||
|
|
||||||
const withList = ({
|
|
||||||
getEntryProps = defaultEntryPropsGetter, // function to accept entry and index values and return props to be passed into the item component
|
|
||||||
getKey = defaultKeyGetter // funciton to accept entry and index values and return key prop value
|
|
||||||
}) => (ItemComponent) => (
|
|
||||||
Vue.component('withList', {
|
|
||||||
props: [
|
|
||||||
'entries', // array of entry
|
|
||||||
'entryProps', // additional props to be passed into each entry
|
|
||||||
'entryListeners' // additional event listeners to be passed into each entry
|
|
||||||
],
|
|
||||||
render (createElement) {
|
|
||||||
return (
|
|
||||||
<div class="with-list">
|
|
||||||
{map(this.entries, (entry, index) => {
|
|
||||||
const props = {
|
|
||||||
key: getKey(entry, index),
|
|
||||||
props: {
|
|
||||||
...this.$props.entryProps,
|
|
||||||
...getEntryProps(entry, index)
|
|
||||||
},
|
|
||||||
on: this.$props.entryListeners
|
|
||||||
}
|
|
||||||
return <ItemComponent {...props} />
|
|
||||||
})}
|
|
||||||
{isEmpty(this.entries) && this.$slots.empty && <div class="with-list-empty-content faint">{this.$slots.empty}</div>}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export default withList
|
|
|
@ -1,6 +0,0 @@
|
||||||
.with-list {
|
|
||||||
&-empty-content {
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
.with-load-more {
|
.with-load-more {
|
||||||
&-footer {
|
&-footer {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
border-top: 1px solid;
|
||||||
|
border-top-color: $fallback--border;
|
||||||
|
border-top-color: var(--border, $fallback--border);
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
@ -112,6 +112,9 @@
|
||||||
"password_confirmation_match": "should be the same as password"
|
"password_confirmation_match": "should be the same as password"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "Select all"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"app_name": "App name",
|
"app_name": "App name",
|
||||||
"attachmentRadius": "Attachments",
|
"attachmentRadius": "Attachments",
|
||||||
|
@ -217,6 +220,8 @@
|
||||||
"reply_visibility_self": "Only show replies directed at me",
|
"reply_visibility_self": "Only show replies directed at me",
|
||||||
"saving_err": "Error saving settings",
|
"saving_err": "Error saving settings",
|
||||||
"saving_ok": "Settings saved",
|
"saving_ok": "Settings saved",
|
||||||
|
"search_user_to_block": "Search whom you want to block",
|
||||||
|
"search_user_to_mute": "Search whom you want to mute",
|
||||||
"security_tab": "Security",
|
"security_tab": "Security",
|
||||||
"scope_copy": "Copy scope when replying (DMs are always copied)",
|
"scope_copy": "Copy scope when replying (DMs are always copied)",
|
||||||
"minimal_scopes_mode": "Minimize post scope selection options",
|
"minimal_scopes_mode": "Minimize post scope selection options",
|
||||||
|
|
|
@ -20,7 +20,10 @@
|
||||||
"submit": "Mandar",
|
"submit": "Mandar",
|
||||||
"more": "Mai",
|
"more": "Mai",
|
||||||
"generic_error": "Una error s’es producha",
|
"generic_error": "Una error s’es producha",
|
||||||
"optional": "opcional"
|
"optional": "opcional",
|
||||||
|
"show_more": "Mostrar mai",
|
||||||
|
"show_less": "Mostrar mens",
|
||||||
|
"cancel": "Anullar"
|
||||||
},
|
},
|
||||||
"image_cropper": {
|
"image_cropper": {
|
||||||
"crop_picture": "Talhar l’imatge",
|
"crop_picture": "Talhar l’imatge",
|
||||||
|
@ -78,7 +81,8 @@
|
||||||
},
|
},
|
||||||
"content_warning": "Avís de contengut (opcional)",
|
"content_warning": "Avís de contengut (opcional)",
|
||||||
"default": "Escrivètz aquí vòstre estatut.",
|
"default": "Escrivètz aquí vòstre estatut.",
|
||||||
"direct_warning": "Aquesta publicacion serà pas que visibla pels utilizaires mencionats.",
|
"direct_warning_to_all": "Aquesta publicacion serà pas que visibla pels utilizaires mencionats.",
|
||||||
|
"direct_warning_to_first_only": "Aquesta publicacion serà pas que visibla pels utilizaires mencionats a la debuta del messatge.",
|
||||||
"posting": "Mandadís",
|
"posting": "Mandadís",
|
||||||
"scope": {
|
"scope": {
|
||||||
"direct": "Dirècte - Publicar pels utilizaires mencionats solament",
|
"direct": "Dirècte - Publicar pels utilizaires mencionats solament",
|
||||||
|
@ -108,6 +112,9 @@
|
||||||
"password_confirmation_match": "deu èsser lo meteis senhal"
|
"password_confirmation_match": "deu èsser lo meteis senhal"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"selectable_list": {
|
||||||
|
"select_all": "O seleccionar tot"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"app_name": "Nom de l’aplicacion",
|
"app_name": "Nom de l’aplicacion",
|
||||||
"attachmentRadius": "Pèças juntas",
|
"attachmentRadius": "Pèças juntas",
|
||||||
|
@ -213,8 +220,11 @@
|
||||||
"reply_visibility_self": "Mostrar pas que las responsas que me son destinadas",
|
"reply_visibility_self": "Mostrar pas que las responsas que me son destinadas",
|
||||||
"saving_err": "Error en enregistrant los paramètres",
|
"saving_err": "Error en enregistrant los paramètres",
|
||||||
"saving_ok": "Paramètres enregistrats",
|
"saving_ok": "Paramètres enregistrats",
|
||||||
"scope_copy": "Copiar lo nivèl de confidencialitat per las responsas (Totjorn aissí pels Messatges Dirèctes)",
|
"search_user_to_block": "Cercatz qual volètz blocar",
|
||||||
|
"search_user_to_mute": "Cercatz qual volètz rescondre",
|
||||||
"security_tab": "Seguretat",
|
"security_tab": "Seguretat",
|
||||||
|
"scope_copy": "Copiar lo nivèl de confidencialitat per las responsas (Totjorn aissí pels Messatges Dirèctes)",
|
||||||
|
"minimal_scopes_mode": "Minimizar lo nombre d’opcions per publicacion",
|
||||||
"set_new_avatar": "Definir un nòu avatar",
|
"set_new_avatar": "Definir un nòu avatar",
|
||||||
"set_new_profile_background": "Definir un nòu fons de perfil",
|
"set_new_profile_background": "Definir un nòu fons de perfil",
|
||||||
"set_new_profile_banner": "Definir una nòva bandièra de perfil",
|
"set_new_profile_banner": "Definir una nòva bandièra de perfil",
|
||||||
|
@ -349,6 +359,11 @@
|
||||||
"checkbox": "Ai legit los tèrmes e condicions d’utilizacion",
|
"checkbox": "Ai legit los tèrmes e condicions d’utilizacion",
|
||||||
"link": "un pichon ligam simpatic"
|
"link": "un pichon ligam simpatic"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"title": "Version",
|
||||||
|
"backend_version": "Version Backend",
|
||||||
|
"frontend_version": "Version Frontend"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
|
@ -394,7 +409,26 @@
|
||||||
"block_progress": "Blocatge...",
|
"block_progress": "Blocatge...",
|
||||||
"unmute": "Tornar mostrar",
|
"unmute": "Tornar mostrar",
|
||||||
"unmute_progress": "Afichatge...",
|
"unmute_progress": "Afichatge...",
|
||||||
"mute_progress": "A amagar..."
|
"mute_progress": "A amagar...",
|
||||||
|
"admin_menu": {
|
||||||
|
"moderation": "Moderacion",
|
||||||
|
"grant_admin": "Passar Admin",
|
||||||
|
"revoke_admin": "Revocar Admin",
|
||||||
|
"grant_moderator": "Passar Moderator",
|
||||||
|
"revoke_moderator": "Revocar Moderator",
|
||||||
|
"activate_account": "Activar lo compte",
|
||||||
|
"deactivate_account": "Desactivar lo compte",
|
||||||
|
"delete_account": "Suprimir lo compte",
|
||||||
|
"force_nsfw": "Marcar totas las publicacions coma sensiblas",
|
||||||
|
"strip_media": "Tirar los mèdias de las publicacions",
|
||||||
|
"force_unlisted": "Forçar las publicacions en pas-listadas",
|
||||||
|
"sandbox": "Forçar las publicacions en seguidors solament",
|
||||||
|
"disable_remote_subscription": "Desactivar lo seguiment d’utilizaire d’instàncias alonhadas",
|
||||||
|
"disable_any_subscription": "Desactivar tot seguiment",
|
||||||
|
"quarantine": "Defendre la federacion de las publicacions de l’utilizaire",
|
||||||
|
"delete_user": "Suprimir l’utilizaire",
|
||||||
|
"delete_user_confirmation": "Volètz vertadièrament far aquò ? Aquesta accion se pòt pas anullar."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"timeline_title": "Flux utilizaire",
|
"timeline_title": "Flux utilizaire",
|
||||||
|
|
|
@ -22,6 +22,7 @@ import pushNotifications from './lib/push_notifications_plugin.js'
|
||||||
import messages from './i18n/messages.js'
|
import messages from './i18n/messages.js'
|
||||||
|
|
||||||
import VueChatScroll from 'vue-chat-scroll'
|
import VueChatScroll from 'vue-chat-scroll'
|
||||||
|
import VueClickOutside from 'v-click-outside'
|
||||||
|
|
||||||
import afterStoreSetup from './boot/after_store.js'
|
import afterStoreSetup from './boot/after_store.js'
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ Vue.use(VueTimeago, {
|
||||||
})
|
})
|
||||||
Vue.use(VueI18n)
|
Vue.use(VueI18n)
|
||||||
Vue.use(VueChatScroll)
|
Vue.use(VueChatScroll)
|
||||||
|
Vue.use(VueClickOutside)
|
||||||
|
|
||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
// By default, use the browser locale, we will update it if neccessary
|
// By default, use the browser locale, we will update it if neccessary
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
||||||
import { compact, map, each, merge, find, last } from 'lodash'
|
import { compact, map, each, merge, last, concat, uniq } from 'lodash'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
|
import { registerPushNotifications, unregisterPushNotifications } from '../services/push/push.js'
|
||||||
import oauthApi from '../services/new_api/oauth'
|
import oauthApi from '../services/new_api/oauth'
|
||||||
|
@ -32,6 +32,35 @@ const getNotificationPermission = () => {
|
||||||
return Promise.resolve(Notification.permission)
|
return Promise.resolve(Notification.permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const blockUser = (store, id) => {
|
||||||
|
return store.rootState.api.backendInteractor.blockUser(id)
|
||||||
|
.then((relationship) => {
|
||||||
|
store.commit('updateUserRelationship', [relationship])
|
||||||
|
store.commit('addBlockId', id)
|
||||||
|
store.commit('removeStatus', { timeline: 'friends', userId: id })
|
||||||
|
store.commit('removeStatus', { timeline: 'public', userId: id })
|
||||||
|
store.commit('removeStatus', { timeline: 'publicAndExternal', userId: id })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const unblockUser = (store, id) => {
|
||||||
|
return store.rootState.api.backendInteractor.unblockUser(id)
|
||||||
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
|
}
|
||||||
|
|
||||||
|
const muteUser = (store, id) => {
|
||||||
|
return store.rootState.api.backendInteractor.muteUser(id)
|
||||||
|
.then((relationship) => {
|
||||||
|
store.commit('updateUserRelationship', [relationship])
|
||||||
|
store.commit('addMuteId', id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const unmuteUser = (store, id) => {
|
||||||
|
return store.rootState.api.backendInteractor.unmuteUser(id)
|
||||||
|
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
||||||
|
}
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
setMuted (state, { user: { id }, muted }) {
|
setMuted (state, { user: { id }, muted }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
|
@ -73,42 +102,27 @@ export const mutations = {
|
||||||
endLogin (state) {
|
endLogin (state) {
|
||||||
state.loggingIn = false
|
state.loggingIn = false
|
||||||
},
|
},
|
||||||
// TODO Clean after ourselves?
|
saveFriendIds (state, { id, friendIds }) {
|
||||||
addFriends (state, { id, friends }) {
|
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
each(friends, friend => {
|
user.friendIds = uniq(concat(user.friendIds, friendIds))
|
||||||
if (!find(user.friends, { id: friend.id })) {
|
|
||||||
user.friends.push(friend)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
user.lastFriendId = last(friends).id
|
|
||||||
},
|
},
|
||||||
addFollowers (state, { id, followers }) {
|
saveFollowerIds (state, { id, followerIds }) {
|
||||||
const user = state.usersObject[id]
|
const user = state.usersObject[id]
|
||||||
each(followers, follower => {
|
user.followerIds = uniq(concat(user.followerIds, followerIds))
|
||||||
if (!find(user.followers, { id: follower.id })) {
|
|
||||||
user.followers.push(follower)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
user.lastFollowerId = last(followers).id
|
|
||||||
},
|
},
|
||||||
// Because frontend doesn't have a reason to keep these stuff in memory
|
// Because frontend doesn't have a reason to keep these stuff in memory
|
||||||
// outside of viewing someones user profile.
|
// outside of viewing someones user profile.
|
||||||
clearFriends (state, userId) {
|
clearFriends (state, userId) {
|
||||||
const user = state.usersObject[userId]
|
const user = state.usersObject[userId]
|
||||||
if (!user) {
|
if (user) {
|
||||||
return
|
set(user, 'friendIds', [])
|
||||||
}
|
}
|
||||||
user.friends = []
|
|
||||||
user.lastFriendId = null
|
|
||||||
},
|
},
|
||||||
clearFollowers (state, userId) {
|
clearFollowers (state, userId) {
|
||||||
const user = state.usersObject[userId]
|
const user = state.usersObject[userId]
|
||||||
if (!user) {
|
if (user) {
|
||||||
return
|
set(user, 'followerIds', [])
|
||||||
}
|
}
|
||||||
user.followers = []
|
|
||||||
user.lastFollowerId = null
|
|
||||||
},
|
},
|
||||||
addNewUsers (state, users) {
|
addNewUsers (state, users) {
|
||||||
each(users, (user) => mergeOrAdd(state.users, state.usersObject, user))
|
each(users, (user) => mergeOrAdd(state.users, state.usersObject, user))
|
||||||
|
@ -132,6 +146,11 @@ export const mutations = {
|
||||||
saveBlockIds (state, blockIds) {
|
saveBlockIds (state, blockIds) {
|
||||||
state.currentUser.blockIds = blockIds
|
state.currentUser.blockIds = blockIds
|
||||||
},
|
},
|
||||||
|
addBlockId (state, blockId) {
|
||||||
|
if (state.currentUser.blockIds.indexOf(blockId) === -1) {
|
||||||
|
state.currentUser.blockIds.push(blockId)
|
||||||
|
}
|
||||||
|
},
|
||||||
updateMutes (state, mutedUsers) {
|
updateMutes (state, mutedUsers) {
|
||||||
// Reset muted of all fetched users
|
// Reset muted of all fetched users
|
||||||
each(state.users, (user) => { user.muted = false })
|
each(state.users, (user) => { user.muted = false })
|
||||||
|
@ -140,6 +159,11 @@ export const mutations = {
|
||||||
saveMuteIds (state, muteIds) {
|
saveMuteIds (state, muteIds) {
|
||||||
state.currentUser.muteIds = muteIds
|
state.currentUser.muteIds = muteIds
|
||||||
},
|
},
|
||||||
|
addMuteId (state, muteId) {
|
||||||
|
if (state.currentUser.muteIds.indexOf(muteId) === -1) {
|
||||||
|
state.currentUser.muteIds.push(muteId)
|
||||||
|
}
|
||||||
|
},
|
||||||
setUserForStatus (state, status) {
|
setUserForStatus (state, status) {
|
||||||
status.user = state.usersObject[status.user.id]
|
status.user = state.usersObject[status.user.id]
|
||||||
},
|
},
|
||||||
|
@ -200,8 +224,10 @@ const users = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchUserRelationship (store, id) {
|
fetchUserRelationship (store, id) {
|
||||||
return store.rootState.api.backendInteractor.fetchUserRelationship({ id })
|
if (store.state.currentUser) {
|
||||||
|
store.rootState.api.backendInteractor.fetchUserRelationship({ id })
|
||||||
.then((relationships) => store.commit('updateUserRelationship', relationships))
|
.then((relationships) => store.commit('updateUserRelationship', relationships))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fetchBlocks (store) {
|
fetchBlocks (store) {
|
||||||
return store.rootState.api.backendInteractor.fetchBlocks()
|
return store.rootState.api.backendInteractor.fetchBlocks()
|
||||||
|
@ -211,18 +237,17 @@ const users = {
|
||||||
return blocks
|
return blocks
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
blockUser (store, userId) {
|
blockUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.blockUser(userId)
|
return blockUser(store, id)
|
||||||
.then((relationship) => {
|
|
||||||
store.commit('updateUserRelationship', [relationship])
|
|
||||||
store.commit('removeStatus', { timeline: 'friends', userId })
|
|
||||||
store.commit('removeStatus', { timeline: 'public', userId })
|
|
||||||
store.commit('removeStatus', { timeline: 'publicAndExternal', userId })
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
unblockUser (store, id) {
|
unblockUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.unblockUser(id)
|
return unblockUser(store, id)
|
||||||
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
},
|
||||||
|
blockUsers (store, ids = []) {
|
||||||
|
return Promise.all(ids.map(id => blockUser(store, id)))
|
||||||
|
},
|
||||||
|
unblockUsers (store, ids = []) {
|
||||||
|
return Promise.all(ids.map(id => unblockUser(store, id)))
|
||||||
},
|
},
|
||||||
fetchMutes (store) {
|
fetchMutes (store) {
|
||||||
return store.rootState.api.backendInteractor.fetchMutes()
|
return store.rootState.api.backendInteractor.fetchMutes()
|
||||||
|
@ -233,32 +258,34 @@ const users = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
muteUser (store, id) {
|
muteUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.muteUser(id)
|
return muteUser(store, id)
|
||||||
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
|
||||||
},
|
},
|
||||||
unmuteUser (store, id) {
|
unmuteUser (store, id) {
|
||||||
return store.rootState.api.backendInteractor.unmuteUser(id)
|
return unmuteUser(store, id)
|
||||||
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
|
|
||||||
},
|
},
|
||||||
addFriends ({ rootState, commit }, fetchBy) {
|
muteUsers (store, ids = []) {
|
||||||
return new Promise((resolve, reject) => {
|
return Promise.all(ids.map(id => muteUser(store, id)))
|
||||||
const user = rootState.users.usersObject[fetchBy]
|
},
|
||||||
const maxId = user.lastFriendId
|
unmuteUsers (store, ids = []) {
|
||||||
rootState.api.backendInteractor.fetchFriends({ id: user.id, maxId })
|
return Promise.all(ids.map(id => unmuteUser(store, id)))
|
||||||
|
},
|
||||||
|
fetchFriends ({ rootState, commit }, id) {
|
||||||
|
const user = rootState.users.usersObject[id]
|
||||||
|
const maxId = last(user.friendIds)
|
||||||
|
return rootState.api.backendInteractor.fetchFriends({ id, maxId })
|
||||||
.then((friends) => {
|
.then((friends) => {
|
||||||
commit('addFriends', { id: user.id, friends })
|
commit('addNewUsers', friends)
|
||||||
resolve(friends)
|
commit('saveFriendIds', { id, friendIds: map(friends, 'id') })
|
||||||
}).catch(() => {
|
return friends
|
||||||
reject()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
addFollowers ({ rootState, commit }, fetchBy) {
|
fetchFollowers ({ rootState, commit }, id) {
|
||||||
const user = rootState.users.usersObject[fetchBy]
|
const user = rootState.users.usersObject[id]
|
||||||
const maxId = user.lastFollowerId
|
const maxId = last(user.followerIds)
|
||||||
return rootState.api.backendInteractor.fetchFollowers({ id: user.id, maxId })
|
return rootState.api.backendInteractor.fetchFollowers({ id, maxId })
|
||||||
.then((followers) => {
|
.then((followers) => {
|
||||||
commit('addFollowers', { id: user.id, followers })
|
commit('addNewUsers', followers)
|
||||||
|
commit('saveFollowerIds', { id, followerIds: map(followers, 'id') })
|
||||||
return followers
|
return followers
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -281,6 +308,9 @@ const users = {
|
||||||
|
|
||||||
unregisterPushNotifications(token)
|
unregisterPushNotifications(token)
|
||||||
},
|
},
|
||||||
|
addNewUsers ({ commit }, users) {
|
||||||
|
commit('addNewUsers', users)
|
||||||
|
},
|
||||||
addNewStatuses (store, { statuses }) {
|
addNewStatuses (store, { statuses }) {
|
||||||
const users = map(statuses, 'user')
|
const users = map(statuses, 'user')
|
||||||
const retweetedUsers = compact(map(statuses, 'retweeted_status.user'))
|
const retweetedUsers = compact(map(statuses, 'retweeted_status.user'))
|
||||||
|
|
|
@ -52,7 +52,7 @@ const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media'
|
||||||
const MASTODON_STATUS_FAVORITEDBY_URL = id => `/api/v1/statuses/${id}/favourited_by`
|
const MASTODON_STATUS_FAVORITEDBY_URL = id => `/api/v1/statuses/${id}/favourited_by`
|
||||||
const MASTODON_STATUS_REBLOGGEDBY_URL = id => `/api/v1/statuses/${id}/reblogged_by`
|
const MASTODON_STATUS_REBLOGGEDBY_URL = id => `/api/v1/statuses/${id}/reblogged_by`
|
||||||
|
|
||||||
import { each, map } from 'lodash'
|
import { each, map, concat, last } from 'lodash'
|
||||||
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
import 'whatwg-fetch'
|
import 'whatwg-fetch'
|
||||||
import { StatusCodeError } from '../errors/errors'
|
import { StatusCodeError } from '../errors/errors'
|
||||||
|
@ -296,10 +296,23 @@ const fetchFriends = ({id, maxId, sinceId, limit = 20, credentials}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportFriends = ({id, credentials}) => {
|
const exportFriends = ({id, credentials}) => {
|
||||||
let url = MASTODON_FOLLOWING_URL(id) + `?all=true`
|
return new Promise(async (resolve, reject) => {
|
||||||
return fetch(url, { headers: authHeaders(credentials) })
|
try {
|
||||||
.then((data) => data.json())
|
let friends = []
|
||||||
.then((data) => data.map(parseUser))
|
let more = true
|
||||||
|
while (more) {
|
||||||
|
const maxId = friends.length > 0 ? last(friends).id : undefined
|
||||||
|
const users = await fetchFriends({id, maxId, credentials})
|
||||||
|
friends = concat(friends, users)
|
||||||
|
if (users.length === 0) {
|
||||||
|
more = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(friends)
|
||||||
|
} catch (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchFollowers = ({id, maxId, sinceId, limit = 20, credentials}) => {
|
const fetchFollowers = ({id, maxId, sinceId, limit = 20, credentials}) => {
|
||||||
|
|
|
@ -129,8 +129,8 @@ export const parseUser = (data) => {
|
||||||
output.locked = data.locked
|
output.locked = data.locked
|
||||||
output.followers_count = data.followers_count
|
output.followers_count = data.followers_count
|
||||||
output.statuses_count = data.statuses_count
|
output.statuses_count = data.statuses_count
|
||||||
output.friends = []
|
output.friendIds = []
|
||||||
output.followers = []
|
output.followerIds = []
|
||||||
if (data.pleroma) {
|
if (data.pleroma) {
|
||||||
output.follow_request_count = data.pleroma.follow_request_count
|
output.follow_request_count = data.pleroma.follow_request_count
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,6 +245,12 @@
|
||||||
"css": "bell-alt",
|
"css": "bell-alt",
|
||||||
"code": 61683,
|
"code": 61683,
|
||||||
"src": "fontawesome"
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "5bb103cd29de77e0e06a52638527b575",
|
||||||
|
"css": "wrench",
|
||||||
|
"code": 59418,
|
||||||
|
"src": "fontawesome"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
2
static/font/css/fontello-codes.css
vendored
2
static/font/css/fontello-codes.css
vendored
|
@ -24,6 +24,8 @@
|
||||||
.icon-adjust:before { content: '\e816'; } /* '' */
|
.icon-adjust:before { content: '\e816'; } /* '' */
|
||||||
.icon-edit:before { content: '\e817'; } /* '' */
|
.icon-edit:before { content: '\e817'; } /* '' */
|
||||||
.icon-pencil:before { content: '\e818'; } /* '' */
|
.icon-pencil:before { content: '\e818'; } /* '' */
|
||||||
|
.icon-verified:before { content: '\e819'; } /* '' */
|
||||||
|
.icon-wrench:before { content: '\e81a'; } /* '' */
|
||||||
.icon-spin3:before { content: '\e832'; } /* '' */
|
.icon-spin3:before { content: '\e832'; } /* '' */
|
||||||
.icon-spin4:before { content: '\e834'; } /* '' */
|
.icon-spin4:before { content: '\e834'; } /* '' */
|
||||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||||
|
|
14
static/font/css/fontello-embedded.css
vendored
14
static/font/css/fontello-embedded.css
vendored
File diff suppressed because one or more lines are too long
2
static/font/css/fontello-ie7-codes.css
vendored
2
static/font/css/fontello-ie7-codes.css
vendored
|
@ -24,6 +24,8 @@
|
||||||
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
.icon-verified { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
.icon-wrench { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
|
2
static/font/css/fontello-ie7.css
vendored
2
static/font/css/fontello-ie7.css
vendored
|
@ -35,6 +35,8 @@
|
||||||
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
.icon-verified { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
.icon-wrench { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||||
|
|
16
static/font/css/fontello.css
vendored
16
static/font/css/fontello.css
vendored
|
@ -1,11 +1,11 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'fontello';
|
font-family: 'fontello';
|
||||||
src: url('../font/fontello.eot?72648396');
|
src: url('../font/fontello.eot?11878820');
|
||||||
src: url('../font/fontello.eot?72648396#iefix') format('embedded-opentype'),
|
src: url('../font/fontello.eot?11878820#iefix') format('embedded-opentype'),
|
||||||
url('../font/fontello.woff2?72648396') format('woff2'),
|
url('../font/fontello.woff2?11878820') format('woff2'),
|
||||||
url('../font/fontello.woff?72648396') format('woff'),
|
url('../font/fontello.woff?11878820') format('woff'),
|
||||||
url('../font/fontello.ttf?72648396') format('truetype'),
|
url('../font/fontello.ttf?11878820') format('truetype'),
|
||||||
url('../font/fontello.svg?72648396#fontello') format('svg');
|
url('../font/fontello.svg?11878820#fontello') format('svg');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'fontello';
|
font-family: 'fontello';
|
||||||
src: url('../font/fontello.svg?72648396#fontello') format('svg');
|
src: url('../font/fontello.svg?11878820#fontello') format('svg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -80,6 +80,8 @@
|
||||||
.icon-adjust:before { content: '\e816'; } /* '' */
|
.icon-adjust:before { content: '\e816'; } /* '' */
|
||||||
.icon-edit:before { content: '\e817'; } /* '' */
|
.icon-edit:before { content: '\e817'; } /* '' */
|
||||||
.icon-pencil:before { content: '\e818'; } /* '' */
|
.icon-pencil:before { content: '\e818'; } /* '' */
|
||||||
|
.icon-verified:before { content: '\e819'; } /* '' */
|
||||||
|
.icon-wrench:before { content: '\e81a'; } /* '' */
|
||||||
.icon-spin3:before { content: '\e832'; } /* '' */
|
.icon-spin3:before { content: '\e832'; } /* '' */
|
||||||
.icon-spin4:before { content: '\e834'; } /* '' */
|
.icon-spin4:before { content: '\e834'; } /* '' */
|
||||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||||
|
|
26
static/font/demo.html
Normal file → Executable file
26
static/font/demo.html
Normal file → Executable file
|
@ -229,11 +229,11 @@ body {
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'fontello';
|
font-family: 'fontello';
|
||||||
src: url('./font/fontello.eot?23081587');
|
src: url('./font/fontello.eot?60799712');
|
||||||
src: url('./font/fontello.eot?23081587#iefix') format('embedded-opentype'),
|
src: url('./font/fontello.eot?60799712#iefix') format('embedded-opentype'),
|
||||||
url('./font/fontello.woff?23081587') format('woff'),
|
url('./font/fontello.woff?60799712') format('woff'),
|
||||||
url('./font/fontello.ttf?23081587') format('truetype'),
|
url('./font/fontello.ttf?60799712') format('truetype'),
|
||||||
url('./font/fontello.svg?23081587#fontello') format('svg');
|
url('./font/fontello.svg?60799712#fontello') format('svg');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -335,25 +335,29 @@ body {
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="the-icons span3" title="Code: 0xe818"><i class="demo-icon icon-pencil"></i> <span class="i-name">icon-pencil</span><span class="i-code">0xe818</span></div>
|
<div class="the-icons span3" title="Code: 0xe818"><i class="demo-icon icon-pencil"></i> <span class="i-name">icon-pencil</span><span class="i-code">0xe818</span></div>
|
||||||
|
<div class="the-icons span3" title="Code: 0xe819"><i class="demo-icon icon-verified"></i> <span class="i-name">icon-verified</span><span class="i-code">0xe819</span></div>
|
||||||
|
<div class="the-icons span3" title="Code: 0xe81a"><i class="demo-icon icon-wrench"></i> <span class="i-name">icon-wrench</span><span class="i-code">0xe81a</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
|
<div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
|
<div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div>
|
<div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
|
<div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div>
|
<div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
|
<div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="the-icons span3" title="Code: 0xf0f3"><i class="demo-icon icon-bell-alt"></i> <span class="i-name">icon-bell-alt</span><span class="i-code">0xf0f3</span></div>
|
<div class="the-icons span3" title="Code: 0xf0f3"><i class="demo-icon icon-bell-alt"></i> <span class="i-name">icon-bell-alt</span><span class="i-code">0xf0f3</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div>
|
<div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
|
|
||||||
<div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
|
||||||
|
<div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div>
|
<div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div>
|
<div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
|
<div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
|
||||||
<div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div>
|
<div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Binary file not shown.
|
@ -56,6 +56,10 @@
|
||||||
|
|
||||||
<glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
|
<glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
|
||||||
|
|
||||||
|
<glyph glyph-name="verified" unicode="" d="M926 453l-19 13c-21 14-30 41-23 65l6 22c10 34-13 69-48 75l-23 4c-25 4-45 23-49 48l-4 23c-6 35-41 57-75 47l-22-7c-24-7-51 2-65 22l-14 20c-21 29-62 33-88 9l-17-16c-19-17-46-21-69-8l-20 11c-31 17-70 3-84-30l-9-22c-9-24-33-39-58-37l-23 1c-36 2-65-28-62-63l2-23c2-25-13-49-36-59l-21-9c-33-14-46-53-29-84l12-20c13-22 10-50-7-69l-15-17c-24-27-19-68 11-88l19-13c21-14 30-41 23-65l-9-23c-10-34 13-69 48-75l23-4c25-4 45-23 49-48l4-23c6-35 41-57 75-47l22 7c24 7 51-2 65-22l14-19c21-29 62-33 88-9l17 16c19 17 46 21 69 8l20-11c31-17 70-3 84 30l9 22c9 24 33 39 58 37l23-1c36-2 65 28 62 63l-1 23c-2 25 13 49 36 59l21 9c33 14 46 53 29 84l-12 20c-13 22-10 50 7 69l15 17c25 26 20 68-9 88z m-399-189l-82-81-81 82-78 79 82 81 78-79 187 186 81-82-187-186z" horiz-adv-x="1000" />
|
||||||
|
|
||||||
|
<glyph glyph-name="wrench" unicode="" d="M214 36q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m360 234l-381-381q-21-20-50-20-29 0-51 20l-59 61q-21 20-21 50 0 29 21 51l380 380q22-55 64-97t97-64z m354 243q0-22-13-59-27-75-92-122t-144-46q-104 0-177 73t-73 177 73 176 177 74q32 0 67-10t60-26q9-6 9-15t-9-16l-163-94v-125l108-60q2 2 44 27t75 45 40 20q8 0 13-5t5-14z" horiz-adv-x="928.6" />
|
||||||
|
|
||||||
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
||||||
|
|
||||||
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
||||||
|
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
14
yarn.lock
14
yarn.lock
|
@ -6389,6 +6389,10 @@ uuid@^3.3.2:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||||
|
|
||||||
|
v-click-outside@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/v-click-outside/-/v-click-outside-2.1.1.tgz#5af80b68a1c82eac89c597890434fa3994b42ed1"
|
||||||
|
|
||||||
validate-npm-package-license@^3.0.1:
|
validate-npm-package-license@^3.0.1:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
||||||
|
@ -6426,16 +6430,6 @@ vue-chat-scroll@^1.2.1:
|
||||||
version "1.3.5"
|
version "1.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/vue-chat-scroll/-/vue-chat-scroll-1.3.5.tgz#a5ee5bae5058f614818a96eac5ee3be4394a2f68"
|
resolved "https://registry.yarnpkg.com/vue-chat-scroll/-/vue-chat-scroll-1.3.5.tgz#a5ee5bae5058f614818a96eac5ee3be4394a2f68"
|
||||||
|
|
||||||
vue-compose@^0.7.1:
|
|
||||||
version "0.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/vue-compose/-/vue-compose-0.7.1.tgz#1c11c4cd5e2c8f2743b03fce8ab43d78aabc20b3"
|
|
||||||
dependencies:
|
|
||||||
vue-hoc "0.x.x"
|
|
||||||
|
|
||||||
vue-hoc@0.x.x:
|
|
||||||
version "0.4.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/vue-hoc/-/vue-hoc-0.4.7.tgz#4d3322ba89b8b0e42b19045ef536c21d948a4fac"
|
|
||||||
|
|
||||||
vue-hot-reload-api@^2.0.11:
|
vue-hot-reload-api@^2.0.11:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2"
|
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2"
|
||||||
|
|
Loading…
Reference in a new issue