diff --git a/src/components/list/list.js b/src/components/list/list.js index 600ad8802..61002c21b 100644 --- a/src/components/list/list.js +++ b/src/components/list/list.js @@ -1,5 +1,3 @@ -import { isEmpty } from 'lodash' - import Checkbox from 'src/components/checkbox/checkbox.vue' const List = { @@ -10,7 +8,7 @@ const List = { }, items: { type: Array, - default: () => [], + default: [], }, fetchFunction: { type: Function, @@ -40,28 +38,37 @@ const List = { type: Boolean, default: false, }, + loading: { + type: Boolean, + default: true, + }, + bottomedOut: { + type: Boolean, + default: false, + }, + error: { + type: String, + default: null, + }, }, + emits: ['fetchRequested'], components: { Checkbox, }, data() { return { - loading: false, - bottomedOut: false, - error: false, - dynamicItems: this.itemsFunction ? [] : null, selected: [], } }, computed: { allKeys() { - return this.actualItems.map(this.getKey) + return this.items.map(this.getKey) }, filteredSelected() { return this.allKeys.filter((key) => this.selected.indexOf(key) !== -1) }, allSelected() { - return this.filteredSelected.length === this.actualItems.length + return this.filteredSelected.length === this.items.length }, noneSelected() { return this.filteredSelected.length === 0 @@ -69,54 +76,26 @@ const List = { someSelected() { return !this.allSelected && !this.noneSelected }, - actualItems() { - return this.dynamicItems || this.actualItems - }, }, created() { - if (this.fetchFunction) { - window.addEventListener('scroll', this.scrollLoad) + window.addEventListener('scroll', this.scrollLoad) - if (this.dynamicItems.length === 0) { - this.fetchEntries() - } + if (this.items.length === 0) { + this.fetchEntries() } }, unmounted() { window.removeEventListener('scroll', this.scrollLoad) }, methods: { - // Entries is not a computed because computed can't track the dynamic - // selector for changes and won't trigger after fetch. - updateEntries(newEntries) { - this.dynamicItems = this.itemsFunction(newEntries) - }, fetchEntries() { - if (!this.loading) { - this.loading = true - this.error = false - this.fetchFunction() - .then((newEntries) => { - this.loading = false - this.bottomedOut = isEmpty(newEntries) - return newEntries - }) - .catch((error) => { - this.loading = false - this.error = error - }) - .finally((newEntries) => { - this.updateEntries(newEntries) - }) - } + this.$emit('fetchRequested') }, scrollLoad(e) { if (this.fetchFunction) { const bodyBRect = document.body.getBoundingClientRect() const height = Math.max(bodyBRect.height, -bodyBRect.y) if ( - this.loading === false && - this.bottomedOut === false && this.$el.offsetHeight > 0 && window.innerHeight + window.pageYOffset >= height - 750 ) { @@ -128,7 +107,6 @@ const List = { return this.filteredSelected.indexOf(this.getKey(item)) !== -1 }, toggle(checked, item) { - console.log('TOGGLE', checked, item) const key = this.getKey(item) const oldChecked = this.isSelected(key) if (checked !== oldChecked) { @@ -138,6 +116,7 @@ const List = { this.selected.splice(this.selected.indexOf(key), 1) } } + this.$emit('selected', this.selected) }, toggleAll(value) { if (value) { @@ -145,6 +124,7 @@ const List = { } else { this.selected = [] } + this.$emit('selected', this.selected) }, }, } diff --git a/src/components/list/list.vue b/src/components/list/list.vue index 5703e2b0d..ab916dfe6 100644 --- a/src/components/list/list.vue +++ b/src/components/list/list.vue @@ -28,7 +28,7 @@ role="list" >
diff --git a/src/components/page_list/page_list.js b/src/components/page_list/page_list.js deleted file mode 100644 index 3030b0a4a..000000000 --- a/src/components/page_list/page_list.js +++ /dev/null @@ -1,87 +0,0 @@ -import SelectableList from 'src/components/selectable_list/selectable_list.vue' - -const PageList = { - components: { - SelectableList, - }, - props: { - /** - * only make the checkbox clickable to toggle, not the whole area - */ - boxOnly: { - type: Boolean, - default: false, - }, - /** - * how many entries to fetch at once - */ - pageSize: { - type: Number, - default: 50, - }, - /** - * the function/callback used to fetch new entries (one page) - */ - fetchPage: { - type: Function, - default: async () => [], - }, - /** - * wether or not this is a single page list (so it won't allow fetching more pages) - */ - singlePage: { - type: Boolean, - default: false, - }, - }, - data() { - return { - pageIndex: 1, - items: [], - canLoadMore: true, - isLoading: false, - } - }, - methods: { - /** - * reset and load first page - */ - reset() { - this.canLoadMore = true - this.pageIndex = 1 - this.items = [] - this.isLoading = false - this.loadMore() // load one page - }, - /** - * load another page - */ - loadMore() { - if (!this.isLoading && this.canLoadMore) { - this.isLoading = true - console.log('is loading = true') - this.fetchPage(this.$store, { - page: this.pageIndex++, - pageSize: this.pageSize, - }).then((items) => { - this.items = [...this.items, ...items] - this.isLoading = false - }) - } - }, - /** - * get currently selected elements - * @returns {Array} - */ - getSelected() { - return this.$refs.list.selected - }, - }, - /** - * auto-load first page when mounted - */ - mounted() { - this.loadMore() - }, -} -export default PageList diff --git a/src/components/page_list/page_list.vue b/src/components/page_list/page_list.vue deleted file mode 100644 index 6e5e1d164..000000000 --- a/src/components/page_list/page_list.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - - - diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js deleted file mode 100644 index a6abae982..000000000 --- a/src/components/selectable_list/selectable_list.js +++ /dev/null @@ -1,70 +0,0 @@ -import Checkbox from 'src/components/checkbox/checkbox.vue' -import List from 'src/components/list/list.vue' - -const SelectableList = { - components: { - List, - Checkbox, - }, - props: { - boxOnly: { - type: Boolean, - default: false, - }, - 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 diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue deleted file mode 100644 index b760508d1..000000000 --- a/src/components/selectable_list/selectable_list.vue +++ /dev/null @@ -1,119 +0,0 @@ - - - - - diff --git a/src/components/settings_modal/admin_tabs/users_tab.js b/src/components/settings_modal/admin_tabs/users_tab.js index 6dcfbb488..47e7f8fb4 100644 --- a/src/components/settings_modal/admin_tabs/users_tab.js +++ b/src/components/settings_modal/admin_tabs/users_tab.js @@ -1,7 +1,9 @@ +import { isEmpty } from 'lodash' + import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue' import Checkbox from 'src/components/checkbox/checkbox.vue' import GenericConfirm from 'src/components/confirm_modal/generic_confirm.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 ProgressButton from 'src/components/progress_button/progress_button.vue' import Select from 'src/components/select/select.vue' @@ -17,7 +19,6 @@ const UsersTab = { }, data() { return { - init: false, filtersOrigin: 'local', filtersActivity: 'all', filtersPrivileges: 'all', @@ -28,6 +29,11 @@ const UsersTab = { filtersEmail: '', expandedUser: null, loading: false, + error: null, + bottomedOut: false, + users: [], + page: 1, + total: null, } }, computed: { @@ -79,26 +85,7 @@ const UsersTab = { filtersExternal() { return this.filtersOrigin === 'external' }, - }, - components: { - Checkbox, - Select, - BasicUserCard, - PageList, - ProgressButton, - AdminCard, - TabSwitcher, - Popover, - GenericConfirm, - }, - methods: { - /** - * fetch a new page of users via admin-api - * @param {object} store - * @param {object} opts - */ - fetchPage(store, opts) { - if (!this.init) return new Promise(() => []) + fetchOptions() { const filters = { isAdmin: this.filtersIsAdmin, isModerator: this.filtersIsModerator, @@ -109,22 +96,51 @@ const UsersTab = { needApproval: this.filtersNeedApproval, unconfirmed: this.filtersUnconfirmeUnconfirmed, } - const nopts = { - ...opts, - ...{ - query: this.filtersQuery, - filters, - name: this.filtersName, - email: this.filtersEmail, - }, + + return { + query: this.filtersQuery, + name: this.filtersName, + email: this.filtersEmail, + pageSize: 50, + filters, } - return store.dispatch('fetchAdminUsers', nopts) }, - /** - * reset the userlist explicitly - */ - reset() { - this.$refs.userList.reset() + }, + components: { + Checkbox, + Select, + BasicUserCard, + List, + ProgressButton, + AdminCard, + TabSwitcher, + Popover, + GenericConfirm, + }, + methods: { + fetchPage() { + if (this.loading) return + + this.loading = true + this.error = null + + this.$store + .dispatch('fetchAdminUsers', { + ...this.fetchOptions, + page: this.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 + }) }, /** * show the confirmation box for bulk actions. @@ -147,20 +163,18 @@ const UsersTab = { u.id !== this.$store.state.users.currentUser.id ) { const uf = this.$store.getters.findUser(u.id) - console.log('user: ', uf) this.$store.dispatch(action, this.$store.getters.findUser(u.id)) } }) - this.reset() }, }, - /** - * mark as initialized and reset user list - */ - mounted() { - this.init = true - this.reset() - }, + watch: { + fetchOptions () { + this.page = 1 + this.users = [] + this.fetchPage() + } + } } export default UsersTab diff --git a/src/components/settings_modal/admin_tabs/users_tab.scss b/src/components/settings_modal/admin_tabs/users_tab.scss index 892abb02c..537e43d09 100644 --- a/src/components/settings_modal/admin_tabs/users_tab.scss +++ b/src/components/settings_modal/admin_tabs/users_tab.scss @@ -1,6 +1,6 @@ .UsersTab { max-height: 100%; - display: grid; + display: flex; flex-direction: column; overflow-y: hidden; diff --git a/src/components/settings_modal/admin_tabs/users_tab.vue b/src/components/settings_modal/admin_tabs/users_tab.vue index 970bf5609..77006f61c 100644 --- a/src/components/settings_modal/admin_tabs/users_tab.vue +++ b/src/components/settings_modal/admin_tabs/users_tab.vue @@ -14,7 +14,6 @@
@@ -43,7 +40,6 @@
-