Merge branch 'feature/show-open-reports-count' into 'develop'

Show open reports count in Sidebar Menu

Closes #128

See merge request pleroma/admin-fe!143
This commit is contained in:
Angelina Filippova 2020-07-14 16:40:10 +00:00
commit 702d989c08
7 changed files with 70 additions and 31 deletions

View file

@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add MRF Activity Expiration setting - Add MRF Activity Expiration setting
- Add ability to disable multi-factor authentication for a user - Add ability to disable multi-factor authentication for a user
- Ability to configure S3 settings on Upload tab - Ability to configure S3 settings on Upload tab
- Show number of open reports in Sidebar Menu
### Changed ### Changed

View file

@ -2,12 +2,13 @@ import { changeState, fetchReports, createNote, deleteNote } from '@/api/reports
const reports = { const reports = {
state: { state: {
fetchedReports: [],
totalReportsCount: 0,
currentPage: 1, currentPage: 1,
fetchedReports: [],
loading: true,
openReportsCount: 0,
pageSize: 50, pageSize: 50,
stateFilter: '', stateFilter: '',
loading: true totalReportsCount: 0
}, },
mutations: { mutations: {
SET_LAST_REPORT_ID: (state, id) => { SET_LAST_REPORT_ID: (state, id) => {
@ -16,6 +17,9 @@ const reports = {
SET_LOADING: (state, status) => { SET_LOADING: (state, status) => {
state.loading = status state.loading = status
}, },
SET_OPEN_REPORTS_COUNT: (state, total) => {
state.openReportsCount = total
},
SET_PAGE: (state, page) => { SET_PAGE: (state, page) => {
state.currentPage = page state.currentPage = page
}, },
@ -30,7 +34,7 @@ const reports = {
} }
}, },
actions: { actions: {
async ChangeReportState({ commit, getters, state }, reportsData) { async ChangeReportState({ commit, dispatch, getters, state }, reportsData) {
changeState(reportsData, getters.authHost, getters.token) changeState(reportsData, getters.authHost, getters.token)
const updatedReports = state.fetchedReports.map(report => { const updatedReports = state.fetchedReports.map(report => {
@ -39,6 +43,7 @@ const reports = {
}) })
commit('SET_REPORTS', updatedReports) commit('SET_REPORTS', updatedReports)
dispatch('FetchOpenReportsCount')
}, },
ClearFetchedReports({ commit }) { ClearFetchedReports({ commit }) {
commit('SET_REPORTS', []) commit('SET_REPORTS', [])
@ -52,7 +57,14 @@ const reports = {
commit('SET_PAGE', page) commit('SET_PAGE', page)
commit('SET_LOADING', false) commit('SET_LOADING', false)
}, },
SetFilter({ commit }, filter) { async FetchOpenReportsCount({ commit, getters, state }) {
commit('SET_LOADING', true)
const { data } = await fetchReports('open', state.currentPage, state.pageSize, getters.authHost, getters.token)
commit('SET_OPEN_REPORTS_COUNT', data.total)
commit('SET_LOADING', false)
},
SetReportsFilter({ commit }, filter) {
commit('SET_REPORTS_FILTER', filter) commit('SET_REPORTS_FILTER', filter)
}, },
CreateReportNote({ commit, getters, state, rootState }, { content, reportID }) { CreateReportNote({ commit, getters, state, rootState }, { content, reportID }) {

View file

@ -1,8 +1,19 @@
<template>
<span>
<svg-icon :icon-class="icon"/>
<span slot="title">{{ title }}</span>
<el-badge :value="count" type="primary" class="count-badge" />
</span>
</template>
<script> <script>
export default { export default {
name: 'MenuItem', name: 'Item',
functional: true,
props: { props: {
count: {
type: String,
default: null
},
icon: { icon: {
type: String, type: String,
default: '' default: ''
@ -11,19 +22,13 @@ export default {
type: String, type: String,
default: '' default: ''
} }
},
render(h, context) {
const { icon, title } = context.props
const vnodes = []
if (icon) {
vnodes.push(<svg-icon icon-class={icon}/>)
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
}
return vnodes
} }
} }
</script> </script>
<style rel='stylesheet/scss' lang='scss' scoped>
.count-badge {
margin-left: 5px;
height: 48px;
}
</style>

View file

@ -4,14 +4,21 @@
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link :to="resolvePath(onlyOneChild.path)"> <app-link :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="generateTitle(onlyOneChild.meta.title)" /> <item
v-if="onlyOneChild.meta"
:count="showCount(item) ? normalizedReportsCount : null"
:icon="onlyOneChild.meta.icon||item.meta.icon"
:title="generateTitle(onlyOneChild.meta.title)" />
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)"> <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)">
<template slot="title"> <template slot="title">
<item v-if="item.meta" :icon="item.meta.icon" :title="generateTitle(item.meta.title)" /> <item
v-if="item.meta"
:count="showCount(item) ? normalizedReportsCount : null"
:icon="item.meta.icon"
:title="generateTitle(item.meta.title)" />
</template> </template>
<template v-for="child in item.children"> <template v-for="child in item.children">
@ -26,7 +33,11 @@
<app-link v-else :to="resolvePath(child.path)" :key="child.name"> <app-link v-else :to="resolvePath(child.path)" :key="child.name">
<el-menu-item :index="resolvePath(child.path)"> <el-menu-item :index="resolvePath(child.path)">
<item v-if="child.meta" :icon="child.meta.icon" :title="generateTitle(child.meta.title)" /> <item
v-if="child.meta"
:count="showCount(item) ? normalizedReportsCount : null"
:icon="child.meta.icon"
:title="generateTitle(child.meta.title)" />
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
@ -43,6 +54,7 @@ import { isExternal } from '@/utils'
import Item from './Item' import Item from './Item'
import AppLink from './Link' import AppLink from './Link'
import FixiOSBug from './FixiOSBug' import FixiOSBug from './FixiOSBug'
import numeral from 'numeral'
export default { export default {
name: 'SidebarItem', name: 'SidebarItem',
@ -71,6 +83,9 @@ export default {
computed: { computed: {
invitesEnabled() { invitesEnabled() {
return this.basePath === '/invites' ? this.$store.state.app.invitesEnabled : true return this.basePath === '/invites' ? this.$store.state.app.invitesEnabled : true
},
normalizedReportsCount() {
return numeral(this.$store.state.reports.openReportsCount).format('0a')
} }
}, },
methods: { methods: {
@ -104,6 +119,9 @@ export default {
} }
return path.resolve(this.basePath, routePath) return path.resolve(this.basePath, routePath)
}, },
showCount(item) {
return item.path === '/reports'
},
isExternalLink(routePath) { isExternalLink(routePath) {
return isExternal(routePath) return isExternal(routePath)
}, },

View file

@ -31,6 +31,9 @@ export default {
isCollapse() { isCollapse() {
return !this.sidebar.opened return !this.sidebar.opened
} }
},
mounted() {
this.$store.dispatch('FetchOpenReportsCount')
} }
} }
</script> </script>

View file

@ -38,11 +38,11 @@ export default {
} }
}, },
created() { created() {
this.$store.dispatch('SetFilter', this.$data.filter) this.$store.dispatch('SetReportsFilter', this.$data.filter)
}, },
methods: { methods: {
toggleFilters() { toggleFilters() {
this.$store.dispatch('SetFilter', this.$data.filter) this.$store.dispatch('SetReportsFilter', this.$data.filter)
this.$store.dispatch('ClearFetchedReports') this.$store.dispatch('ClearFetchedReports')
this.$store.dispatch('FetchReports', 1) this.$store.dispatch('FetchReports', 1)
} }

View file

@ -26,7 +26,7 @@ describe('Reports filter', () => {
it('shows open reports when "Open" filter is applied', async (done) => { it('shows open reports when "Open" filter is applied', async (done) => {
expect(store.state.reports.fetchedReports.length).toEqual(7) expect(store.state.reports.fetchedReports.length).toEqual(7)
store.dispatch('SetFilter', 'open') store.dispatch('SetReportsFilter', 'open')
store.dispatch('ClearFetchedReports') store.dispatch('ClearFetchedReports')
store.dispatch('FetchReports', 1) store.dispatch('FetchReports', 1)
await flushPromises() await flushPromises()
@ -38,7 +38,7 @@ describe('Reports filter', () => {
it('shows resolved reports when "Resolved" filter is applied', async (done) => { it('shows resolved reports when "Resolved" filter is applied', async (done) => {
expect(store.state.reports.fetchedReports.length).toEqual(7) expect(store.state.reports.fetchedReports.length).toEqual(7)
store.dispatch('SetFilter', 'resolved') store.dispatch('SetReportsFilter', 'resolved')
store.dispatch('ClearFetchedReports') store.dispatch('ClearFetchedReports')
store.dispatch('FetchReports') store.dispatch('FetchReports')
await flushPromises() await flushPromises()
@ -50,7 +50,7 @@ describe('Reports filter', () => {
it('shows closed reports when "Closed" filter is applied', async (done) => { it('shows closed reports when "Closed" filter is applied', async (done) => {
expect(store.state.reports.fetchedReports.length).toEqual(7) expect(store.state.reports.fetchedReports.length).toEqual(7)
store.dispatch('SetFilter', 'closed') store.dispatch('SetReportsFilter', 'closed')
store.dispatch('ClearFetchedReports') store.dispatch('ClearFetchedReports')
store.dispatch('FetchReports') store.dispatch('FetchReports')
await flushPromises() await flushPromises()
@ -62,13 +62,13 @@ describe('Reports filter', () => {
it('shows all users after removing filters', async (done) => { it('shows all users after removing filters', async (done) => {
expect(store.state.reports.fetchedReports.length).toEqual(7) expect(store.state.reports.fetchedReports.length).toEqual(7)
store.dispatch('SetFilter', 'open') store.dispatch('SetReportsFilter', 'open')
store.dispatch('ClearFetchedReports') store.dispatch('ClearFetchedReports')
store.dispatch('FetchReports') store.dispatch('FetchReports')
await flushPromises() await flushPromises()
expect(store.state.reports.fetchedReports.length).toEqual(2) expect(store.state.reports.fetchedReports.length).toEqual(2)
store.dispatch('SetFilter', '') store.dispatch('SetReportsFilter', '')
store.dispatch('ClearFetchedReports') store.dispatch('ClearFetchedReports')
store.dispatch('FetchReports') store.dispatch('FetchReports')
await flushPromises() await flushPromises()