mirror of
https://github.com/supanadit/todo.git
synced 2024-11-21 17:46:23 +00:00
Todo List and item
This commit is contained in:
parent
981fc35917
commit
15e9ca1d91
@ -11,9 +11,15 @@ class TodoController extends Controller
|
||||
return view('home');
|
||||
}
|
||||
|
||||
// Todo
|
||||
public function todoList(Request $request)
|
||||
{
|
||||
return \App\Todo::where('user_id', $request->session()->get('user'))->get();
|
||||
$search = $request->query('search');
|
||||
$model = \App\Todo::with('todoItems')->where('user_id', $request->session()->get('user'));
|
||||
if ($search != null && $search != "") {
|
||||
$model = $model->where("name", "like", "%$search%")->orWhere("description", "like", "%$search%");
|
||||
}
|
||||
return $model->get();
|
||||
}
|
||||
|
||||
public function todoManipulate(Request $request, $id)
|
||||
@ -55,13 +61,13 @@ class TodoController extends Controller
|
||||
|
||||
public function todoView(Request $request, $id)
|
||||
{
|
||||
$model = \App\Todo::find($id);
|
||||
$model = \App\Todo::with('todoItems')->find($id);
|
||||
if ($model == null) {
|
||||
return response()->json(array(
|
||||
"message" => "There's no todo with id $id"
|
||||
), 400);
|
||||
} else {
|
||||
return $model->with('todo_items');
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,4 +90,113 @@ class TodoController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
// End Todo
|
||||
|
||||
// Todo Items
|
||||
public function todoItemList(Request $request, $todo_id)
|
||||
{
|
||||
$search = $request->query('search');
|
||||
$model = \App\TodoItem::where('todo_id', $todo_id);
|
||||
if ($search != null && $search != "") {
|
||||
$model = $model->where("name", "like", "%$search%");
|
||||
}
|
||||
return $model->get();
|
||||
}
|
||||
|
||||
public function todoItemManipulate(Request $request, $id)
|
||||
{
|
||||
$todo = new \App\TodoItem();
|
||||
if ($id != null) {
|
||||
$todo = \App\TodoItem::find($id);
|
||||
}
|
||||
$todo['name'] = $request->input('name');
|
||||
$todo['complete'] = ($request->input('complete') != null) ? $request->input('complete') : false;
|
||||
$todo['todo_id'] = $request->input('todo_id');
|
||||
if ($todo->save()) {
|
||||
return response()->json(array(
|
||||
"message" => "Success " . ($id != null ? "edit" : "create") . " todo item"
|
||||
), 200);
|
||||
} else {
|
||||
return response()->json(array(
|
||||
"message" => "Failed create todo item"
|
||||
), 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function todoItemCreate(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required",
|
||||
"todo_id" => "required",
|
||||
]);
|
||||
return $this->todoItemManipulate($request, null);
|
||||
}
|
||||
|
||||
public function todoItemEdit(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required",
|
||||
"id" => "required",
|
||||
"todo_id" => "required",
|
||||
]);
|
||||
return $this->todoItemManipulate($request, $request->input('id'));
|
||||
}
|
||||
|
||||
public function todoItemView(Request $request, $id)
|
||||
{
|
||||
$model = \App\TodoItem::find($id);
|
||||
if ($model == null) {
|
||||
return response()->json(array(
|
||||
"message" => "There's no todo item with id $id"
|
||||
), 400);
|
||||
} else {
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
|
||||
public function todoItemDelete(Request $request, $id)
|
||||
{
|
||||
$model = \App\TodoItem::find($id);
|
||||
if ($model == null) {
|
||||
return response()->json(array(
|
||||
"message" => "There's no todo item with id $id"
|
||||
), 400);
|
||||
} else {
|
||||
if ($model->delete()) {
|
||||
return response()->json(array(
|
||||
"message" => "Success delete todo item"
|
||||
), 200);
|
||||
} else {
|
||||
return response()->json(array(
|
||||
"message" => "Failed delete todo item"
|
||||
), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function todoItemMark(Request $request, $id, $complete = true)
|
||||
{
|
||||
$todo = \App\TodoItem::find($id);
|
||||
$todo['complete'] = $complete;
|
||||
if ($todo->save()) {
|
||||
return response()->json(array(
|
||||
"message" => "Success mark " . ($complete ? "complete" : "not complete")
|
||||
), 200);
|
||||
} else {
|
||||
return response()->json(array(
|
||||
"message" => "Failed mark todo item"
|
||||
), 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function todoItemMarkComplete(Request $request, $id)
|
||||
{
|
||||
return $this->todoItemMark($request, $id, true);
|
||||
}
|
||||
|
||||
public function todoItemMarkNotComplete(Request $request, $id)
|
||||
{
|
||||
return $this->todoItemMark($request, $id, false);
|
||||
}
|
||||
// End Todo Items
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
@endsection
|
||||
|
||||
@section('top-button')
|
||||
<button class="btn btn-info btn-sm" data-toggle="modal" data-target="#modal-default">
|
||||
<button class="btn btn-info btn-sm" data-toggle="modal" data-target="#todo-create-modal">
|
||||
Create Todo
|
||||
</button>
|
||||
@endsection
|
||||
@ -25,44 +25,131 @@
|
||||
@section('content')
|
||||
<input type="text" class="form-control" placeholder="Search" id="search-todo"/>
|
||||
<br/>
|
||||
<!-- /.box -->
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="box box-widget widget-user">
|
||||
<!-- Add the bg color to the header using any of the bg-* classes -->
|
||||
<div class="widget-user-header bg-aqua-active">
|
||||
<h3 class="widget-user-username">Alexander Pierce</h3>
|
||||
<h5 class="widget-user-desc">Founder & CEO</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" id="todo-list">
|
||||
<div style="text-align: center;height: 200px;position: relative;">
|
||||
<i class="fa fa-spinner fa-spin" style="position: absolute;top:50%;left:50%;"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modal-default">
|
||||
<div class="modal fade" id="todo-create-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form action="/" method="post" id="todo-create-modal-form">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Create Todo</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
<input type="text" class="form-control" placeholder="Insert todo name or title"
|
||||
id="todo-create-field-name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea class="form-control"
|
||||
id="todo-create-field-description"
|
||||
rows="3"
|
||||
style="resize:vertical;max-height: 200px;min-height:100px;"
|
||||
placeholder="Describe what this todo really is"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fa fa-spinner fa-spin" id="todo-create-modal-save-loading-indicator"></i>
|
||||
<span id="todo-create-modal-save-button-label">Save</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="todo-view-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Default Modal</h4>
|
||||
<h4 class="modal-title" id="todo-view-modal-title"></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>One fine body…</p>
|
||||
<dl>
|
||||
<dt>Description</dt>
|
||||
<dd id="todo-view-modal-description"></dd>
|
||||
</dl>
|
||||
<div>
|
||||
<b>Todo Item List</b>
|
||||
<div class="pull-right">
|
||||
<button class="btn btn-info btn-xs" id="todo-view-modal-add-todo-item-button">
|
||||
Add Todo Item
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th style="width: 90px;">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="todo-view-modal-table-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary">Save changes</button>
|
||||
<button type="button" class="btn btn-info">Edit Todo</button>
|
||||
<button type="button" class="btn btn-danger">Delete Todo</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
<!-- /.modal -->
|
||||
|
||||
<div class="modal fade" id="todo-item-create-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form action="/" method="post" id="todo-item-create-modal-form">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Create Todo Item</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="Insert todo item name here"
|
||||
id="todo-item-create-modal-field-name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left"
|
||||
id="todo-item-create-modal-cancel-button">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fa fa-spinner fa-spin" id="todo-item-create-modal-save-loading-indicator"></i>
|
||||
<span id="todo-item-create-modal-save-button">Save</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('js')
|
||||
<script type="application/javascript">
|
||||
let todoId = null;
|
||||
|
||||
$(document).bind('keydown', function (e) {
|
||||
// CTRL + S
|
||||
if (e.ctrlKey && e.which === 83) {
|
||||
@ -78,13 +165,221 @@
|
||||
|
||||
// ALT + N
|
||||
if (e.altKey && e.which === 78) {
|
||||
$("#modal-default").modal('show');
|
||||
$("#todo-create-modal").modal('show');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
const loadTodoList = function () {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/web/todo",
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: {
|
||||
"search": $("#search-todo").val(),
|
||||
},
|
||||
contentType: "application/json",
|
||||
async: true,
|
||||
success: function (result) {
|
||||
if (result.length !== 0) {
|
||||
$("#todo-list").html(result.map(m => todoComponent(m)));
|
||||
} else {
|
||||
$("#todo-list").html("<div style=\"text-align: center;height: 200px;position: relative;\">\n" +
|
||||
" <p style=\"position: absolute;top:50%;left:50%;color:#777;\"><i class='fa fa-calendar-times-o'></i> Not found or empty</p>\n" +
|
||||
" </div>");
|
||||
}
|
||||
},
|
||||
error: function (result) {
|
||||
toastr.error(result.responseJSON.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const todoComponent = function (todo) {
|
||||
const description = (todo.description != null ? (todo.description.length > 20) ? todo.description.substring(0, 20).concat("...") : todo.description : "");
|
||||
const todoData = "<div class=\"col-md-4 col-sm-6 col-xs-12\">\n" +
|
||||
" <div class=\"box box-widget widget-user\">\n" +
|
||||
" <!-- Add the bg color to the header using any of the bg-* classes -->\n" +
|
||||
" <div class=\"widget-user-header bg-aqua-active\">\n" +
|
||||
" <h3 class=\"widget-user-username\">" + todo.name + "</h3>\n" +
|
||||
" <h5 class=\"widget-user-desc\">" + description + "</h5>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </div>";
|
||||
return $(todoData).click(function () {
|
||||
todoId = todo.id;
|
||||
|
||||
loadTodoItemList();
|
||||
|
||||
$("#todo-view-modal-title").html(todo.name);
|
||||
$("#todo-view-modal-description").html(todo.description);
|
||||
|
||||
$("#todo-view-modal").modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
const todoItemTableRowComponent = function (todoItem) {
|
||||
const buttonToggleMark = "<button type=\"button\" class=\"btn btn-xs " + (!todoItem.complete ? "btn-danger" : "btn-success") + "\"><i class=\"fa " + (!todoItem.complete ? "fa-toggle-off" : "fa-toggle-on") + "\"></i></button>";
|
||||
const buttonEdit = "<button class=\"btn btn-xs btn-info\"><i class=\"fa fa-edit\"></i></button>";
|
||||
return "<tr>\n" +
|
||||
" <td>" + todoItem.name + "</td>\n" +
|
||||
" <td><label class=\"label " + (!todoItem.complete ? "label-danger" : "label-success") + "\">" + (!todoItem.complete ? "Not complete" : "Complete") + "</label></td>\n" +
|
||||
" <td>\n" +
|
||||
" " + buttonToggleMark + "\n" +
|
||||
" " + buttonEdit + "\n" +
|
||||
" <button class=\"btn btn-xs btn-danger\"><i class=\"fa fa-trash\"></i></button>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>";
|
||||
}
|
||||
|
||||
const loadTodoItemList = function () {
|
||||
$("#todo-view-modal-table-body").html("<tr>\n" +
|
||||
" <td colspan=\"4\" style=\"text-align:center;color:#777;\">\n" +
|
||||
" <i class=\"fa fa-spinner fa-spin\"></i>\n" +
|
||||
" </td>\n" +
|
||||
" </tr>");
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/web/todo/item/" + todoId,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
contentType: "application/json",
|
||||
async: true,
|
||||
success: function (result) {
|
||||
if (result.length !== 0) {
|
||||
$("#todo-view-modal-table-body").html(result.map(m => todoItemTableRowComponent(m)));
|
||||
} else {
|
||||
$("#todo-view-modal-table-body").html("<tr>\n" +
|
||||
" <td colspan=\"4\" style=\"text-align:center;color:#777;\">\n" +
|
||||
" No Todo Item\n" +
|
||||
" </td>\n" +
|
||||
" </tr>");
|
||||
}
|
||||
},
|
||||
error: function (result) {
|
||||
toastr.error(result.responseJSON.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
// Prepare Data From Backend
|
||||
loadTodoList();
|
||||
|
||||
// Component Initialization
|
||||
$("#todo-create-modal-save-loading-indicator").hide();
|
||||
$("#todo-item-create-modal-save-loading-indicator").hide();
|
||||
|
||||
// Create Todo Submit Action
|
||||
$("#todo-create-modal-form").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = $("#todo-create-field-name");
|
||||
const description = $("#todo-create-field-description");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/web/todo",
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: JSON.stringify({
|
||||
"name": name.val(),
|
||||
"description": description.val(),
|
||||
}),
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
async: true,
|
||||
beforeSend: function () {
|
||||
$("#todo-create-modal-save-loading-indicator").show();
|
||||
$("#todo-create-modal-save-button-label").hide();
|
||||
},
|
||||
success: function (result) {
|
||||
$("#todo-create-modal-save-loading-indicator").hide();
|
||||
$("#todo-create-modal-save-button-label").show();
|
||||
|
||||
name.val(null);
|
||||
description.val(null);
|
||||
|
||||
toastr.success(result.message);
|
||||
|
||||
$("#todo-create-modal").modal('hide');
|
||||
|
||||
loadTodoList();
|
||||
},
|
||||
error: function (result) {
|
||||
$("#todo-create-modal-save-loading-indicator").hide();
|
||||
$("#todo-create-modal-save-button-label").show();
|
||||
|
||||
toastr.error(result.responseJSON.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Create Todo Item Submit Action
|
||||
$("#todo-item-create-modal-form").on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const name = $("#todo-item-create-modal-field-name");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/web/todo/item",
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
|
||||
},
|
||||
data: JSON.stringify({
|
||||
"name": name.val(),
|
||||
"todo_id": todoId,
|
||||
}),
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
async: true,
|
||||
beforeSend: function () {
|
||||
$("#todo-item-create-modal-save-loading-indicator").show();
|
||||
$("#todo-item-create-modal-save-button-label").hide();
|
||||
},
|
||||
success: function (result) {
|
||||
$("#todo-item-create-modal-save-loading-indicator").hide();
|
||||
$("#todo-item-create-modal-save-button-label").show();
|
||||
|
||||
name.val(null);
|
||||
|
||||
toastr.success(result.message);
|
||||
|
||||
$("#todo-view-modal").modal('show');
|
||||
$("#todo-item-create-modal").modal('hide');
|
||||
|
||||
loadTodoItemList();
|
||||
},
|
||||
error: function (result) {
|
||||
$("#todo-item-create-modal-save-loading-indicator").hide();
|
||||
$("#todo-item-create-modal-save-button-label").show();
|
||||
|
||||
toastr.error(result.responseJSON.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Search
|
||||
$("input#search-todo").on('keyup', function () {
|
||||
loadTodoList();
|
||||
});
|
||||
|
||||
// Button Add Todo Item
|
||||
$("#todo-view-modal-add-todo-item-button").click(function () {
|
||||
$("#todo-view-modal").modal('hide');
|
||||
$("#todo-item-create-modal").modal('show');
|
||||
});
|
||||
|
||||
// Button Cancel On Create Todo Item Modal
|
||||
$("#todo-item-create-modal-cancel-button").click(function () {
|
||||
$("#todo-view-modal").modal('show');
|
||||
$("#todo-item-create-modal").modal('hide');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
@ -21,11 +21,22 @@ Route::middleware('auth.web')->group(function () {
|
||||
|
||||
// This group is used for internal API provided by session
|
||||
Route::prefix('/web')->group(function () {
|
||||
// Todo
|
||||
Route::get('/todo', "TodoController@todoList");
|
||||
Route::post('/todo', "TodoController@todoCreate");
|
||||
Route::put('/todo', "TodoController@todoEdit");
|
||||
Route::get('/todo/{id}', "TodoController@todoView");
|
||||
Route::delete('/todo/{id}', "TodoController@todoDelete");
|
||||
|
||||
// Todo Item
|
||||
Route::get('/todo/item/mark/{id}', "TodoController@todoItemMarkComplete");
|
||||
Route::get('/todo/item/unmark/{id}', "TodoController@todoItemMarkNotComplete");
|
||||
|
||||
Route::get('/todo/item/{todo_id}', "TodoController@todoItemList");
|
||||
Route::post('/todo/item', "TodoController@todoItemCreate");
|
||||
Route::put('/todo/item', "TodoController@todoItemEdit");
|
||||
Route::get('/todo/item/{id}', "TodoController@todoItemView");
|
||||
Route::delete('/todo/item/{id}', "TodoController@todoItemDelete");
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user