diff --git a/CHANGELOG.md b/CHANGELOG.md
index d75c63d1..19b74ca0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased
+### Changed
+
+- Statuses count changes when an instance is selected and shows the amount of statuses from an originating instance
+- Add a dialog window with a confirmation when a remove button is clicked on the Settings page
+
+### Fixed
+
+- Send `true` and `false` as booleans if they are values of single selects on the Settings page
+
## [2.0.3] - 2020-04-29
### Added
diff --git a/src/api/__mocks__/peers.js b/src/api/__mocks__/peers.js
new file mode 100644
index 00000000..da61938f
--- /dev/null
+++ b/src/api/__mocks__/peers.js
@@ -0,0 +1,4 @@
+export async function fetchPeers(authHost, token) {
+ const data = ['lain.com', 'heaven.com']
+ return Promise.resolve({ data })
+}
diff --git a/src/api/__mocks__/status.js b/src/api/__mocks__/status.js
index 0e7bc9fb..c8f98545 100644
--- a/src/api/__mocks__/status.js
+++ b/src/api/__mocks__/status.js
@@ -5,3 +5,66 @@ export async function changeStatusScope(id, sensitive, visibility, authHost, tok
export async function deleteStatus(id, authHost, token) {
return Promise.resolve()
}
+
+export async function fetchStatusesByInstance({ instance, authHost, token, pageSize, page }) {
+ let data
+ if (pageSize === 1) {
+ data = page === 1 || page === 2
+ ? [{
+ 'account': {
+ 'avatar': 'http://localhost:4000/images/avi.png',
+ 'display_name': 'sky',
+ 'url': 'http://localhost:4000/users/sky'
+ },
+ 'content': 'A nice young couple contacted us from Brazil to decorate their newly acquired apartment.',
+ 'created_at': '2020-01-31T18:20:01.000Z',
+ 'id': '9rZIr0Jzao5Gjgfmro',
+ 'sensitive': false,
+ 'url': 'http://localhost:4000/objects/7af9abbd-fb6c-4318-aeb7-6636c138ac98',
+ 'visibility': 'unlisted'
+ }]
+ : []
+ } else {
+ data = [
+ {
+ 'account': {
+ 'avatar': 'http://localhost:4000/images/avi.png',
+ 'display_name': 'sky',
+ 'url': 'http://localhost:4000/users/sky'
+ },
+ 'content': 'A nice young couple contacted us from Brazil to decorate their newly acquired apartment.',
+ 'created_at': '2020-01-31T18:20:01.000Z',
+ 'id': '9rZIr0Jzao5Gjgfmro',
+ 'sensitive': false,
+ 'url': 'http://localhost:4000/objects/7af9abbd-fb6c-4318-aeb7-6636c138ac98',
+ 'visibility': 'unlisted'
+ },
+ {
+ 'account': {
+ 'avatar': 'http://localhost:4000/images/avi.png',
+ 'display_name': 'sky',
+ 'url': 'http://localhost:4000/users/sky'
+ },
+ 'content': 'the happiest man ever',
+ 'created_at': '2019-11-23T12:56:18.000Z',
+ 'id': '9pFoVfWMU3A96Rzq3k',
+ 'sensitive': false,
+ 'url': 'http://localhost:4000/objects/449c90fe-c457-4c64-baf2-fe6d0a59ca25',
+ 'visibility': 'unlisted'
+ }]
+ }
+ return Promise.resolve({ data })
+}
+
+export async function fetchStatusesCount(instance, authHost, token) {
+ const data = instance === 'heaven.com'
+ ? {
+ 'status_visibility':
+ { 'direct': 1, 'private': 2, 'public': 3, 'unlisted': 0 }
+ }
+ : {
+ 'status_visibility':
+ { 'direct': 4, 'private': 10, 'public': 4, 'unlisted': 10 }
+ }
+ return Promise.resolve({ data })
+}
diff --git a/src/api/status.js b/src/api/status.js
index fcc820e0..e3bb3fd4 100644
--- a/src/api/status.js
+++ b/src/api/status.js
@@ -30,10 +30,10 @@ export async function fetchStatuses({ godmode, localOnly, authHost, token, pageS
})
}
-export async function fetchStatusesCount(authHost, token) {
+export async function fetchStatusesCount(instance, authHost, token) {
return await request({
baseURL: baseName(authHost),
- url: `/api/pleroma/admin/stats`,
+ url: instance ? `/api/pleroma/admin/stats?instance=${instance}` : `/api/pleroma/admin/stats`,
method: 'get',
headers: authHeaders(token)
})
diff --git a/src/store/modules/status.js b/src/store/modules/status.js
index 8847e8bf..74fb6641 100644
--- a/src/store/modules/status.js
+++ b/src/store/modules/status.js
@@ -58,6 +58,14 @@ const status = {
dispatch('FetchStatusesByInstance')
}
},
+ ClearState({ commit }) {
+ commit('CHANGE_SELECTED_INSTANCE', '')
+ commit('SET_STATUSES_BY_INSTANCE', [])
+ commit('CHANGE_LOCAL_CHECKBOX_VALUE', false)
+ commit('CHANGE_GODMODE_CHECKBOX_VALUE', false)
+ commit('SET_ALL_LOADED', false)
+ commit('CHANGE_PAGE', 1)
+ },
async DeleteStatus({ dispatch, getters }, { statusId, reportCurrentPage, userId, godmode, fetchStatusesByInstance }) {
await deleteStatus(statusId, getters.authHost, getters.token)
if (reportCurrentPage !== 0) { // called from Reports
@@ -68,14 +76,15 @@ const status = {
dispatch('FetchStatusesByInstance')
}
},
- async FetchStatusesCount({ commit, getters }) {
+ async FetchStatusesCount({ commit, getters }, instance) {
commit('SET_LOADING', true)
- const { data } = await fetchStatusesCount(getters.authHost, getters.token)
+ const { data } = await fetchStatusesCount(instance, getters.authHost, getters.token)
commit('SET_STATUS_VISIBILITY', data.status_visibility)
commit('SET_LOADING', false)
},
- async FetchStatusesByInstance({ commit, getters, state, rootState }) {
+ async FetchStatusesByInstance({ commit, dispatch, getters, state, rootState }) {
commit('SET_LOADING', true)
+ dispatch('FetchStatusesCount', state.statusesByInstance.selectedInstance)
if (state.statusesByInstance.selectedInstance === '') {
commit('SET_STATUSES_BY_INSTANCE', [])
} else {
diff --git a/src/views/statuses/index.vue b/src/views/statuses/index.vue
index 0d17316f..6b5c3db5 100644
--- a/src/views/statuses/index.vue
+++ b/src/views/statuses/index.vue
@@ -8,10 +8,18 @@
@@ -61,6 +69,7 @@
import MultipleUsersMenu from '@/views/users/components/MultipleUsersMenu'
import Status from '@/components/Status'
import RebootButton from '@/components/RebootButton'
+import numeral from 'numeral'
export default {
name: 'Statuses',
@@ -142,7 +151,14 @@ export default {
this.$store.dispatch('FetchPeers')
this.$store.dispatch('FetchStatusesCount')
},
+ destroyed() {
+ this.clearSelection()
+ this.$store.dispatch('ClearState')
+ },
methods: {
+ clearSelection() {
+ this.selectedUsers = []
+ },
handleFilterChange() {
this.$store.dispatch('HandlePageChange', 1)
this.$store.dispatch('FetchStatusesByInstance')
@@ -152,14 +168,14 @@ export default {
this.$store.dispatch('FetchStatusesPageByInstance')
},
- clearSelection() {
- this.selectedUsers = []
- },
handleStatusSelection(user) {
if (this.selectedUsers.find(selectedUser => user.id === selectedUser.id) !== undefined) {
return
}
this.selectedUsers = [...this.selectedUsers, user]
+ },
+ normalizedCount(count) {
+ return numeral(count).format('0a')
}
}
}
@@ -175,6 +191,13 @@ export default {
margin: 0 0 10px;
}
}
+.statuses-header-container {
+ .el-button.is-plain:focus, .el-button.is-plain:hover {
+ border-color: #DCDFE6;
+ color: #606266;
+ cursor: default
+ }
+}
.checkbox-container {
margin-bottom: 15px;
}
@@ -228,8 +251,26 @@ export default {
.statuses-header-container {
flex-direction: column;
align-items: flex-start;
+ .el-button-group {
+ width: 100%;
+ }
.el-button {
padding: 10px 6.5px;
+ width: 50%;
+ }
+ .el-button-group>.el-button:first-child {
+ border-bottom-left-radius: 0;
+ }
+ .el-button-group>.el-button:not(:first-child):not(:last-child).private-button {
+ border-top-right-radius: 4px;
+ }
+ .el-button-group>.el-button:not(:first-child):not(:last-child).public-button {
+ border-bottom-left-radius: 4px;
+ border-top: white;
+ }
+ .el-button-group>.el-button:last-child {
+ border-top-right-radius: 0;
+ border-top: white;
}
.reboot-button {
margin: 10px 0 0 0;
diff --git a/test/views/statuses/index.test.js b/test/views/statuses/index.test.js
new file mode 100644
index 00000000..e6173883
--- /dev/null
+++ b/test/views/statuses/index.test.js
@@ -0,0 +1,103 @@
+import Vuex from 'vuex'
+import { mount, createLocalVue, config } from '@vue/test-utils'
+import flushPromises from 'flush-promises'
+import Element from 'element-ui'
+import Statuses from '@/views/statuses/index'
+import storeConfig from './store.conf'
+import { cloneDeep } from 'lodash'
+
+config.mocks["$t"] = () => {}
+
+const localVue = createLocalVue()
+localVue.use(Vuex)
+localVue.use(Element)
+
+jest.mock('@/api/app')
+jest.mock('@/api/status')
+jest.mock('@/api/peers')
+jest.mock('@/api/nodeInfo')
+
+describe('Statuses', () => {
+ let store
+
+ beforeEach(() => {
+ store = new Vuex.Store(cloneDeep(storeConfig))
+ })
+
+ it('fetches peers and statuses count', async (done) => {
+ mount(Statuses, {
+ store,
+ localVue
+ })
+
+ await flushPromises()
+ const statusVisibilityCount = store.state.status.statusVisibility
+ expect(statusVisibilityCount.direct).toEqual(4)
+ expect(statusVisibilityCount.private).toEqual(10)
+ expect(statusVisibilityCount.public).toEqual(4)
+ expect(statusVisibilityCount.unlisted).toEqual(10)
+ done()
+ })
+
+ it('fetches statuses from selected instance and updates the count', async (done) => {
+ const wrapper = mount(Statuses, {
+ store,
+ localVue
+ })
+ await flushPromises()
+
+ store.dispatch('HandleFilterChange', 'heaven.com')
+ wrapper.vm.handleFilterChange()
+ await flushPromises()
+ const statusVisibilityCount = store.state.status.statusVisibility
+
+ expect(statusVisibilityCount.direct).toEqual(1)
+ expect(statusVisibilityCount.private).toEqual(2)
+ expect(statusVisibilityCount.public).toEqual(3)
+ expect(statusVisibilityCount.unlisted).toEqual(0)
+ expect(store.state.status.fetchedStatuses.length).toEqual(2)
+ done()
+ })
+
+ it('handles status select', async (done) => {
+ const wrapper = mount(Statuses, {
+ store: store,
+ localVue
+ })
+ await flushPromises()
+
+ store.dispatch('HandleFilterChange', 'heaven.com')
+ wrapper.vm.handleFilterChange()
+ await flushPromises()
+ wrapper.find('.status-checkbox input').setChecked()
+ await flushPromises()
+
+ expect(wrapper.vm.selectedUsers.length).toEqual(1)
+ expect(wrapper.vm.selectedUsers[0].display_name).toBe('sky')
+ done()
+ })
+
+ it('clear state after component was destroyed', async (done) => {
+ const wrapper = mount(Statuses, {
+ store: store,
+ localVue
+ })
+ await flushPromises()
+
+ store.dispatch('HandleFilterChange', 'heaven.com')
+ wrapper.vm.handleFilterChange()
+ await flushPromises()
+ wrapper.find('.status-checkbox input').setChecked()
+ await flushPromises()
+
+ expect(wrapper.vm.selectedUsers.length).toEqual(1)
+ expect(store.state.status.statusesByInstance.selectedInstance).toBe('heaven.com')
+ expect(store.state.status.fetchedStatuses.length).toEqual(2)
+ wrapper.destroy()
+
+ expect(wrapper.vm.selectedUsers.length).toEqual(0)
+ expect(store.state.status.statusesByInstance.selectedInstance).toBe('')
+ expect(store.state.status.fetchedStatuses.length).toEqual(0)
+ done()
+ })
+})
diff --git a/test/views/statuses/pagination.test.js b/test/views/statuses/pagination.test.js
new file mode 100644
index 00000000..2cbfb823
--- /dev/null
+++ b/test/views/statuses/pagination.test.js
@@ -0,0 +1,53 @@
+import Vuex from 'vuex'
+import { mount, createLocalVue, config } from '@vue/test-utils'
+import flushPromises from 'flush-promises'
+import Element from 'element-ui'
+import Statuses from '@/views/statuses/index'
+import storeConfig from './storeForPagination.conf'
+import { cloneDeep } from 'lodash'
+
+config.mocks["$t"] = () => {}
+
+const localVue = createLocalVue()
+localVue.use(Vuex)
+localVue.use(Element)
+
+jest.mock('@/api/app')
+jest.mock('@/api/status')
+jest.mock('@/api/peers')
+jest.mock('@/api/nodeInfo')
+
+describe('Statuses', () => {
+ let store
+
+ beforeEach(() => {
+ store = new Vuex.Store(cloneDeep(storeConfig))
+ })
+
+ it('pagination', async (done) => {
+ const wrapper = mount(Statuses, {
+ store,
+ localVue
+ })
+ await flushPromises()
+
+ store.dispatch('HandleFilterChange', 'heaven.com')
+ wrapper.vm.handleFilterChange()
+ await flushPromises()
+
+ expect(store.state.status.statusesByInstance.allLoaded).toBe(false)
+ expect(store.state.status.statusesByInstance.page).toBe(1)
+ wrapper.find('.statuses-pagination button').trigger('click')
+ await flushPromises()
+
+ expect(store.state.status.statusesByInstance.allLoaded).toBe(false)
+ expect(store.state.status.statusesByInstance.page).toBe(2)
+
+ wrapper.find('.statuses-pagination button').trigger('click')
+ await flushPromises()
+
+ expect(store.state.status.statusesByInstance.allLoaded).toBe(true)
+
+ done()
+ })
+})
diff --git a/test/views/statuses/store.conf.js b/test/views/statuses/store.conf.js
new file mode 100644
index 00000000..6e22b617
--- /dev/null
+++ b/test/views/statuses/store.conf.js
@@ -0,0 +1,17 @@
+import app from '@/store/modules/app'
+import peers from '@/store/modules/peers'
+import user from '@/store/modules/user'
+import settings from '@/store/modules/settings'
+import status from '@/store/modules/status'
+import getters from '@/store/getters'
+
+export default {
+ modules: {
+ app,
+ peers,
+ settings,
+ status,
+ user: { ...user, state: { ...user.state, authHost: 'localhost:4000' }}
+ },
+ getters
+}
diff --git a/test/views/statuses/storeForPagination.conf.js b/test/views/statuses/storeForPagination.conf.js
new file mode 100644
index 00000000..76747f97
--- /dev/null
+++ b/test/views/statuses/storeForPagination.conf.js
@@ -0,0 +1,17 @@
+import app from '@/store/modules/app'
+import peers from '@/store/modules/peers'
+import user from '@/store/modules/user'
+import settings from '@/store/modules/settings'
+import status from '@/store/modules/status'
+import getters from '@/store/getters'
+
+export default {
+ modules: {
+ app,
+ peers,
+ settings,
+ status: { ...status, state: { ...status.state, statusesByInstance: { ...status.state.statusesByInstance, pageSize: 1 }}},
+ user: { ...user, state: { ...user.state, authHost: 'localhost:4000' }}
+ },
+ getters
+}