Skip to content

Commit

Permalink
Add batch delete
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidWells committed Jun 21, 2018
1 parent 7ceec6e commit 56590ba
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
32 changes: 32 additions & 0 deletions functions/todos-delete-batch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import faunadb from 'faunadb'
import getId from './utils/getId'

const q = faunadb.query
const client = new faunadb.Client({
secret: process.env.FAUNADB_SECRET
})

exports.handler = (event, context, callback) => {
const data = JSON.parse(event.body)
console.log('data', data)
console.log("Function `todo-delete-batch` invoked", data.ids)
// construct batch query from IDs
const deleteAllCompletedTodoQuery = data.ids.map((id) => {
return q.Delete(q.Ref(`classes/todos/${id}`))
})
// Hit fauna with the query to delete the completed items
return client.query(deleteAllCompletedTodoQuery)
.then((response) => {
console.log("success", response)
return callback(null, {
statusCode: 200,
body: JSON.stringify(response)
})
}).catch((error) => {
console.log("error", error)
return callback(null, {
statusCode: 400,
body: JSON.stringify(error)
})
})
}
44 changes: 42 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,49 @@ export default class App extends Component {
})
}
}
clearCompleted = () => {
const { todos } = this.state

// Optimistically remove todos from UI
const data = todos.reduce((acc, current) => {
if (current.data.completed) {
// save item being removed for rollback
acc.completedTodoIds = acc.completedTodoIds.concat(getTodoId(current))
return acc
}
// filter deleted todo out of the todos list
acc.optimisticState = acc.optimisticState.concat(current)
return acc
}, {
completedTodoIds: [],
optimisticState: []
})

// only set state if completed todos exist
if (!data.completedTodoIds.length) {
alert('Please check off some todos to batch remove them')
this.closeModal()
return false
}

this.setState({
todos: data.optimisticState
}, () => {
api.batchDelete(data.completedTodoIds).then(() => {
console.log(`Batch removal complete`, data.completedTodoIds)
this.closeModal()
}).catch((e) => {
console.log('An API error occurred', e)
})
})

}
closeModal = (e) => {
this.setState({
showMenu: false
})
}
openModal = () => {
console.log('settings')
this.setState({
showMenu: true
})
Expand Down Expand Up @@ -254,7 +290,11 @@ export default class App extends Component {

{this.renderTodos()}
</div>
<SettingsMenu showMenu={this.state.showMenu} handleModalClose={this.closeModal} />
<SettingsMenu
showMenu={this.state.showMenu}
handleModalClose={this.closeModal}
handleClearCompleted={this.clearCompleted}
/>
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/SettingsIcon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styles from './SettingIcon.css' // eslint-disable-line
const SettingIcon = (props) => {
const className = props.className || ''
return (
<span onClick={props.onClick} class={`setting-toggle-wrapper ${className}`}>
<span onClick={props.onClick} className={`setting-toggle-wrapper ${className}`}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125" className="settings-toggle">
<use xlinkHref="#settings" className="settings-gear"></use>
</svg>
Expand Down
5 changes: 4 additions & 1 deletion src/components/SettingsMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default class Menu extends Component {
const deleteConfirm = window.confirm("Are you sure you want to clear all completed todos?");
if (deleteConfirm) {
console.log('delete')
this.props.handleClearCompleted()
}
}
render() {
Expand All @@ -28,7 +29,9 @@ export default class Menu extends Component {
return (
<div className='settings-wrapper' style={{display: showOrHide}}>
<div className='settings-content'>
<span className='settings-close' onClick={this.props.handleModalClose}></span>
<span className='settings-close' onClick={this.props.handleModalClose} role="img" aria-label='close'>
</span>
<h2>Settings</h2>
<div className='settings-section' onClick={this.handleDelete}>
<button className='btn-danger'>
Expand Down
14 changes: 13 additions & 1 deletion src/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,21 @@ const deleteTodo = (todoId) => {
})
}

const batchDeleteTodo = (todoIds) => {
return fetch(`/.netlify/functions/todos-delete-batch`, {
body: JSON.stringify({
ids: todoIds
}),
method: 'POST'
}).then(response => {
return response.json()
})
}

export default {
create: create,
readAll: readAll,
update: update,
delete: deleteTodo
delete: deleteTodo,
batchDelete: batchDeleteTodo
}

0 comments on commit 56590ba

Please sign in to comment.