Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Implement delete all option for admin
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Eng committed May 31, 2016
1 parent 0f669b1 commit 6142303
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 33 deletions.
39 changes: 37 additions & 2 deletions frontend/src/main/web/src/actions/glossary.js
Expand Up @@ -45,9 +45,14 @@ export const GLOSSARY_TOGGLE_IMPORT_DISPLAY = 'GLOSSARY_TOGGLE_IMPORT_DISPLAY'
export const GLOSSARY_UPDATE_SORT = 'GLOSSARY_UPDATE_SORT'
export const GLOSSARY_TOGGLE_NEW_ENTRY_DISPLAY =
'GLOSSARY_TOGGLE_NEW_ENTRY_DISPLAY'
export const GLOSSARY_TOGGLE_DELETE_ALL_ENTRY_DISPLAY =
'GLOSSARY_TOGGLE_DELETE_ALL_ENTRY_DISPLAY'
export const GLOSSARY_CREATE_REQUEST = 'GLOSSARY_CREATE_REQUEST'
export const GLOSSARY_CREATE_SUCCESS = 'GLOSSARY_CREATE_SUCCESS'
export const GLOSSARY_CREATE_FAILURE = 'GLOSSARY_CREATE_FAILURE'
export const GLOSSARY_DELETE_ALL_REQUEST = 'GLOSSARY_DELETE_ALL_REQUEST'
export const GLOSSARY_DELETE_ALL_SUCCESS = 'GLOSSARY_DELETE_ALL_SUCCESS'
export const GLOSSARY_DELETE_ALL_FAILURE = 'GLOSSARY_DELETE_ALL_FAILURE'

export const glossaryUpdateIndex = createAction(GLOSSARY_UPDATE_INDEX)
export const glossaryUpdateLocale = createAction(GLOSSARY_UPDATE_LOCALE)
Expand All @@ -64,6 +69,8 @@ export const glossaryUpdateImportFileLocale =
export const glossaryUpdateSort = createAction(GLOSSARY_UPDATE_SORT)
export const glossaryToggleNewEntryModal =
createAction(GLOSSARY_TOGGLE_NEW_ENTRY_DISPLAY)
export const glossaryToggleDeleteAllEntryModal =
createAction(GLOSSARY_TOGGLE_DELETE_ALL_ENTRY_DISPLAY)

const getPageNumber =
(index) => Math.floor(index / GLOSSARY_PAGE_SIZE) + 1
Expand Down Expand Up @@ -152,7 +159,6 @@ const importGlossaryFile = (dispatch, data, srcLocaleId) => {
formData.append('transLocale', data.transLocale.value)
}


const apiTypes = [
GLOSSARY_UPLOAD_REQUEST,
{
Expand All @@ -167,7 +173,8 @@ const importGlossaryFile = (dispatch, data, srcLocaleId) => {
GLOSSARY_UPLOAD_FAILURE
]
return {
[CALL_API]: buildAPIRequest(endpoint, 'POST', getJsonHeaders(), apiTypes, formData)
[CALL_API]: buildAPIRequest(endpoint, 'POST',
getJsonHeaders(), apiTypes, formData)
}
}

Expand Down Expand Up @@ -257,6 +264,28 @@ const deleteGlossaryTerm = (dispatch, id) => {
}
}

const deleteAllGlossaryEntry = (dispatch) => {
const endpoint = window.config.baseUrl + window.config.apiRoot + '/glossary'
const apiTypes = [
{
type: GLOSSARY_DELETE_ALL_REQUEST,
payload: (action, state) => {
return ''
}
},
{
type: GLOSSARY_DELETE_ALL_SUCCESS,
payload: (action, state, res) => {
return dispatch(getGlossaryStats(dispatch, true))
}
},
GLOSSARY_DELETE_ALL_FAILURE
]
return {
[CALL_API]: buildAPIRequest(endpoint, 'DELETE', getJsonHeaders(), apiTypes)
}
}

