list editing, deleting
This commit is contained in:
parent
3bb07e7d47
commit
9a53cfbaa6
@ -1,34 +1,20 @@
|
||||
[resolvers.createTask]
|
||||
operation_name = "createTask"
|
||||
[resolvers.getUser]
|
||||
operation_name = "getUser"
|
||||
|
||||
[resolvers.createTask.resolver]
|
||||
command_type = "SQLInsert"
|
||||
[resolvers.getUser.resolver]
|
||||
command_type = "SQLSelect"
|
||||
|
||||
[resolvers.createTask.resolver.command]
|
||||
table = "Task"
|
||||
[resolvers.getUser.resolver.command]
|
||||
table = "User"
|
||||
columns = []
|
||||
where_clauses = []
|
||||
modify_values = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "title"
|
||||
value = "'$title'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "description"
|
||||
value = "'$description'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "completed"
|
||||
value = "$completed"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "list_id"
|
||||
value = "'$list.$id'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "user_username"
|
||||
value = "'$user.$username'"
|
||||
[[resolvers.getUser.resolver.command.where_clauses]]
|
||||
table = "User"
|
||||
column = "username"
|
||||
condition_str = "= '$username'"
|
||||
index = ""
|
||||
|
||||
[resolvers.updateTask]
|
||||
operation_name = "updateTask"
|
||||
@ -63,38 +49,20 @@ column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers.getUser]
|
||||
operation_name = "getUser"
|
||||
[resolvers.deleteList]
|
||||
operation_name = "deleteList"
|
||||
|
||||
[resolvers.getUser.resolver]
|
||||
command_type = "SQLSelect"
|
||||
|
||||
[resolvers.getUser.resolver.command]
|
||||
table = "User"
|
||||
columns = []
|
||||
modify_values = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.getUser.resolver.command.where_clauses]]
|
||||
table = "User"
|
||||
column = "username"
|
||||
condition_str = "= '$username'"
|
||||
index = ""
|
||||
|
||||
[resolvers.deleteTask]
|
||||
operation_name = "deleteTask"
|
||||
|
||||
[resolvers.deleteTask.resolver]
|
||||
[resolvers.deleteList.resolver]
|
||||
command_type = "SQLDelete"
|
||||
|
||||
[resolvers.deleteTask.resolver.command]
|
||||
table = "Task"
|
||||
[resolvers.deleteList.resolver.command]
|
||||
table = "List"
|
||||
columns = []
|
||||
modify_values = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.deleteTask.resolver.command.where_clauses]]
|
||||
table = "Task"
|
||||
[[resolvers.deleteList.resolver.command.where_clauses]]
|
||||
table = "List"
|
||||
column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
@ -119,6 +87,77 @@ value = "'$username'"
|
||||
column = "name"
|
||||
value = "'$name'"
|
||||
|
||||
[resolvers.deleteTask]
|
||||
operation_name = "deleteTask"
|
||||
|
||||
[resolvers.deleteTask.resolver]
|
||||
command_type = "SQLDelete"
|
||||
|
||||
[resolvers.deleteTask.resolver.command]
|
||||
table = "Task"
|
||||
columns = []
|
||||
modify_values = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.deleteTask.resolver.command.where_clauses]]
|
||||
table = "Task"
|
||||
column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers.createTask]
|
||||
operation_name = "createTask"
|
||||
|
||||
[resolvers.createTask.resolver]
|
||||
command_type = "SQLInsert"
|
||||
|
||||
[resolvers.createTask.resolver.command]
|
||||
table = "Task"
|
||||
columns = []
|
||||
where_clauses = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "title"
|
||||
value = "'$title'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "description"
|
||||
value = "'$description'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "completed"
|
||||
value = "$completed"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "list_id"
|
||||
value = "'$list.$id'"
|
||||
|
||||
[[resolvers.createTask.resolver.command.modify_values]]
|
||||
column = "user_username"
|
||||
value = "'$user.$username'"
|
||||
|
||||
[resolvers.updateList]
|
||||
operation_name = "updateList"
|
||||
|
||||
[resolvers.updateList.resolver]
|
||||
command_type = "SQLUpdate"
|
||||
|
||||
[resolvers.updateList.resolver.command]
|
||||
table = "List"
|
||||
columns = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.updateList.resolver.command.modify_values]]
|
||||
column = "title"
|
||||
value = "'$title'"
|
||||
|
||||
[[resolvers.updateList.resolver.command.where_clauses]]
|
||||
table = "List"
|
||||
column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers.createList]
|
||||
operation_name = "createList"
|
||||
|
||||
|
@ -54,6 +54,13 @@ type Mutation {
|
||||
user: User! # username needs to be specified as it's non-nullable
|
||||
): List @bb_resolver(_type: insert, _object: List, _fields: { title: "$title", user: "$user" })
|
||||
|
||||
updateList(
|
||||
id: ID!,
|
||||
title: String!
|
||||
): List @bb_resolver(_type: update, _object: List, _filter: { id: { _eq: "$id" } }, _fields: { title: "$title" })
|
||||
|
||||
deleteList(id: ID!): List @bb_resolver(_type: delete, _object: List, _filter: { id: { _eq: "$id" } })
|
||||
|
||||
createTask(
|
||||
title: String!,
|
||||
description: String,
|
||||
|
25
src/App.vue
25
src/App.vue
@ -1,8 +1,8 @@
|
||||
<script setup>
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import HelloWorld from './components/Welcome.vue'
|
||||
import { store } from './store.js'
|
||||
import {clearSession} from "./store.js";
|
||||
import {Modal} from "bootstrap";
|
||||
|
||||
/**
|
||||
* Logout the user.
|
||||
@ -36,11 +36,14 @@ function dismissError() {
|
||||
<div v-if="store.session.token" class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<RouterLink to="/about" class="nav-link" active-class="active">About</RouterLink>
|
||||
<RouterLink to="/" class="nav-link" active-class="active">Tasks</RouterLink>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<RouterLink to="/lists" class="nav-link" active-class="active">Lists</RouterLink>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<RouterLink to="/about" class="nav-link" active-class="active">About</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="navbar-text">Hello, {{ store.session.username }}!</li>
|
||||
@ -60,6 +63,24 @@ function dismissError() {
|
||||
<button type="button" class="btn-close" @click="dismissError()" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<!-- message modal -->
|
||||
<div class="modal" tabindex="-1" id="msgbox">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Modal title</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Modal body text goes here.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RouterView />
|
||||
</main>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
</h1>
|
||||
|
||||
<div class="toolbar">
|
||||
<button type="button" @click="addItem()" class="btn btn-primary btn-large">New List</button>
|
||||
<button type="button" @click="addList()" class="btn btn-primary btn-large">New List</button>
|
||||
<div class="ms-auto">
|
||||
<small>{{ gStore.lists.length }} lists found.</small>
|
||||
</div>
|
||||
@ -30,7 +30,8 @@
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#">Delete this list</a></li>
|
||||
<li><a class="dropdown-item" href="#"
|
||||
@click="deleteList(list)">Delete this list</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<span class="item-counter">
|
||||
@ -42,7 +43,7 @@
|
||||
|
||||
<div class="alert alert-info" v-if="gStore.lists.length === 0">
|
||||
<p>There are no lists, yet.</p>
|
||||
<button type="button" @click="addItem()" class="btn btn-primary btn-large">Create your first list</button>
|
||||
<button type="button" @click="addList()" class="btn btn-primary btn-large">Create your first list</button>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
@ -53,7 +54,10 @@
|
||||
|
||||
<script>
|
||||
import {gqlQuery} from "../util/net";
|
||||
import {store} from "../store";
|
||||
import {showError, store} from "../store";
|
||||
import {showModal} from "../util/misc";
|
||||
|
||||
const NEW_LIST_ID = "new-list-id";
|
||||
|
||||
export default {
|
||||
name: "Lists",
|
||||
@ -62,19 +66,87 @@ export default {
|
||||
|
||||
/**
|
||||
* Save a list to the database.
|
||||
* @param list
|
||||
* @param list - the list object to save.
|
||||
*/
|
||||
saveList(list)
|
||||
{
|
||||
/* Prepare request; it is different if the list is new */
|
||||
let gql = "";
|
||||
if (list.id === NEW_LIST_ID) {
|
||||
/* create new list */
|
||||
gql = `mutation {
|
||||
createList(
|
||||
title: "${list.title}"
|
||||
user: {
|
||||
username: "${store.session.username}"
|
||||
}
|
||||
) {
|
||||
id
|
||||
}
|
||||
}`;
|
||||
} else {
|
||||
/* save existing list */
|
||||
gql = `mutation {
|
||||
updateList(
|
||||
id: "${list.id}",
|
||||
title: "${list.title}"
|
||||
) {
|
||||
id
|
||||
}
|
||||
}`;
|
||||
}
|
||||
/* send query */
|
||||
gqlQuery(
|
||||
gql
|
||||
).then(data => {
|
||||
/* Save the list's id in case it was just created */
|
||||
list.id = data.List.id;
|
||||
}).catch(e => {
|
||||
const errMsg = `Failed to save list: ${e}`;
|
||||
console.error(errMsg);
|
||||
showError(errMsg);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a list.
|
||||
* @param list - the list object to delete
|
||||
*/
|
||||
deleteList(list) {
|
||||
if (list.id !== NEW_LIST_ID) {
|
||||
/* Make sure the list is not in use */
|
||||
if (store.tasks.findIndex(task => task.list.id === list.id) !== -1) {
|
||||
showModal("Delete List", "The list cannot be deleted as it is in use.");
|
||||
return;
|
||||
}
|
||||
/* List must be also deleted from the server */
|
||||
gqlQuery(`mutation {
|
||||
deleteList(id: "${list.id}") {
|
||||
id
|
||||
}
|
||||
}`);
|
||||
}
|
||||
|
||||
/* delete list from the store. */
|
||||
const idx = store.lists.findIndex(item => item.id === list.id);
|
||||
if (idx !== -1) {
|
||||
store.lists.splice(idx, 1);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a new list.
|
||||
*/
|
||||
addItem()
|
||||
addList()
|
||||
{
|
||||
|
||||
/* push it to the array of lists in the store; it will be saved
|
||||
* when the user leaves the title field.
|
||||
*/
|
||||
store.lists.push({
|
||||
title: "Enter list title",
|
||||
id: NEW_LIST_ID
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -12,24 +12,6 @@
|
||||
ToDo List
|
||||
</h1>
|
||||
|
||||
<!-- message modal -->
|
||||
<div class="modal" tabindex="-1" id="msgbox">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Modal title</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Modal body text goes here.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="filter-form" class="toolbar">
|
||||
|
||||
<label class="switch">
|
||||
@ -37,7 +19,7 @@
|
||||
Show completed
|
||||
</label>
|
||||
|
||||
<button type="button" @click="addItem()" class="ms-auto btn btn-primary btn-large">Add Item</button>
|
||||
<button type="button" @click="addTask()" class="ms-auto btn btn-primary btn-large">Add Item</button>
|
||||
|
||||
<div class="ms-auto">
|
||||
<div class="d-flex">
|
||||
@ -69,7 +51,7 @@
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" @click="deleteTask(task)">Delete this item</a></li>
|
||||
<li><a class="dropdown-item" href="" @click="deleteTask(task)">Delete this item</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -81,7 +63,7 @@
|
||||
</p>
|
||||
<p v-if="currentList !== 0">You can add items or select another list.</p>
|
||||
<hr>
|
||||
<button type="button" class="btn btn-primary btn-sm" @click="addItem()">Create Todo Item</button>
|
||||
<button type="button" class="btn btn-primary btn-sm" @click="addTask()">Create Todo Item</button>
|
||||
</div>
|
||||
|
||||
</transition-group>
|
||||
@ -93,7 +75,7 @@
|
||||
<script>
|
||||
import {gqlQuery} from "../util/net";
|
||||
import {showError, store} from "../store";
|
||||
import { Modal } from 'bootstrap';
|
||||
import {showModal} from "../util/misc";
|
||||
|
||||
const NEW_TASK_ID = "new-task-id";
|
||||
|
||||
@ -158,7 +140,7 @@ export default {
|
||||
gqlQuery(
|
||||
request
|
||||
).then(data => {
|
||||
/* save the task's id */
|
||||
/* Save the task's id in case it was just created */
|
||||
task.id = data.Task.id;
|
||||
}).catch(e => {
|
||||
const errMsg = `Failed to save task: ${e}`;
|
||||
@ -190,22 +172,11 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a message nox (Bootstrap modal)
|
||||
* Add a task to the current list.
|
||||
*/
|
||||
showModal(title, text) {
|
||||
const el = document.getElementById('msgbox');
|
||||
el.querySelector(".modal-title").innerHTML = title;
|
||||
el.querySelector(".modal-body").innerHTML = text;
|
||||
const modal = new Modal(el);
|
||||
modal.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an item to the current list.
|
||||
*/
|
||||
addItem() {
|
||||
addTask() {
|
||||
if (!this.currentList) {
|
||||
this.showModal("No list selected",
|
||||
showModal("No list selected",
|
||||
'Please select a specific list (not "All") before adding an item.');
|
||||
return;
|
||||
}
|
||||
|
21
src/util/misc.js
Normal file
21
src/util/misc.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Misc utility functions.
|
||||
*
|
||||
* Part of the basebox sample Todo app.
|
||||
* https://basebox.tech
|
||||
*/
|
||||
import {Modal} from "bootstrap";
|
||||
|
||||
/**
|
||||
* Show a message box (Bootstrap modal).
|
||||
*
|
||||
* The markup for the modal is defined in App.vue.
|
||||
*/
|
||||
export function showModal(title, text) {
|
||||
const el = document.getElementById('msgbox');
|
||||
el.querySelector(".modal-title").innerHTML = title;
|
||||
el.querySelector(".modal-body").innerHTML = text;
|
||||
const modal = new Modal(el);
|
||||
modal.show();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user