Added delete permantly button
This commit is contained in:
@@ -52,6 +52,8 @@
|
||||
8. **Task Reopening:** Added a "Reopen task" button to restore accidentally closed tasks back to the queue.
|
||||
9. **User Management (Settings):** Built backend API endpoints (`POST`, `PATCH`, `DELETE` for `/users`) and wired up the `WorkspaceTab` allowing Admins to manage the team from the UI.
|
||||
10. **Task Editing:** Implemented inline editing for task descriptions using an active text box state with "Save/Cancel" actions.
|
||||
11. **UI Cleanup:** Removed hardcoded, prototype placeholder notes from the `TaskDetail` modal to prepare for future dynamic notes integration.
|
||||
12. **Permanent Deletion:** Added a "Delete task permanently" button to the `TaskDetail` sidebar with a confirmation dialog, backed by a new `DELETE /tasks/{id}` API endpoint.
|
||||
|
||||
### Phase 3: Advanced Features
|
||||
- **Real-time Notifications:** Explore WebSockets for task assignments.
|
||||
|
||||
@@ -118,6 +118,14 @@ class ApiService {
|
||||
return data;
|
||||
}
|
||||
|
||||
async deleteTask(id) {
|
||||
const data = await this.request(`/tasks/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
this.notify();
|
||||
return data;
|
||||
}
|
||||
|
||||
async addAudit(auditData) {
|
||||
const data = await this.request('/audit', {
|
||||
method: 'POST',
|
||||
|
||||
@@ -166,6 +166,18 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const deleteTask = async (taskId) => {
|
||||
try {
|
||||
const t = tasks.find(x => x.id === taskId);
|
||||
await api.deleteTask(taskId);
|
||||
await api.addAudit({ actor: meId, action: 'task_deleted', summary: 'Deleted task' + (t ? ': ' + t.title : ''), target: taskId });
|
||||
setOpenTaskId(null);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
alert("Failed to delete task: " + e.message);
|
||||
}
|
||||
};
|
||||
|
||||
const dismissHU = (id) => setHeadsUp(h => h.filter(x => x.id !== id));
|
||||
const openTaskFromAnywhere = (id) => { setOpenTaskId(id); setShowLogs(false); };
|
||||
|
||||
@@ -223,7 +235,7 @@ function App() {
|
||||
|
||||
<AddTaskModal open={!!adding} onClose={() => setAdding(null)} onSubmit={addTask} defaultAssignee={adding} me={me} />
|
||||
{mappedOpenTask && (
|
||||
<TaskDetail task={mappedOpenTask} allAudit={frontendAudit} onClose={() => setOpenTaskId(null)} onMove={moveTask} onPriority={setPriority} onComplete={() => completeTask(mappedOpenTask.id)} onReopen={() => reopenTask(mappedOpenTask.id)} onEditDesc={(newDesc) => editTaskDesc(mappedOpenTask.id, newDesc)} />
|
||||
<TaskDetail task={mappedOpenTask} allAudit={frontendAudit} onClose={() => setOpenTaskId(null)} onMove={moveTask} onPriority={setPriority} onComplete={() => completeTask(mappedOpenTask.id)} onReopen={() => reopenTask(mappedOpenTask.id)} onEditDesc={(newDesc) => editTaskDesc(mappedOpenTask.id, newDesc)} onDeleteTask={() => deleteTask(mappedOpenTask.id)} />
|
||||
)}
|
||||
{showLogs && (
|
||||
<Modal title="Audit log" onClose={() => setShowLogs(false)} wide>
|
||||
|
||||
+11
-2
@@ -118,15 +118,24 @@ def update_task(task_id: str, task_update: schemas.TaskUpdate, db: Session = Dep
|
||||
db_task = db.query(models.Task).filter(models.Task.id == task_id).first()
|
||||
if not db_task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
|
||||
update_data = task_update.dict(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(db_task, key, value)
|
||||
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_task)
|
||||
return db_task
|
||||
|
||||
@app.delete("/tasks/{task_id}")
|
||||
def delete_task(task_id: str, db: Session = Depends(get_db)):
|
||||
db_task = db.query(models.Task).filter(models.Task.id == task_id).first()
|
||||
if not db_task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
db.delete(db_task)
|
||||
db.commit()
|
||||
return {"message": "Task deleted"}
|
||||
@app.get("/audit", response_model=List[schemas.AuditLog])
|
||||
def read_audit(db: Session = Depends(get_db)):
|
||||
return db.query(models.AuditLog).order_by(models.AuditLog.at.desc()).all()
|
||||
|
||||
+11
-1
@@ -407,7 +407,7 @@ function Modal({ children, onClose, title, eyebrow, wide = false }) {
|
||||
);
|
||||
}
|
||||
|
||||
function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComplete, onReopen, onEditDesc }) {
|
||||
function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComplete, onReopen, onEditDesc, onDeleteTask }) {
|
||||
const [editingDesc, setEditingDesc] = React.useState(false);
|
||||
const [descValue, setDescValue] = React.useState(task ? task.description || '' : '');
|
||||
|
||||
@@ -557,6 +557,16 @@ function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComple
|
||||
<Field label="Reminder">
|
||||
<div className="meta-row">Thu, May 7 · 4:00 pm</div>
|
||||
</Field>
|
||||
|
||||
<div style={{ marginTop: '2rem', paddingTop: '1.5rem', borderTop: '1px solid var(--border-subtle)' }}>
|
||||
<button
|
||||
className="btn btn--ghost btn--full"
|
||||
style={{ color: 'var(--prio-high-dot)', borderColor: 'transparent' }}
|
||||
onClick={() => { if (confirm('Are you sure you want to permanently delete this task?')) onDeleteTask(); }}
|
||||
>
|
||||
<Icon.Close /> Delete task permanently
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user