Add batch delete
This commit is contained in:
parent
7ceec6e7d0
commit
56590ba57a
5 changed files with 92 additions and 5 deletions
32
functions/todos-delete-batch.js
Normal file
32
functions/todos-delete-batch.js
Normal file
|
|
@ -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
src/App.js
44
src/App.js
|
|
@ -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) => {
|
closeModal = (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
showMenu: false
|
showMenu: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
openModal = () => {
|
openModal = () => {
|
||||||
console.log('settings')
|
|
||||||
this.setState({
|
this.setState({
|
||||||
showMenu: true
|
showMenu: true
|
||||||
})
|
})
|
||||||
|
|
@ -254,7 +290,11 @@ export default class App extends Component {
|
||||||
|
|
||||||
{this.renderTodos()}
|
{this.renderTodos()}
|
||||||
</div>
|
</div>
|
||||||
<SettingsMenu showMenu={this.state.showMenu} handleModalClose={this.closeModal} />
|
<SettingsMenu
|
||||||
|
showMenu={this.state.showMenu}
|
||||||
|
handleModalClose={this.closeModal}
|
||||||
|
handleClearCompleted={this.clearCompleted}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import styles from './SettingIcon.css' // eslint-disable-line
|
||||||
const SettingIcon = (props) => {
|
const SettingIcon = (props) => {
|
||||||
const className = props.className || ''
|
const className = props.className || ''
|
||||||
return (
|
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">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 125" className="settings-toggle">
|
||||||
<use xlinkHref="#settings" className="settings-gear"></use>
|
<use xlinkHref="#settings" className="settings-gear"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export default class Menu extends Component {
|
||||||
const deleteConfirm = window.confirm("Are you sure you want to clear all completed todos?");
|
const deleteConfirm = window.confirm("Are you sure you want to clear all completed todos?");
|
||||||
if (deleteConfirm) {
|
if (deleteConfirm) {
|
||||||
console.log('delete')
|
console.log('delete')
|
||||||
|
this.props.handleClearCompleted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -28,7 +29,9 @@ export default class Menu extends Component {
|
||||||
return (
|
return (
|
||||||
<div className='settings-wrapper' style={{display: showOrHide}}>
|
<div className='settings-wrapper' style={{display: showOrHide}}>
|
||||||
<div className='settings-content'>
|
<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>
|
<h2>Settings</h2>
|
||||||
<div className='settings-section' onClick={this.handleDelete}>
|
<div className='settings-section' onClick={this.handleDelete}>
|
||||||
<button className='btn-danger'>
|
<button className='btn-danger'>
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
export default {
|
||||||
create: create,
|
create: create,
|
||||||
readAll: readAll,
|
readAll: readAll,
|
||||||
update: update,
|
update: update,
|
||||||
delete: deleteTodo
|
delete: deleteTodo,
|
||||||
|
batchDelete: batchDeleteTodo
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue