Skip to content

Commit

Permalink
[ICIJ/datashare#325] Add a "Mark as read" button
Browse files Browse the repository at this point in the history
  • Loading branch information
annelhote committed Mar 23, 2020
1 parent 73b56e5 commit 70da4d2
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 65 deletions.
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ VUE_APP_ES_INDEX=local-datashare
VUE_APP_DS_HOST=http://localhost:8080
VUE_APP_FEATURE_SERVER_RENDERING_SPREADSHEET=true
VUE_APP_FEATURE_DOWNLOAD_ALLOWED=true
VUE_APP_FEATURE_MARK_AS_READ=true
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ VUE_APP_ES_ANOTHER_INDEX=another-index
VUE_APP_ES_LOG=debug
VUE_APP_ES_HOST=http://elasticsearch:9200
VUE_APP_FEATURE_DOWNLOAD_ALLOWED=true
VUE_APP_FEATURE_MARK_AS_READ=true
6 changes: 6 additions & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ export default class Api {
getUser () {
return this.sendAction('/api/users/me')
}
setMarkAsRead (project, docIds) {
return this.sendActionAsText(`/api/${project}/documents/batchUpdate/markRead`, { method: 'POST', data: { docIds } })
}
setMarkAsUnread (project, docIds) {
return this.sendActionAsText(`/api/${project}/documents/batchUpdate/unmarkRead`, { method: 'POST', data: { docIds } })
}
async sendAction (url, config = {}) {
try {
const r = await axios.request({ url: Api.getFullUrl(url), ...config })
Expand Down
2 changes: 1 addition & 1 deletion src/components/FilterText.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
</template>

<script>
import filters from '@/mixins/filters'
import FilterBoilerplate from '@/components/FilterBoilerplate'
import filters from '@/mixins/filters'
export default {
name: 'FilterText',
Expand Down
18 changes: 12 additions & 6 deletions src/components/SearchDocumentNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
<span v-html="nextTooltip"></span>
</b-tooltip>
</span>
<b-btn class="btn-light px-2 py-0 search-document-navbar__readBy" size="sm" @click="toggleAsRead" v-if="hasFeature('MARK_AS_READ')">
{{ markAsReadLabel }}
</b-btn>
<document-actions
:document="currentDocument"
class="search-document-navbar__actions d-flex"
Expand All @@ -39,15 +42,15 @@
</template>

<script>
import { mapState } from 'vuex'
import findIndex from 'lodash/findIndex'
import first from 'lodash/first'
import last from 'lodash/last'
import { getShortkeyOS } from '@/utils/utils'
import shortkeys from '@/mixins/shortkeys'
import { mapState } from 'vuex'
import DocumentActions from '@/components/DocumentActions'
import features from '@/mixins/features'
import shortkeys from '@/mixins/shortkeys'
export default {
name: 'SearchDocumentNavbar',
Expand All @@ -62,10 +65,7 @@ export default {
return this.$store.getters['search/toRouteQuery']()
},
currentDocumentIndex () {
if (this.currentDocument) {
return findIndex(this.response.hits, { id: this.currentDocument.id })
}
return -1
return this.currentDocument ? findIndex(this.response.hits, { id: this.currentDocument.id }) : -1
},
navRequiresPreviousPage () {
return this.isFirstDocument && !this.isFirstPage
Expand Down Expand Up @@ -108,6 +108,9 @@ export default {
},
nextTooltip () {
return getShortkeyOS() === 'mac' ? this.$t('search.nav.next.tooltipMac') : this.$t('search.nav.next.tooltipOthers')
},
markAsReadLabel () {
return this.isRead ? this.$t('search.nav.markAsUnread') : this.$t('search.nav.markAsRead')
}
},
mounted () {
Expand Down Expand Up @@ -143,6 +146,9 @@ export default {
return this.goToDocument(this.firstDocument)
}
return this.goToDocument(this.nextDocument)
},
toggleAsRead () {
this.$store.dispatch('document/toggleAsRead', { documents: [this.currentDocument] })
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@
},
"document": {
"extensionWarning": "This document has the wrong file extension for its type. You might need to add the extension <code>%{extension}</code> before you can open it."
}
},
"markAsRead": "Mark as read",
"markAsUnread": "Mark as unread"
}
},
"pagination": {
Expand Down
14 changes: 13 additions & 1 deletion src/store/modules/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export function initialState () {
},
parentDocument: null,
showNamedEntities: false,
tags: []
tags: [],
isRead: false
}
}

Expand Down Expand Up @@ -101,6 +102,9 @@ export const mutations = {
},
deleteTag (state, tagToDelete) {
state.tags.splice(findIndex(state.tags, { label: tagToDelete.label }), 1)
},
toggleIsRead (state) {
state.isRead = !state.isRead
}
}

Expand Down Expand Up @@ -187,6 +191,14 @@ export const actions = {
async deleteTag ({ state, commit }, { documents, tag }) {
await api.untagDocuments(state.doc.index, map(documents, 'id'), [tag.label])
if (documents.length === 1) commit('deleteTag', tag)
},
async toggleAsRead ({ state, commit }, { documents }) {
if (state.isRead) {
await api.setMarkAsUnread(state.doc.index, map(documents, 'id'))
} else {
await api.setMarkAsRead(state.doc.index, map(documents, 'id'))
}
commit('toggleIsRead')
}
}

Expand Down
10 changes: 10 additions & 0 deletions tests/unit/specs/api/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ describe('Datashare backend client', () => {
expect(json).toEqual({})
})

it('should return backend response to setMarkAsRead', async () => {
json = await api.setMarkAsRead()
expect(json).toEqual({})
})

it('should return backend response to setMarkAsUnread', async () => {
json = await api.setMarkAsUnread()
expect(json).toEqual({})
})

it('should emit an error if the backend response has a bad status', async () => {
const error = new Error('Forbidden')
axios.request.mockReturnValue(Promise.reject(error))
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/specs/components/FilterText.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ describe('FilterText.vue', () => {
it('should display the language filter in French', async () => {
const i18n = new VueI18n({ locale: 'fr', messages: { fr: messagesFr } })
wrapper = mount(FilterText, {
localVue,
i18n,
localVue,
router,
store,
wait,
Expand All @@ -381,8 +381,8 @@ describe('FilterText.vue', () => {
it('should translate any weird language', async () => {
const i18n = new VueI18n({ locale: 'fr', messages: { fr: messagesFr } })
wrapper = mount(FilterText, {
localVue,
i18n,
localVue,
router,
store,
wait,
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/specs/components/SearchDocumentNavbar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ import { createLocalVue, shallowMount } from '@vue/test-utils'
import { Core } from '@/core'
import { getShortkeyOS } from '@/utils/utils'
import SearchDocumentNavbar from '@/components/SearchDocumentNavbar'
import { IndexedDocument, letData } from 'tests/unit/es_utils'
import esConnectionHelper from 'tests/unit/specs/utils/esConnectionHelper'
import axios from 'axios'
import Api from '@/api'

jest.mock('@/utils/utils')

jest.mock('axios', () => {
return {
request: jest.fn().mockResolvedValue({ data: {} })
}
})

const { localVue, store } = Core.init(createLocalVue()).useAll()

describe('SearchDocumentNavbar.vue', () => {
const index = toLower('SearchDocumentNavbar')
esConnectionHelper(index)
const es = esConnectionHelper.es
let wrapper

beforeAll(() => store.commit('search/index', index))
Expand All @@ -36,4 +48,26 @@ describe('SearchDocumentNavbar.vue', () => {

expect(wrapper.vm.previousTooltip).toBe('search.nav.previous.tooltipOthers')
})

describe('Mark as read button', () => {
beforeAll(async () => {
await letData(es).have(new IndexedDocument('doc_01', index)).commit()
await store.dispatch('document/get', { id: 'doc_01', index })
})

it('should display a "Mark as read" button', () => {
expect(wrapper.find('.search-document-navbar__readBy').exists()).toBeTruthy()
})

it('should call batchUpdate api function', async () => {
await wrapper.vm.toggleAsRead()

expect(axios.request).toBeCalledTimes(1)
expect(axios.request).toBeCalledWith(expect.objectContaining({
url: Api.getFullUrl('/api/searchdocumentnavbar/documents/batchUpdate/markRead'),
method: 'POST',
data: { docIds: ['doc_01'] }
}))
})
})
})
Loading

0 comments on commit 70da4d2

Please sign in to comment.