const shouldFetchTerms = (state, newIndex) => {
const {
pagesLoaded,
Expand Down Expand Up @@ -325,6 +354,12 @@ export const glossaryDeleteTerm = (id) => {
}
}

export const glossaryDeleteAll = () => {
return (dispatch, getState) => {
dispatch(deleteAllGlossaryEntry(dispatch))
}
}

export const glossaryUpdateTerm = (term, needRefresh) => {
return (dispatch, getState) => {
// do cloning to prevent changes in selectedTerm
Expand Down
@@ -0,0 +1,72 @@
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import {
ButtonLink,
ButtonRound,
LoaderText,
Icon,
Tooltip,
Overlay
} from '../../components'

/**
* Confirmation modal dialog for delete all glossary entries
*/
class DeleteAllEntryModal extends Component {
render () {
const {
show,
isDeleting,
handleDeleteAllEntryDisplay,
handleDeleteAllEntry
} = this.props

return (
<div className='Mstart(rq) D(ib)'>
<Overlay
placement='bottom'
target={() => ReactDOM.findDOMNode(this)}
rootClose
show={show}
onHide={() => handleDeleteAllEntryDisplay(false)}>
<Tooltip id='delete-entries' title='Delete all glossary entry'>
<p>
Are you sure you want to delete&nbsp;
<strong>all entries</strong>&nbsp;?
</p>
<div className='Mt(rq)'>
<ButtonLink
atomic={{m: 'Mend(rh)'}}
onClick={() => handleDeleteAllEntryDisplay(false)}>
Cancel
</ButtonLink>
<ButtonRound type='danger' size='n1'
disabled={isDeleting}
onClick={() => handleDeleteAllEntry()}>
<LoaderText loading={isDeleting} size='n1'
loadingText='Deleting'>
Delete all
</LoaderText>
</ButtonRound>
</div>
</Tooltip>
</Overlay>
<ButtonLink type='danger'
onClick={() => handleDeleteAllEntryDisplay(true)}
disabled={isDeleting}>
<Icon name='trash' atomic={{m: 'Mend(re)'}} />
<span className='Hidden--lesm'>Delete all</span>
</ButtonLink>
</div>
)
}
}

DeleteAllEntryModal.propTypes = {
show: React.PropTypes.bool,
isDeleting: React.PropTypes.bool,
handleDeleteAllEntryDisplay: PropTypes.func.isRequired,
handleDeleteAllEntry: React.PropTypes.func.isRequired
}

export default DeleteAllEntryModal
Expand Up @@ -25,6 +25,7 @@ class DeleteEntryModal extends Component {
show,
isDeleting,
handleDeleteEntryDisplay,
handleDeleteEntry
} = this.props
const info = entry.termsCount > 0 ? (
<p>
Expand Down Expand Up @@ -52,7 +53,7 @@ class DeleteEntryModal extends Component {
</ButtonLink>
<ButtonRound type='danger' size='n1'
disabled={isDeleting}
onClick={() => this.handleDeleteEntry(entry.id)}>
onClick={() => handleDeleteEntry(entry.id)}>
<LoaderText loading={isDeleting} size='n1'
loadingText='Deleting'>
Delete all
Expand All @@ -79,7 +80,7 @@ DeleteEntryModal.propTypes = {
entry: React.PropTypes.object,
show: React.PropTypes.bool,
isDeleting: React.PropTypes.bool,
handleDeleteEntryDisplay: PropTypes.func,
handleDeleteEntryDisplay: PropTypes.func.isRequired,
handleDeleteEntry: React.PropTypes.func.isRequired
}

Expand Down
71 changes: 44 additions & 27 deletions frontend/src/main/web/src/containers/Glossary/ViewHeader.js
Expand Up @@ -17,16 +17,18 @@ import {
glossaryFilterTextChanged,
glossarySortColumn,
glossaryToggleImportFileDisplay,
glossaryToggleNewEntryModal
glossaryToggleNewEntryModal,
glossaryToggleDeleteAllEntryModal,
glossaryDeleteAll
} from '../../actions/glossary'
import ImportModal from './ImportModal'
import NewEntryModal from './NewEntryModal'
import DeleteAllEntryModal from './DeleteAllEntryModal'

/**
* Header for glossary page
*/
class ViewHeader extends Component {

currentLocaleCount () {
if (this.props.filterText && this.props.results) {
return this.props.results
Expand Down Expand Up @@ -71,14 +73,18 @@ class ViewHeader extends Component {
handleFilterFieldUpdate,
handleImportFileDisplay,
handleNewEntryDisplay,
handleDeleteAllEntryDisplay,
handleDeleteAllEntry,
handleSortColumn,
permission,
sort
sort,
deleteAll
} = this.props
const currentLocaleCount = this.currentLocaleCount()
const isReadOnly = !(permission.canAddNewEntry || permission.canUpdateEntry || permission.canDeleteEntry)
const icon = isReadOnly ? 'locked' : undefined
const tooltip = isReadOnly ? 'read-only' : undefined
const showDeleteAll = permission.canDeleteEntry && termCount > 0
return (
<Header title='Glossary' icon={icon} tooltip={tooltip}
extraElements={(
Expand All @@ -95,36 +101,42 @@ class ViewHeader extends Component {
title='Cancel search'
disabled={isEmpty(filterText)}
onClick={(e) => { this.handleClearSearch() }}>
<Icon name='cross'/>
<Icon name='cross' />
</ButtonLink>

{permission.canAddNewEntry ? (
{permission.canAddNewEntry && (
<div className='Mstart(rq)'>
<ButtonLink type='default'
onClick={() => handleImportFileDisplay(true)}
atomic={{m: 'Mstart(rh)'}}>
atomic={{m: 'Mstart(rq)'}}>
<Row>
<Icon name='import'
atomic={{m: 'Mend(rq)'}}/>
<Icon name='import' atomic={{m: 'Mend(re)'}} />
<span className='Hidden--lesm'>Import Glossary</span>
</Row>
</ButtonLink>
<ImportModal/>
</div>) : ''}
<ImportModal />
</div>)}

{permission.canAddNewEntry && (
<div className='Mstart(rq)'>
<ButtonLink atomic={{m: 'Mstart(rq)'}}
onClick={() => handleNewEntryDisplay(true)}>
<Row>
<Icon name='plus' atomic={{m: 'Mend(re)'}} />
<span className='Hidden--lesm'>New Term</span>
</Row>
</ButtonLink>
<NewEntryModal />
</div>)}

{permission.canAddNewEntry ? (
{showDeleteAll && (
<div className='Mstart(rq)'>
<ButtonLink atomic={{m: 'Mstart(rh)'}}
onClick={() => handleNewEntryDisplay(true)}>
<Row>
<Icon name='plus'
atomic={{m: 'Mend(rq)'}}/>
<span className='Hidden--lesm'>New Term</span>
</Row>
</ButtonLink>
<NewEntryModal/>
</div>) : ''
}
<DeleteAllEntryModal show={deleteAll.show}
isDeleting={deleteAll.isDeleting}
handleDeleteAllEntryDisplay={(display) =>
handleDeleteAllEntryDisplay(display)}
handleDeleteAllEntry={handleDeleteAllEntry} />
</div>)}
</View>
)}>
<View theme={{
Expand All @@ -142,8 +154,8 @@ class ViewHeader extends Component {
<Row>
{'src_content' in sort
? (sort.src_content === true)
? <Icon name='chevron-down'/>
: <Icon name='chevron-up'/>
? <Icon name='chevron-down' />
: <Icon name='chevron-up' />
: ''}
<Icon name='glossary'
atomic={{c: 'C(neutral)', m: 'Mend(re) MStart(rq)'}} />
Expand Down Expand Up @@ -232,7 +244,8 @@ const mapStateToProps = (state) => {
termCount,
filter,
permission,
sort
sort,
deleteAll
} = state.glossary
const query = state.routing.location.query
return {
Expand All @@ -242,7 +255,8 @@ const mapStateToProps = (state) => {
filterText: filter,
selectedTransLocale: query.locale,
permission,
sort
sort,
deleteAll
}
}

Expand All @@ -265,7 +279,10 @@ const mapDispatchToProps = (dispatch) => {
handleImportFileDisplay: (display) =>
dispatch(glossaryToggleImportFileDisplay(display)),
handleNewEntryDisplay: (display) =>
dispatch(glossaryToggleNewEntryModal(display))
dispatch(glossaryToggleNewEntryModal(display)),
handleDeleteAllEntryDisplay: (display) =>
dispatch(glossaryToggleDeleteAllEntryModal(display)),
handleDeleteAllEntry: () => dispatch(glossaryDeleteAll())
}
}

Expand Down

0 comments on commit 6142303

Please sign in to comment.