mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 05:54: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 import viewsets
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
from boards.models import Board, ListBoard
|
from boards.models import Board, ListBoard
|
||||||
from boards.serializers import BoardSerializer, ListBoardSerializer
|
from boards.serializers import BoardSerializer, ListBoardSerializer
|
||||||
|
|
||||||
class BoardViewSet(viewsets.ModelViewSet):
|
class BoardViewSet(viewsets.ModelViewSet):
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
queryset = Board.objects.all()
|
queryset = Board.objects.all()
|
||||||
serializer_class = BoardSerializer
|
serializer_class = BoardSerializer
|
||||||
http_method_names = ['get']
|
http_method_names = ['get']
|
||||||
@ -16,6 +18,7 @@ class BoardViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
|
|
||||||
class ListBoardViewSet(viewsets.ModelViewSet):
|
class ListBoardViewSet(viewsets.ModelViewSet):
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
serializer_class = ListBoardSerializer
|
serializer_class = ListBoardSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { formatDate } from "@fullcalendar/core";
|
import { formatDate } from "@fullcalendar/core";
|
||||||
import FullCalendar from "@fullcalendar/react";
|
import FullCalendar from "@fullcalendar/react";
|
||||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
import interactionPlugin from "@fullcalendar/interaction";
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
import { getEvents, createEventId } from "./TaskDataHandler";
|
import { getEvents, createEventId } from "./TaskDataHandler";
|
||||||
import { axiosInstance } from "src/api/AxiosConfig";
|
|
||||||
|
|
||||||
export class Calendar extends React.Component {
|
export class Calendar extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
@ -62,10 +61,13 @@ export class Calendar extends React.Component {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={this.state.weekendsVisible}
|
checked={this.state.weekendsVisible}
|
||||||
onChange={this.handleWeekendsToggle}
|
onChange={this.handleWeekendsToggle}
|
||||||
className="mr-2"
|
className="mr-2 mb-4"
|
||||||
/>
|
/>
|
||||||
Toggle weekends
|
Toggle weekends
|
||||||
</label>
|
</label>
|
||||||
|
<button className="btn btn-info" onClick={() => alert("Commit soon🥺")}>
|
||||||
|
Load Data from Google
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Show all task */}
|
{/* Show all task */}
|
||||||
|
|||||||
@ -224,30 +224,24 @@ export function KanbanBoard() {
|
|||||||
|
|
||||||
const isActiveATask = active.data.current?.type === "Task";
|
const isActiveATask = active.data.current?.type === "Task";
|
||||||
const isOverAColumn = over.data.current?.type === "Column";
|
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
|
// Move tasks between columns and update columnId
|
||||||
if (isActiveATask && isOverAColumn) {
|
if (isActiveATask && isOverAColumn) {
|
||||||
setTasks((tasks) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
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
|
// API call to update task's columnId
|
||||||
axiosInstance
|
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) => {})
|
.then((response) => {})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Error updating task columnId:", 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
|
// Handle the drag-over event
|
||||||
function onDragOver(event) {
|
function onDragOver(event) {
|
||||||
const { active, over } = event;
|
const { active, over } = event;
|
||||||
@ -284,7 +286,16 @@ export function KanbanBoard() {
|
|||||||
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
tasks[activeIndex].columnId = tasks[overIndex].columnId;
|
||||||
return arrayMove(tasks, activeIndex, overIndex - 1);
|
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);
|
return arrayMove(tasks, activeIndex, overIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -294,7 +305,16 @@ export function KanbanBoard() {
|
|||||||
if (isActiveATask && isOverAColumn && tasks.some((task) => task.columnId !== overId)) {
|
if (isActiveATask && isOverAColumn && tasks.some((task) => task.columnId !== overId)) {
|
||||||
setTasks((tasks) => {
|
setTasks((tasks) => {
|
||||||
const activeIndex = tasks.findIndex((t) => t.id === activeId);
|
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;
|
tasks[activeIndex].columnId = overId;
|
||||||
return arrayMove(tasks, activeIndex, activeIndex);
|
return arrayMove(tasks, activeIndex, activeIndex);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -19,12 +19,12 @@ export const KanbanPage = () => {
|
|||||||
onClick={() => handleTabClick("kanban")}>
|
onClick={() => handleTabClick("kanban")}>
|
||||||
Kanban
|
Kanban
|
||||||
</a>
|
</a>
|
||||||
<a
|
{/* <a
|
||||||
id="table"
|
id="table"
|
||||||
className={`tab ${activeTab === "table" ? "tab-active" : ""}`}
|
className={`tab ${activeTab === "table" ? "tab-active" : ""}`}
|
||||||
onClick={() => handleTabClick("table")}>
|
onClick={() => handleTabClick("table")}>
|
||||||
Table
|
Table
|
||||||
</a>
|
</a> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,9 +9,9 @@ const menuItems = [
|
|||||||
{ id: 0, path: "/", icon: <AiOutlineHome /> },
|
{ id: 0, path: "/", icon: <AiOutlineHome /> },
|
||||||
{ id: 1, path: "/tasks", icon: <AiOutlineUnorderedList /> },
|
{ id: 1, path: "/tasks", icon: <AiOutlineUnorderedList /> },
|
||||||
{ id: 2, path: "/calendar", icon: <AiOutlineSchedule /> },
|
{ id: 2, path: "/calendar", icon: <AiOutlineSchedule /> },
|
||||||
{ id: 3, path: "/settings", icon: <IoSettingsOutline /> },
|
{ id: 3, path: "/priority", icon: <PiStepsDuotone /> },
|
||||||
{ id: 4, path: "/priority", icon: <PiStepsDuotone /> },
|
|
||||||
];
|
];
|
||||||
|
// { id: 3, path: "/settings", icon: <IoSettingsOutline /> },
|
||||||
|
|
||||||
export const SideNav = () => {
|
export const SideNav = () => {
|
||||||
const [selected, setSelected] = useState(0);
|
const [selected, setSelected] = useState(0);
|
||||||
|
|||||||
@ -25,14 +25,14 @@ export function NavBar() {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-none gap-2">
|
<div className="flex-none gap-2">
|
||||||
<div className="form-control">
|
{/* <div className="form-control">
|
||||||
<input type="text" placeholder="Search" className="input input-bordered w-24 md:w-auto" />
|
<button className="btn btn-success">Sync Data</button>
|
||||||
</div>
|
</div> */}
|
||||||
{isAuthenticated ? (
|
{isAuthenticated ? (
|
||||||
<div className="dropdown dropdown-end">
|
<div className="dropdown dropdown-end">
|
||||||
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
|
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
|
||||||
<div className="w-10 rounded-full">
|
<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>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<ul
|
<ul
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user