i changed my mind, fetch logic does belong in <List>
This commit is contained in:
parent
a0d5decc49
commit
4a0be19607
9 changed files with 77 additions and 137 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { isEmpty } from 'lodash'
|
||||||
|
|
||||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
|
||||||
const List = {
|
const List = {
|
||||||
|
|
@ -6,21 +8,13 @@ const List = {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
items: {
|
|
||||||
type: Array,
|
|
||||||
default: [],
|
|
||||||
},
|
|
||||||
fetchFunction: {
|
fetchFunction: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
itemsFunction: {
|
|
||||||
type: Function,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
getKey: {
|
getKey: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: (item) => item.id,
|
default: (item) => item,
|
||||||
},
|
},
|
||||||
getClass: {
|
getClass: {
|
||||||
type: Function,
|
type: Function,
|
||||||
|
|
@ -38,16 +32,8 @@ const List = {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
loading: {
|
externalItems: {
|
||||||
type: Boolean,
|
type: Array,
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
bottomedOut: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -57,25 +43,34 @@ const List = {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selected: [],
|
items: [],
|
||||||
|
selected: new Set([]),
|
||||||
|
loading: false,
|
||||||
|
bottomedOut: true,
|
||||||
|
error: null,
|
||||||
|
page: 1,
|
||||||
|
total: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
allKeys() {
|
allKeys() {
|
||||||
return this.items.map(this.getKey)
|
return new Set(this.finalItems.map(this.getKey))
|
||||||
},
|
},
|
||||||
filteredSelected() {
|
filteredSelected() {
|
||||||
return this.allKeys.filter((key) => this.selected.indexOf(key) !== -1)
|
return [ ...this.allKeys.values().filter((key) => this.selected.has(key))]
|
||||||
},
|
},
|
||||||
allSelected() {
|
allSelected() {
|
||||||
return this.filteredSelected.length === this.items.length
|
return this.selected.size === this.finalItems.length
|
||||||
},
|
},
|
||||||
noneSelected() {
|
noneSelected() {
|
||||||
return this.filteredSelected.length === 0
|
return this.selected.size === 0
|
||||||
},
|
},
|
||||||
someSelected() {
|
someSelected() {
|
||||||
return !this.allSelected && !this.noneSelected
|
return !this.allSelected && !this.noneSelected
|
||||||
},
|
},
|
||||||
|
finalItems() {
|
||||||
|
return this.externalItems || this.items
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
window.addEventListener('scroll', this.scrollLoad)
|
window.addEventListener('scroll', this.scrollLoad)
|
||||||
|
|
@ -89,7 +84,32 @@ const List = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchEntries() {
|
fetchEntries() {
|
||||||
this.$emit('fetchRequested')
|
if (this.loading) return
|
||||||
|
|
||||||
|
this.loading = true
|
||||||
|
this.error = null
|
||||||
|
|
||||||
|
this.fetchFunction(this.page)
|
||||||
|
.then((result) => {
|
||||||
|
this.loading = false
|
||||||
|
this.bottomedOut = isEmpty(result.items)
|
||||||
|
if (this.externalItems) return
|
||||||
|
this.page += 1
|
||||||
|
this.total = result.count
|
||||||
|
this.items.push(...result.items)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.loading = false
|
||||||
|
this.error = error
|
||||||
|
})
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.items = []
|
||||||
|
this.page = 1
|
||||||
|
this.total = null
|
||||||
|
this.error = null
|
||||||
|
this.loading = false
|
||||||
|
this.fetchEntries()
|
||||||
},
|
},
|
||||||
scrollLoad(e) {
|
scrollLoad(e) {
|
||||||
if (this.fetchFunction) {
|
if (this.fetchFunction) {
|
||||||
|
|
@ -111,18 +131,18 @@ const List = {
|
||||||
const oldChecked = this.isSelected(key)
|
const oldChecked = this.isSelected(key)
|
||||||
if (checked !== oldChecked) {
|
if (checked !== oldChecked) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.selected.push(key)
|
this.selected.add(key)
|
||||||
} else {
|
} else {
|
||||||
this.selected.splice(this.selected.indexOf(key), 1)
|
this.selected.delete(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$emit('selected', this.selected)
|
this.$emit('selected', this.selected)
|
||||||
},
|
},
|
||||||
toggleAll(value) {
|
toggleAll(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.selected = this.allKeys.slice(0)
|
this.selected = new Set([...this.allKeys])
|
||||||
} else {
|
} else {
|
||||||
this.selected = []
|
this.selected = new Set([])
|
||||||
}
|
}
|
||||||
this.$emit('selected', this.selected)
|
this.$emit('selected', this.selected)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
role="list"
|
role="list"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="item in items"
|
v-for="item in finalItems"
|
||||||
:key="getKey(item)"
|
:key="getKey(item)"
|
||||||
class="list-item"
|
class="list-item"
|
||||||
:class="[getClass(item), nonInteractive ? '-non-interactive' : '']"
|
:class="[getClass(item), nonInteractive ? '-non-interactive' : '']"
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="items.length === 0 && !!$slots.empty"
|
v-if="finalItems.length === 0 && !!$slots.empty"
|
||||||
class="list-empty-content faint"
|
class="list-empty-content faint"
|
||||||
>
|
>
|
||||||
<slot name="empty" />
|
<slot name="empty" />
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import GenericConfirm from 'src/components/confirm_modal/generic_confirm.vue'
|
import GenericConfirm from 'src/components/confirm_modal/generic_confirm.vue'
|
||||||
import TextConfirm from 'src/components/confirm_modal/text_confirm.vue'
|
import TextConfirm from 'src/components/confirm_modal/text_confirm.vue'
|
||||||
import Modal from 'src/components/modal/modal.vue'
|
import Modal from 'src/components/modal/modal.vue'
|
||||||
import PageList from 'src/components/page_list/page_list.vue'
|
import List from 'src/components/list/list.vue'
|
||||||
import Popover from 'src/components/popover/popover.vue'
|
import Popover from 'src/components/popover/popover.vue'
|
||||||
import Select from 'src/components/select/select.vue'
|
import Select from 'src/components/select/select.vue'
|
||||||
import AdminStatusCard from 'src/components/settings_modal/admin_tabs/admin_status_card.vue'
|
import AdminStatusCard from 'src/components/settings_modal/admin_tabs/admin_status_card.vue'
|
||||||
|
|
@ -132,7 +132,7 @@ const AdminCard = {
|
||||||
components: {
|
components: {
|
||||||
BasicUserCard,
|
BasicUserCard,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
PageList,
|
List,
|
||||||
AdminStatusCard,
|
AdminStatusCard,
|
||||||
Modal,
|
Modal,
|
||||||
Popover,
|
Popover,
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,6 @@ const UsersTab = {
|
||||||
filtersName: '',
|
filtersName: '',
|
||||||
filtersEmail: '',
|
filtersEmail: '',
|
||||||
expandedUser: null,
|
expandedUser: null,
|
||||||
loading: false,
|
|
||||||
error: null,
|
|
||||||
bottomedOut: false,
|
|
||||||
users: [],
|
|
||||||
page: 1,
|
|
||||||
total: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -118,29 +112,14 @@ const UsersTab = {
|
||||||
GenericConfirm,
|
GenericConfirm,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchPage() {
|
fetchUsers(page) {
|
||||||
if (this.loading) return
|
console.log(page)
|
||||||
|
return this.$store
|
||||||
this.loading = true
|
|
||||||
this.error = null
|
|
||||||
|
|
||||||
this.$store
|
|
||||||
.dispatch('fetchAdminUsers', {
|
.dispatch('fetchAdminUsers', {
|
||||||
...this.fetchOptions,
|
...this.fetchOptions,
|
||||||
page: this.page,
|
page,
|
||||||
})
|
|
||||||
.then((result) => {
|
|
||||||
console.log('RESULT', result)
|
|
||||||
this.loading = false
|
|
||||||
this.bottomedOut = isEmpty(result.users)
|
|
||||||
this.page += 1
|
|
||||||
this.total = result.count
|
|
||||||
this.users.push(...result.users)
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.loading = false
|
|
||||||
this.error = error
|
|
||||||
})
|
})
|
||||||
|
.then(({ count, users }) => ({ count, items: users }))
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* show the confirmation box for bulk actions.
|
* show the confirmation box for bulk actions.
|
||||||
|
|
@ -170,9 +149,7 @@ const UsersTab = {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
fetchOptions () {
|
fetchOptions () {
|
||||||
this.page = 1
|
this.$refs.usersList.reset()
|
||||||
this.users = []
|
|
||||||
this.fetchPage()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,12 +121,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<List
|
<List
|
||||||
:get-key="i => i"
|
ref="usersList"
|
||||||
:items="users"
|
:fetch-function="fetchUsers"
|
||||||
:loading="loading"
|
|
||||||
:error="error"
|
|
||||||
:bottomed-out="bottomedOut"
|
|
||||||
@fetch-requested="fetchPage"
|
|
||||||
selectable
|
selectable
|
||||||
scrollable
|
scrollable
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import DomainMuteCard from 'src/components/domain_mute_card/domain_mute_card.vue
|
||||||
import List from 'src/components/list/list.vue'
|
import List from 'src/components/list/list.vue'
|
||||||
import MuteCard from 'src/components/mute_card/mute_card.vue'
|
import MuteCard from 'src/components/mute_card/mute_card.vue'
|
||||||
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
import ProgressButton from 'src/components/progress_button/progress_button.vue'
|
||||||
import SelectableList from 'src/components/selectable_list/selectable_list.vue'
|
|
||||||
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
||||||
|
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
|
|
@ -61,24 +60,7 @@ const MutesAndBlocks = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchItems(group) {
|
fetchItems(group) {
|
||||||
if (this[group + 'Loading']) return
|
return () => this.$store.dispatch('fetch' + group, this.userId)
|
||||||
|
|
||||||
const capGroup = group[0].toUpperCase() + group.slice(1)
|
|
||||||
|
|
||||||
this[group + 'Loading'] = true
|
|
||||||
this[group + 'Error'] = null
|
|
||||||
|
|
||||||
this.$store
|
|
||||||
.dispatch('fetch' + capGroup, this.userId)
|
|
||||||
.then((newEntries) => {
|
|
||||||
this[group + 'Loading'] = false
|
|
||||||
this[group + 'BottomedOut'] = isEmpty(newEntries)
|
|
||||||
return newEntries
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this[group + 'Loading'] = false
|
|
||||||
this[group + 'Error'] = error
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
importFollows(file) {
|
importFollows(file) {
|
||||||
return this.$store.state.api.backendInteractor
|
return this.$store.state.api.backendInteractor
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,8 @@
|
||||||
</div>
|
</div>
|
||||||
<List
|
<List
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
:items="blocks"
|
:external-items="blocks"
|
||||||
:loading="blocksLoading"
|
:fetch-function="fetchItems('Blocks')"
|
||||||
:error="blocksError"
|
|
||||||
:bottomed-out="blocksBottomedOut"
|
|
||||||
@fetch-requested="fetchItems('blocks')"
|
|
||||||
scrollable
|
scrollable
|
||||||
selectable
|
selectable
|
||||||
>
|
>
|
||||||
|
|
@ -79,11 +76,8 @@
|
||||||
</div>
|
</div>
|
||||||
<List
|
<List
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
:items="mutes"
|
:external-items="mutes"
|
||||||
:loading="mutesLoading"
|
:fetch-function="fetchItems('Mutes')"
|
||||||
:error="mutesError"
|
|
||||||
:bottomed-out="mutesBottomedOut"
|
|
||||||
@fetch-requested="fetchItems('mutes')"
|
|
||||||
scrollable
|
scrollable
|
||||||
selectable
|
selectable
|
||||||
>
|
>
|
||||||
|
|
@ -136,11 +130,8 @@
|
||||||
</div>
|
</div>
|
||||||
<List
|
<List
|
||||||
:get-key="i => i"
|
:get-key="i => i"
|
||||||
:items="domains"
|
:external-items="domains"
|
||||||
:loading="domainsLoading"
|
:fetch-function="fetchItems('DomainMutes')"
|
||||||
:error="domainsError"
|
|
||||||
:bottomed-out="domainsBottomedOut"
|
|
||||||
@fetch-requested="fetchItems('domainMutes')"
|
|
||||||
scrollable
|
scrollable
|
||||||
selectable
|
selectable
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { get, isEmpty } from 'lodash'
|
import { get } from 'lodash'
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import Conversation from 'src/components/conversation/conversation.vue'
|
import Conversation from 'src/components/conversation/conversation.vue'
|
||||||
|
|
@ -27,12 +27,6 @@ const UserProfile = {
|
||||||
userId: null,
|
userId: null,
|
||||||
tab: defaultTabKey,
|
tab: defaultTabKey,
|
||||||
footerRef: null,
|
footerRef: null,
|
||||||
friendsLoading: false,
|
|
||||||
friendsError: null,
|
|
||||||
friendsBottomedOut: false,
|
|
||||||
followersLoading: false,
|
|
||||||
followersError: null,
|
|
||||||
followersBottomedOut: false,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
@ -109,24 +103,10 @@ const UserProfile = {
|
||||||
this.footerRef = el
|
this.footerRef = el
|
||||||
},
|
},
|
||||||
fetchUsers(group) {
|
fetchUsers(group) {
|
||||||
if (this[group + 'Loading']) return
|
return () => this
|
||||||
|
.$store
|
||||||
const capGroup = group[0].toUpperCase() + group.slice(1)
|
.dispatch('fetch' + group, this.userId)
|
||||||
|
.then((result) => ({ items: result }))
|
||||||
this[group + 'Loading'] = true
|
|
||||||
this[group + 'Error'] = null
|
|
||||||
|
|
||||||
this.$store
|
|
||||||
.dispatch('fetch' + capGroup, this.userId)
|
|
||||||
.then((newEntries) => {
|
|
||||||
this[group + 'Loading'] = false
|
|
||||||
this[group + 'BottomedOut'] = isEmpty(newEntries)
|
|
||||||
return newEntries
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this[group + 'Loading'] = false
|
|
||||||
this[group + 'Error'] = error
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
load(userNameOrId) {
|
load(userNameOrId) {
|
||||||
const startFetchingTimeline = (timeline, userId) => {
|
const startFetchingTimeline = (timeline, userId) => {
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,8 @@
|
||||||
:disabled="!user.friends_count"
|
:disabled="!user.friends_count"
|
||||||
>
|
>
|
||||||
<List
|
<List
|
||||||
:items="friends"
|
:fetch-function="fetchUsers('Friends')"
|
||||||
:loading="friendsLoading"
|
:external-items="friends"
|
||||||
:error="friendsError"
|
|
||||||
:bottomed-out="friendsBottomedOut"
|
|
||||||
@fetch-requested="fetchUsers('friends')"
|
|
||||||
>
|
>
|
||||||
<template #item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard :user="item" />
|
<FollowCard :user="item" />
|
||||||
|
|
@ -59,11 +56,8 @@
|
||||||
:disabled="!user.followers_count"
|
:disabled="!user.followers_count"
|
||||||
>
|
>
|
||||||
<List
|
<List
|
||||||
:items="followers"
|
:fetch-function="fetchUsers('Followers')"
|
||||||
:loading="followersLoading"
|
:external-items="followers"
|
||||||
:error="followersError"
|
|
||||||
:bottomed-out="followersBottomedOut"
|
|
||||||
@fetch-requested="fetchUsers('followers')"
|
|
||||||
>
|
>
|
||||||
<template #item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard
|
<FollowCard
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue