Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Edit a Task / Group #11

Merged
merged 3 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,3 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# Fuckin tauri man
stupid_env.txt
14 changes: 14 additions & 0 deletions src-tauri/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,20 @@ pub mod ops {
}
}

#[tauri::command(rename_all = "snake_case")]
pub fn edit_task_or_group(table: &str, name: &str, id: u64) {
let db = DB_SINGLETON.lock().unwrap();

if let Some(conn) = &db.db_conn {
let command = format!("UPDATE {table} SET name=(?1) WHERE id=(?2)");

match conn.execute(&command, params![name, id]) {
Ok(_) => (),
Err(err) => println!("[ERROR] Could not update task: {}", err.to_string()),
}
}
}

/* ----------------------------------------------------------------------------- */
/* -------------------------------HELPER FUNCTIONS------------------------------ */
/* ----------------------------------------------------------------------------- */
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ fn main() {
ops::commands::add_task_group,
ops::commands::delete_task,
ops::commands::delete_task_group,
ops::commands::edit_task_or_group,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
22 changes: 21 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,26 @@ form .form-group select {
user-select: none;
}

.edit-area {
height: 25px;
width: 100%;
align-items: center;
}

.edit-task-inp {
height: inherit;
width: inherit;
background: transparent;
border: none;
font-size: 20px;
color: white;
font-family: Inter;
caret-color: white;
outline: none;
animation: phase-caret 1s ease-in-out infinite;
overflow: visible;
}

/* ---------- */
/* Task Group */
/* ---------- */
Expand Down Expand Up @@ -695,7 +715,7 @@ form .form-group select {
}

.featured-day-name {
margin-top: 10px;
margin-top: 10px;
font-size: 20px;
text-align: center;
color: wheat;
Expand Down
2 changes: 2 additions & 0 deletions src/Constants.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const TAURI_ADD_TASK = "add_task";
const TAURI_ADD_TASKGROUP = "add_task_group";
const TAURI_DELETE_TASK = "delete_task";
const TAURI_DELETE_GROUP = "delete_task_group";
const TAURI_EDIT_TASK_OR_GROUP = "edit_task_or_group";

export {
// Table names
Expand All @@ -34,4 +35,5 @@ export {
TAURI_ADD_TASKGROUP,
TAURI_DELETE_TASK,
TAURI_DELETE_GROUP,
TAURI_EDIT_TASK_OR_GROUP,
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const removeItem = (id, node) => {

return child.id !== id;
});
node.children.sort(tasksFirstGroupsNext)
node.children.sort(tasksFirstGroupsNext);
// If item not found in node.children, search and remove it from each child of node.children.
node.children.forEach((child) => removeItem(id, child));
}
Expand All @@ -40,4 +40,14 @@ function tasksFirstGroupsNext(child1, child2) {
}
}

export { addItem, removeItem };
const updateItem = (id, name, node) => {
if (node.id === id) {
console.log("previous name: " + node.name);
node.name = name;
console.log("updated name: " + node.name);
} else if (node.children) {
node.children.forEach((child) => updateItem(id, name, child));
}
};

export { addItem, removeItem, updateItem };
2 changes: 1 addition & 1 deletion src/views/TasksView/DragDropContext.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { createContext, useEffect, useState } from "react";

import { addItem, removeItem } from "../../utility/AddRemoveItems";
import { addItem, removeItem } from "../../utility/AddRemoveUpdateItems";
import { TASKS_VIEW } from "../../Constants";

const DragDropContext = createContext();
Expand Down
126 changes: 104 additions & 22 deletions src/views/TasksView/Task.jsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,145 @@
import React from "react";
import { useContext } from "react";
import React, { useState, useEffect, useContext } from "react";
import { invoke } from "@tauri-apps/api";

// Icon Imports
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import CheckIcon from "@mui/icons-material/Check";

// Local Resources
import { DragDropContext } from "./DragDropContext";
import { TASK, TASKS_VIEW, TAURI_DELETE_TASK, TODAY } from "../../Constants";
import { removeItem } from "../../utility/AddRemoveItems";
import {
TASK,
TASKS_VIEW,
TODAY,
TAURI_DELETE_TASK,
TAURI_EDIT_TASK_OR_GROUP,
} from "../../Constants";
import { removeItem, updateItem } from "../../utility/AddRemoveUpdateItems";

const Task = (props) => {
// Adds ID of dragged task to DragEvent datastore and changes state of the DragDropContext.
const { handleOnDrag } = useContext(DragDropContext);

const [editingTaskId, setEditingTaskId] = useState(null);
const [editedName, setEditedName] = useState(null);

useEffect(() => {
if (editingTaskId) {
window.addEventListener('keydown', handleKeyDown);
} else {
window.removeEventListener('keydown', handleKeyDown);
}

return () => {
window.removeEventListener('keydown', handleKeyDown);
}
}, [editingTaskId]);

const handleDelete = (e) => {
e.preventDefault();

// Delete task from the database.
invoke(TAURI_DELETE_TASK, {
table: TODAY,
id: props.id,
});

// Delete task from the frontend.
let storedView = JSON.parse(sessionStorage.getItem(TASKS_VIEW));

removeItem(props.id, storedView);

sessionStorage.setItem(TASKS_VIEW, JSON.stringify(storedView));
props.onDelete();
props.onChangeTasksView();
};

function handleEdit() {
if (editingTaskId) {
setEditingTaskId(null);
} else {
setEditingTaskId(props.id);
}
}

function onChange(e) {
setEditedName(e.target.value);
}

function handleConfirmEdit() {
// Update name in the database.
invoke(TAURI_EDIT_TASK_OR_GROUP, {
table: TODAY,
name: editedName,
id: props.id,
});

// Update name on the frontend.
const storedView = JSON.parse(sessionStorage.getItem(TASKS_VIEW));
updateItem(props.id, editedName, storedView);
sessionStorage.setItem(TASKS_VIEW, JSON.stringify(storedView));

setEditingTaskId(null);
props.onChangeTasksView();
}

const handleKeyDown = (e) => {
if (e.key === 'Escape') {
cancelEdit();
}
}

function cancelEdit() {
setEditedName(null);
setEditingTaskId(null);
}

return (
<div
className="task-card"
draggable
onDragStart={(e) => {
/* A duplicate of this current task is passed to handleOnDrag*/
handleOnDrag(e, { id: props.id, name: props.name, type: TASK })
}}
handleOnDrag(e, { id: props.id, name: props.name, type: TASK });
}}
>
<input type="checkbox" id={props.id} />
<label className="task-checkbox" htmlFor={props.id}></label>
<div className="text-container">
<label className="task-name" htmlFor={props.id}>
{props.name}
</label>
{editingTaskId === props.id ? (
<span className="edit-area">
<input
type="text"
className="edit-task-inp"
onInput={onChange}
autoFocus
/>
</span>
) : (
<label className="task-name" htmlFor={props.id}>
{props.name}
</label>
)}
</div>
<ul>
<li>
<button className="task-btn">
<EditIcon></EditIcon>
</button>
</li>
<li>
<button className="delete-icon" onClick={handleDelete}>
<DeleteIcon></DeleteIcon>
</button>
</li>
{editingTaskId == props.id ? (
<li>
<button className="task-btn" onClick={handleConfirmEdit}>
<CheckIcon />
</button>
</li>
) : (
<>
<li>
<button className="task-btn" onClick={handleEdit}>
<EditIcon />
</button>
</li>
<li>
<button className="delete-icon" onClick={handleDelete}>
<DeleteIcon />
</button>
</li>
</>
)}
</ul>
</div>
);
Expand Down
14 changes: 7 additions & 7 deletions src/views/TasksView/TaskGroup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import {
import Task from "./Task";
import { DragDropContext } from "./DragDropContext";
import { invoke } from "@tauri-apps/api";
import { removeItem } from "../../utility/AddRemoveItems";
import { removeItem } from "../../utility/AddRemoveUpdateItems";
import AlertModal from "../../components/AlertModal";

const TaskGroup = ({ id, name, children, onDelete }) => {
const TaskGroup = ({ id, name, children, onChangeTasksView }) => {
const [anchorEl, setAnchorEl] = useState(null);
const [showAlert, setAlertVisibility] = useState(false);

Expand Down Expand Up @@ -59,7 +59,7 @@ const TaskGroup = ({ id, name, children, onDelete }) => {
removeItem(id, storedView);
sessionStorage.setItem(TASKS_VIEW, JSON.stringify(storedView));
// To rerender TasksView.
onDelete();
onChangeTasksView();
}

function onCancel() {
Expand Down Expand Up @@ -97,8 +97,8 @@ const TaskGroup = ({ id, name, children, onDelete }) => {
onClose={handleClose}
open={open}
MenuListProps={{
'display': "flex",
'flex-direction': "column",
display: "flex",
"flex-direction": "column",
}}
>
{groupOptions.map((option) => (
Expand All @@ -121,7 +121,7 @@ const TaskGroup = ({ id, name, children, onDelete }) => {
name={child.name}
id={child.id}
key={child.id}
onDelete={onDelete}
onChangeTasksView={onChangeTasksView}
/>
);
} else if (child.type === TASK_GROUP) {
Expand All @@ -131,7 +131,7 @@ const TaskGroup = ({ id, name, children, onDelete }) => {
id={child.id}
name={child.name}
children={child.children}
onDelete={onDelete}
onChangeTasksView={onChangeTasksView}
/>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/views/TasksView/TasksView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import TaskGroup from "./TaskGroup";
import { DragDropProvider, DragDropContext } from "./DragDropContext";
import Modal from "../../components/Modal";
import { addItem } from "../../utility/AddRemoveItems";
import { addItem } from "../../utility/AddRemoveUpdateItems";

/*
TODO -> ERROR HANDLING.
Expand Down Expand Up @@ -151,7 +151,7 @@ const TasksView = () => {
setModalVisibility(false);
}

function onDelete() {
function onChangeTasksView() {
setStructure(JSON.parse(sessionStorage.getItem(TASKS_VIEW)));
}

Expand All @@ -172,7 +172,7 @@ const TasksView = () => {
id={structure.id}
name={structure.name}
children={structure.children}
onDelete={onDelete}
onChangeTasksView={onChangeTasksView}
/>
) : (
<p>loading...</p>
Expand Down