mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-18 21:44:07 +01:00
Merge pull request #68 from TurTaskProject/feature/kanban-board
Comment some bugs feature, deploy by 10pm of 23/11
This commit is contained in:
commit
0158fe5a87
@ -1,11 +1,13 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from boards.models import Board, ListBoard
|
||||
from boards.serializers import BoardSerializer, ListBoardSerializer
|
||||
|
||||
class BoardViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
queryset = Board.objects.all()
|
||||
serializer_class = BoardSerializer
|
||||
http_method_names = ['get']
|
||||
@ -16,6 +18,7 @@ class BoardViewSet(viewsets.ModelViewSet):
|
||||
|
||||
|
||||
class ListBoardViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
serializer_class = ListBoardSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { formatDate } from "@fullcalendar/core";
|
||||
import FullCalendar from "@fullcalendar/react";
|
||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import { getEvents, createEventId } from "./TaskDataHandler";
|
||||
import { axiosInstance } from "src/api/AxiosConfig";
|
||||
|
||||
export class Calendar extends React.Component {
|
||||
state = {
|
||||
@ -62,10 +61,13 @@ export class Calendar extends React.Component {
|
||||
type="checkbox"
|
||||
checked={this.state.weekendsVisible}
|
||||
onChange={this.handleWeekendsToggle}
|
||||
className="mr-2"
|
||||
className="mr-2 mb-4"
|
||||
/>
|
||||
Toggle weekends
|
||||
</label>
|
||||
<button className="btn btn-info" onClick={() => alert("Commit soon🥺")}>
|
||||
Load Data from Google
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Show all task */}
|
||||
|
||||
@ -224,30 +224,24 @@ export function KanbanBoard() {
|
||||
|
||||
const isActiveATask = active.data.current?.type === "Task";
|
||||
const isOverAColumn = over.data.current?.type === "Column";
|
||||
const isOverATask = over.data.current?.type === "Task";
|
||||
|
||||
// Reorder logic for Tasks within the same column
|
||||
if (isActiveATask && isOverATask) {
|
||||
setTasks((tasks) => {
|
||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||
const overIndex = tasks.findIndex((t) => t.id === overId);
|
||||
|
||||
const reorderedTasks = arrayMove(tasks, activeIndex, overIndex);
|
||||
|
||||
return reorderedTasks;
|
||||
});
|
||||
}
|
||||
|
||||
// Move tasks between columns and update columnId
|
||||
if (isActiveATask && isOverAColumn) {
|
||||
setTasks((tasks) => {
|
||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||
|
||||
tasks[activeIndex].columnId = overId;
|
||||
// Extract the column ID from overId
|
||||
const columnId = extractColumnId(overId);
|
||||
|
||||
tasks[activeIndex].columnId = columnId;
|
||||
|
||||
// API call to update task's columnId
|
||||
axiosInstance
|
||||
.put(`todo/change_task_list_board/`, { todo_id: activeId, new_list_board_id: overId, new_index: 0 })
|
||||
.put(`todo/change_task_list_board/`, {
|
||||
todo_id: activeId,
|
||||
new_list_board_id: over.data.current.task.columnId,
|
||||
new_index: 0,
|
||||
})
|
||||
.then((response) => {})
|
||||
.catch((error) => {
|
||||
console.error("Error updating task columnId:", error);
|
||||
@ -258,6 +252,14 @@ export function KanbanBoard() {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to extract the column ID from the element ID
|
||||
function extractColumnId(elementId) {
|
||||
// Implement logic to extract the column ID from elementId
|
||||
// For example, if elementId is in the format "column-123", you can do:
|
||||
const parts = elementId.split("-");
|
||||
return parts.length === 2 ? parseInt(parts[1], 10) : null;
|
||||
}
|
||||
|
||||
// Handle the drag-over event
|
||||
function onDragOver(event) {
|
||||
const { active, over } = event;
|
||||
@ -284,7 +286,16 @@ export function KanbanBoard() {
|
||||
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
||||
return arrayMove(tasks, activeIndex, overIndex - 1);
|
||||
}
|
||||
|
||||
axiosInstance
|
||||
.put(`todo/change_task_list_board/`, {
|
||||
todo_id: activeId,
|
||||
new_list_board_id: over.data.current.task.columnId,
|
||||
new_index: 0,
|
||||
})
|
||||
.then((response) => {})
|
||||
.catch((error) => {
|
||||
console.error("Error updating task columnId:", error);
|
||||
});
|
||||
return arrayMove(tasks, activeIndex, overIndex);
|
||||
});
|
||||
}
|
||||
@ -294,7 +305,16 @@ export function KanbanBoard() {
|
||||
if (isActiveATask && isOverAColumn && tasks.some((task) => task.columnId !== overId)) {
|
||||
setTasks((tasks) => {
|
||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
||||
|
||||
axiosInstance
|
||||
.put(`todo/change_task_list_board/`, {
|
||||
todo_id: activeId,
|
||||
new_list_board_id: over.data.current.task.columnId,
|
||||
new_index: 0,
|
||||
})
|
||||
.then((response) => {})
|
||||
.catch((error) => {
|
||||
console.error("Error updating task columnId:", error);
|
||||
});
|
||||
tasks[activeIndex].columnId = overId;
|
||||
return arrayMove(tasks, activeIndex, activeIndex);
|
||||
});
|
||||
|
||||
@ -19,12 +19,12 @@ export const KanbanPage = () => {
|
||||
onClick={() => handleTabClick("kanban")}>
|
||||
Kanban
|
||||
</a>
|
||||
<a
|
||||
{/* <a
|
||||
id="table"
|
||||
className={`tab ${activeTab === "table" ? "tab-active" : ""}`}
|
||||
onClick={() => handleTabClick("table")}>
|
||||
Table
|
||||
</a>
|
||||
</a> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -9,9 +9,9 @@ const menuItems = [
|
||||
{ id: 0, path: "/", icon: <AiOutlineHome /> },
|
||||
{ id: 1, path: "/tasks", icon: <AiOutlineUnorderedList /> },
|
||||
{ id: 2, path: "/calendar", icon: <AiOutlineSchedule /> },
|
||||
{ id: 3, path: "/settings", icon: <IoSettingsOutline /> },
|
||||
{ id: 4, path: "/priority", icon: <PiStepsDuotone /> },
|
||||
{ id: 3, path: "/priority", icon: <PiStepsDuotone /> },
|
||||
];
|
||||
// { id: 3, path: "/settings", icon: <IoSettingsOutline /> },
|
||||
|
||||
export const SideNav = () => {
|
||||
const [selected, setSelected] = useState(0);
|
||||
|
||||
@ -25,14 +25,14 @@ export function NavBar() {
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex-none gap-2">
|
||||
<div className="form-control">
|
||||
<input type="text" placeholder="Search" className="input input-bordered w-24 md:w-auto" />
|
||||
</div>
|
||||
{/* <div className="form-control">
|
||||
<button className="btn btn-success">Sync Data</button>
|
||||
</div> */}
|
||||
{isAuthenticated ? (
|
||||
<div className="dropdown dropdown-end">
|
||||
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img src="https://us-tuna-sounds-images.voicemod.net/f322631f-689a-43ac-81ab-17a70f27c443-1692187175560.png" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png" />
|
||||
</div>
|
||||
</label>
|
||||
<ul
|
||||
|
||||
Loading…
Reference in New Issue
Block a user