From 074aeb70bc64fbdf8a1e61bafd43904fe9ab00e7 Mon Sep 17 00:00:00 2001 From: Wissarut Kanasub Date: Mon, 6 Nov 2023 11:08:44 +0700 Subject: [PATCH 1/7] Calander component and branch --- frontend/package.json | 4 ++ frontend/pnpm-lock.yaml | 59 +++++++++++++++++++ frontend/src/components/calendar/calendar.jsx | 28 +++++++++ 3 files changed, 91 insertions(+) create mode 100644 frontend/src/components/calendar/calendar.jsx diff --git a/frontend/package.json b/frontend/package.json index 793cfe0..1a78f51 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,10 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@fullcalendar/daygrid": "^6.1.9", + "@fullcalendar/interaction": "^6.1.9", + "@fullcalendar/react": "^6.1.9", + "@fullcalendar/timegrid": "^6.1.9", "@mui/icons-material": "^5.14.15", "@mui/material": "^5.14.15", "@mui/system": "^5.14.15", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 67325cd..271029a 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -11,6 +11,18 @@ dependencies: '@emotion/styled': specifier: ^11.11.0 version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@fullcalendar/daygrid': + specifier: ^6.1.9 + version: 6.1.9(@fullcalendar/core@6.1.9) + '@fullcalendar/interaction': + specifier: ^6.1.9 + version: 6.1.9(@fullcalendar/core@6.1.9) + '@fullcalendar/react': + specifier: ^6.1.9 + version: 6.1.9(@fullcalendar/core@6.1.9)(react-dom@18.2.0)(react@18.2.0) + '@fullcalendar/timegrid': + specifier: ^6.1.9 + version: 6.1.9(@fullcalendar/core@6.1.9) '@mui/icons-material': specifier: ^5.14.15 version: 5.14.15(@mui/material@5.14.15)(@types/react@18.2.33)(react@18.2.0) @@ -728,6 +740,49 @@ packages: resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} dev: false + /@fullcalendar/core@6.1.9: + resolution: {integrity: sha512-eeG+z9BWerdsU9Ac6j16rpYpPnE0wxtnEHiHrh/u/ADbGTR3hCOjCD9PxQOfhOTHbWOVs7JQunGcksSPu5WZBQ==} + dependencies: + preact: 10.12.1 + dev: false + + /@fullcalendar/daygrid@6.1.9(@fullcalendar/core@6.1.9): + resolution: {integrity: sha512-o/6joH/7lmVHXAkbaa/tUbzWYnGp/LgfdiFyYPkqQbjKEeivNZWF1WhHqFbhx0zbFONSHtrvkjY2bjr+Ef2quQ==} + peerDependencies: + '@fullcalendar/core': ~6.1.9 + dependencies: + '@fullcalendar/core': 6.1.9 + dev: false + + /@fullcalendar/interaction@6.1.9(@fullcalendar/core@6.1.9): + resolution: {integrity: sha512-I3FGnv0kKZpIwujg3HllbKrciNjTqeTYy3oJG226oAn7lV6wnrrDYMmuGmA0jPJAGN46HKrQqKN7ItxQRDec4Q==} + peerDependencies: + '@fullcalendar/core': ~6.1.9 + dependencies: + '@fullcalendar/core': 6.1.9 + dev: false + + /@fullcalendar/react@6.1.9(@fullcalendar/core@6.1.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ioxu0V++pYz2u/N1LL1V8DkMyiKGRun0gMAll2tQz3Kzi3r9pTwncGKRb1zO8h0e+TrInU08ywk/l5lBwp7eog==} + peerDependencies: + '@fullcalendar/core': ~6.1.9 + react: ^16.7.0 || ^17 || ^18 + react-dom: ^16.7.0 || ^17 || ^18 + dependencies: + '@fullcalendar/core': 6.1.9 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@fullcalendar/timegrid@6.1.9(@fullcalendar/core@6.1.9): + resolution: {integrity: sha512-le7UV05wVE1Trdr054kgJXTwa+A1pEI8nlCBnPWdcyrL+dTLoPvQ4AWEVCnV7So+4zRYaCqnqGXfCJsj0RQa0g==} + peerDependencies: + '@fullcalendar/core': ~6.1.9 + dependencies: + '@fullcalendar/core': 6.1.9 + '@fullcalendar/daygrid': 6.1.9(@fullcalendar/core@6.1.9) + dev: false + /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -2779,6 +2834,10 @@ packages: source-map-js: 1.0.2 dev: true + /preact@10.12.1: + resolution: {integrity: sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==} + dev: false + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} diff --git a/frontend/src/components/calendar/calendar.jsx b/frontend/src/components/calendar/calendar.jsx new file mode 100644 index 0000000..00cdc9c --- /dev/null +++ b/frontend/src/components/calendar/calendar.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import FullCalendar from '@fullcalendar/react'; +import dayGridPlugin from '@fullcalendar/daygrid'; +import timeGridPlugin from '@fullcalendar/timegrid'; + +const Calendar = () => { + return ( +
+ +
+ ); +}; + +export default Calendar; From 568f739b559522cc34d9d101025f4a9433974492 Mon Sep 17 00:00:00 2001 From: Wissarut Kanasub Date: Mon, 6 Nov 2023 13:02:30 +0700 Subject: [PATCH 2/7] Calendar page adding --- frontend/src/components/calendar/calendar.jsx | 2 +- frontend/src/components/calendar/calendarPage.jsx | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/calendar/calendarPage.jsx diff --git a/frontend/src/components/calendar/calendar.jsx b/frontend/src/components/calendar/calendar.jsx index 00cdc9c..2c6dbf7 100644 --- a/frontend/src/components/calendar/calendar.jsx +++ b/frontend/src/components/calendar/calendar.jsx @@ -12,7 +12,7 @@ const Calendar = () => { events={[ { title: 'Event 1', date: '2023-11-10' }, { title: 'Event 2', date: '2023-11-15' }, - // Add more events as needed + { title: 'Event 2', date: '2023-11-15' }, ]} headerToolbar={{ start: 'prev,next', diff --git a/frontend/src/components/calendar/calendarPage.jsx b/frontend/src/components/calendar/calendarPage.jsx new file mode 100644 index 0000000..7b5dbd7 --- /dev/null +++ b/frontend/src/components/calendar/calendarPage.jsx @@ -0,0 +1,11 @@ +import React from 'react' + +function calendarPage() { + return ( +
+ +
+ ) +} + +export default calendarPage From 4139f9be482aa36ef01c85e3c200f2dd3462f7af Mon Sep 17 00:00:00 2001 From: sosokker Date: Mon, 6 Nov 2023 20:35:44 +0700 Subject: [PATCH 3/7] Rename axiosapi to AuthenticationApi --- frontend/src/api/{axiosapi.jsx => AuthenticationApi.jsx} | 0 frontend/src/components/Nav/Navbar.jsx | 2 +- frontend/src/components/authentication/LoginPage.jsx | 2 +- frontend/src/components/authentication/SignUpPage.jsx | 2 +- frontend/src/components/testAuth.jsx | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename frontend/src/api/{axiosapi.jsx => AuthenticationApi.jsx} (100%) diff --git a/frontend/src/api/axiosapi.jsx b/frontend/src/api/AuthenticationApi.jsx similarity index 100% rename from frontend/src/api/axiosapi.jsx rename to frontend/src/api/AuthenticationApi.jsx diff --git a/frontend/src/components/Nav/Navbar.jsx b/frontend/src/components/Nav/Navbar.jsx index f88d821..5fee6cf 100644 --- a/frontend/src/components/Nav/Navbar.jsx +++ b/frontend/src/components/Nav/Navbar.jsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Link, useNavigate } from 'react-router-dom'; import IsAuthenticated from '../authentication/IsAuthenticated'; -import axiosapi from '../../api/axiosapi'; +import axiosapi from '../../api/AuthenticationApi'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Toolbar from '@mui/material/Toolbar'; diff --git a/frontend/src/components/authentication/LoginPage.jsx b/frontend/src/components/authentication/LoginPage.jsx index 242a9f1..b28e274 100644 --- a/frontend/src/components/authentication/LoginPage.jsx +++ b/frontend/src/components/authentication/LoginPage.jsx @@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom"; import { useGoogleLogin } from "@react-oauth/google" import refreshAccessToken from './refreshAcesstoken'; -import axiosapi from '../../api/axiosapi'; +import axiosapi from '../../api/AuthenticationApi'; function LoginPage() { const Navigate = useNavigate(); diff --git a/frontend/src/components/authentication/SignUpPage.jsx b/frontend/src/components/authentication/SignUpPage.jsx index 7739016..2712f97 100644 --- a/frontend/src/components/authentication/SignUpPage.jsx +++ b/frontend/src/components/authentication/SignUpPage.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import axiosapi from '../../api/axiosapi'; +import axiosapi from '../../api/AuthenticationApi'; import Avatar from '@mui/material/Avatar'; import Button from '@mui/material/Button'; diff --git a/frontend/src/components/testAuth.jsx b/frontend/src/components/testAuth.jsx index 9a822c7..abd7ba1 100644 --- a/frontend/src/components/testAuth.jsx +++ b/frontend/src/components/testAuth.jsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import axiosapi from '../api/axiosapi'; +import axiosapi from '../api/AuthenticationApi'; import { Button } from '@mui/material'; import { useNavigate } from 'react-router-dom'; From a403e45f9fc9f0ca2fd41a49ed5880bf4f00fa58 Mon Sep 17 00:00:00 2001 From: sosokker Date: Tue, 7 Nov 2023 03:23:20 +0700 Subject: [PATCH 4/7] Use ModelViewset for Todo and Add some fields before validate --- backend/tasks/api.py | 4 ++++ backend/tasks/tasks/views.py | 37 ++++++++---------------------------- backend/tasks/urls.py | 14 +++++++------- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/backend/tasks/api.py b/backend/tasks/api.py index 5352f9a..7669d76 100644 --- a/backend/tasks/api.py +++ b/backend/tasks/api.py @@ -31,6 +31,10 @@ class GoogleCalendarEventViewset(viewsets.ViewSet): for event in events.get('items', []): if event.get('recurringEventId'): continue + event['start_datetime'] = event.get('start').get('dateTime') + event['end_datetime'] = event.get('end').get('dateTime') + event.pop('start') + event.pop('end') try: task = Todo.objects.get(google_calendar_id=event['id']) serializer = TodoUpdateSerializer(instance=task, data=event) diff --git a/backend/tasks/tasks/views.py b/backend/tasks/tasks/views.py index 4077315..d884bbe 100644 --- a/backend/tasks/tasks/views.py +++ b/backend/tasks/tasks/views.py @@ -1,37 +1,16 @@ -from rest_framework import status -from rest_framework.response import Response -from rest_framework.generics import CreateAPIView, RetrieveAPIView, RetrieveUpdateAPIView, DestroyAPIView +from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated -from ..models import Todo +from tasks.models import Todo from .serializers import TaskCreateSerializer, TaskGeneralSerializer -class TaskCreateView(CreateAPIView): - queryset = Todo.objects.all() - serializer_class = TaskCreateSerializer - permission_classes = [IsAuthenticated] - def create(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) - - if serializer.is_valid(): - self.perform_create(serializer) - return Response(serializer.data, status=status.HTTP_201_CREATED) - - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - - -class TaskRetrieveView(RetrieveAPIView): +class TodoViewSet(viewsets.ModelViewSet): queryset = Todo.objects.all() serializer_class = TaskGeneralSerializer permission_classes = [IsAuthenticated] - -class TaskUpdateView(RetrieveUpdateAPIView): - queryset = Todo.objects.all() - serializer_class = TaskGeneralSerializer - permission_classes = [IsAuthenticated] - - -class TaskDeleteView(DestroyAPIView): - queryset = Todo.objects.all() - permission_classes = [IsAuthenticated] \ No newline at end of file + def get_serializer_class(self): + # Can't add ManytoMany at creation time (Tags) + if self.action == 'create': + return TaskCreateSerializer + return TaskGeneralSerializer \ No newline at end of file diff --git a/backend/tasks/urls.py b/backend/tasks/urls.py index c04bd68..b44ddd9 100644 --- a/backend/tasks/urls.py +++ b/backend/tasks/urls.py @@ -1,17 +1,17 @@ from django.urls import path, include + from rest_framework.routers import DefaultRouter -from .api import GoogleCalendarEventViewset -from .tasks.views import TaskCreateView, TaskRetrieveView, TaskUpdateView, TaskDeleteView -from .misc.views import TagViewSet + +from tasks.api import GoogleCalendarEventViewset +from tasks.tasks.views import TodoViewSet +from tasks.misc.views import TagViewSet + router = DefaultRouter() +router.register(r'todo', TodoViewSet) router.register(r'tags', TagViewSet) router.register(r'calendar-events', GoogleCalendarEventViewset, basename='calendar-events') urlpatterns = [ path('', include(router.urls)), - path('tasks/create/', TaskCreateView.as_view(), name="add-task"), - path('tasks//', TaskRetrieveView.as_view(), name='retrieve-task'), - path('tasks//update/', TaskUpdateView.as_view(), name='update-task'), - path('tasks//delete/', TaskDeleteView.as_view(), name='delete-task'), ] \ No newline at end of file From 02e76f88c58c37828ec4e552d3e274b8ecd0754e Mon Sep 17 00:00:00 2001 From: sosokker Date: Tue, 7 Nov 2023 03:24:58 +0700 Subject: [PATCH 5/7] Fetch event data from api and show on fullcalendar --- frontend/package.json | 1 + frontend/pnpm-lock.yaml | 3 + frontend/src/App.jsx | 4 +- frontend/src/api/TaskApi.jsx | 23 +++ .../components/calendar/TaskDataHandler.jsx | 42 +++++ frontend/src/components/calendar/calendar.jsx | 147 +++++++++++++++--- .../src/components/calendar/calendarPage.jsx | 11 -- frontend/src/components/calendar/index.css | 55 +++++++ 8 files changed, 250 insertions(+), 36 deletions(-) create mode 100644 frontend/src/api/TaskApi.jsx create mode 100644 frontend/src/components/calendar/TaskDataHandler.jsx delete mode 100644 frontend/src/components/calendar/calendarPage.jsx create mode 100644 frontend/src/components/calendar/index.css diff --git a/frontend/package.json b/frontend/package.json index 1a78f51..a7f5f04 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@fullcalendar/core": "^6.1.9", "@fullcalendar/daygrid": "^6.1.9", "@fullcalendar/interaction": "^6.1.9", "@fullcalendar/react": "^6.1.9", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 271029a..a23ba2c 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: '@emotion/styled': specifier: ^11.11.0 version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.33)(react@18.2.0) + '@fullcalendar/core': + specifier: ^6.1.9 + version: 6.1.9 '@fullcalendar/daygrid': specifier: ^6.1.9 version: 6.1.9(@fullcalendar/core@6.1.9) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e9bb13b..cfa3a5a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -6,7 +6,8 @@ import LoginPage from './components/authentication/LoginPage'; import SignUpPage from './components/authentication/SignUpPage'; import NavBar from './components/Nav/Navbar'; import Home from './components/Home'; -import ProfileUpdate from './components/ProfileUpdatePage' +import ProfileUpdate from './components/ProfileUpdatePage'; +import Calendar from './components/calendar/calendar'; const App = () => { return ( @@ -19,6 +20,7 @@ const App = () => { }/> }/> }/> + }/> diff --git a/frontend/src/api/TaskApi.jsx b/frontend/src/api/TaskApi.jsx new file mode 100644 index 0000000..e56662b --- /dev/null +++ b/frontend/src/api/TaskApi.jsx @@ -0,0 +1,23 @@ +import axios from 'axios'; + +// Create an Axios instance with common configurations +const axiosInstance = axios.create({ + baseURL: 'http://127.0.0.1:8000/api/', + timeout: 5000, + headers: { + 'Authorization': "Bearer " + localStorage.getItem('access_token'), + 'Content-Type': 'application/json', + 'accept': 'application/json', + } +}); + +export const fetchTodoTasks = () => { + return axiosInstance + .get('todo/') + .then((response) => { + return response.data; + }) + .catch(error => { + throw error; + }); +}; \ No newline at end of file diff --git a/frontend/src/components/calendar/TaskDataHandler.jsx b/frontend/src/components/calendar/TaskDataHandler.jsx new file mode 100644 index 0000000..3c123e9 --- /dev/null +++ b/frontend/src/components/calendar/TaskDataHandler.jsx @@ -0,0 +1,42 @@ +import { fetchTodoTasks } from '../../api/TaskApi'; + +let eventGuid = 0 + +// function getDateAndTime(dateString) { +// const dateObject = new Date(dateString); + +// const year = dateObject.getFullYear(); +// const month = (dateObject.getMonth() + 1).toString().padStart(2, '0'); +// const day = dateObject.getDate().toString().padStart(2, '0'); +// const dateFormatted = `${year}-${month}-${day}`; + +// const hours = dateObject.getUTCHours().toString().padStart(2, '0'); +// const minutes = dateObject.getUTCMinutes().toString().padStart(2, '0'); +// const seconds = dateObject.getUTCSeconds().toString().padStart(2, '0'); +// const timeFormatted = `T${hours}:${minutes}:${seconds}`; + +// return dateFormatted + timeFormatted; +// } + +const mapResponseToEvents = (response) => { + return response.map(item => ({ + id: createEventId(), + title: item.title, + start: item.start_event, + end: item.end_event, + })); +} + +export async function getEvents() { + try { + const response = await fetchTodoTasks(); + return mapResponseToEvents(response); + } catch (error) { + console.error(error); + return []; + } +} + +export function createEventId() { + return String(eventGuid++); +} \ No newline at end of file diff --git a/frontend/src/components/calendar/calendar.jsx b/frontend/src/components/calendar/calendar.jsx index 2c6dbf7..443d4bc 100644 --- a/frontend/src/components/calendar/calendar.jsx +++ b/frontend/src/components/calendar/calendar.jsx @@ -1,28 +1,127 @@ -import React from 'react'; -import FullCalendar from '@fullcalendar/react'; -import dayGridPlugin from '@fullcalendar/daygrid'; -import timeGridPlugin from '@fullcalendar/timegrid'; +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 './index.css' -const Calendar = () => { +export default class Calendar extends React.Component { + state = { + weekendsVisible: true, + currentEvents: [], + }; + + render() { + return ( +
+ {this.renderSidebar()} +
+ +
+
+ ); + } + + renderSidebar() { + return ( +
+
+

Instructions

+
    +
  • Select dates and you will be prompted to create a new event
  • +
  • Drag, drop, and resize events
  • +
  • Click an event to delete it
  • +
+
+
+ +
+
+

All Events ({this.state.currentEvents.length})

+
    {this.state.currentEvents.map(renderSidebarEvent)}
+
+
+ ); + } + + handleWeekendsToggle = () => { + this.setState({ + weekendsVisible: !this.state.weekendsVisible, + }); + }; + + handleDateSelect = selectInfo => { + let title = prompt("Please enter a new title for your event"); + let calendarApi = selectInfo.view.calendar; + + calendarApi.unselect(); // clear date selection + + if (title) { + calendarApi.addEvent({ + id: createEventId(), + title, + start: selectInfo.startStr, + end: selectInfo.endStr, + allDay: selectInfo.allDay, + }); + } + }; + + handleEventClick = clickInfo => { + if (confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) { + clickInfo.event.remove(); + } + }; + + handleEvents = events => { + this.setState({ + currentEvents: events, + }); + }; +} + +function renderEventContent(eventInfo) { return ( -
- -
+ <> + {eventInfo.timeText} + {eventInfo.event.title} + ); -}; +} -export default Calendar; +function renderSidebarEvent(event) { + return ( +
  • + {formatDate(event.start, { year: "numeric", month: "short", day: "numeric" })} + {event.title} +
  • + ); +} diff --git a/frontend/src/components/calendar/calendarPage.jsx b/frontend/src/components/calendar/calendarPage.jsx deleted file mode 100644 index 7b5dbd7..0000000 --- a/frontend/src/components/calendar/calendarPage.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -function calendarPage() { - return ( -
    - -
    - ) -} - -export default calendarPage diff --git a/frontend/src/components/calendar/index.css b/frontend/src/components/calendar/index.css new file mode 100644 index 0000000..e5086bd --- /dev/null +++ b/frontend/src/components/calendar/index.css @@ -0,0 +1,55 @@ + +html, +body, +body > div { /* the react root */ + margin: 0; + padding: 0; + height: 100%; +} + +h2 { + margin: 0; + font-size: 16px; +} + +ul { + margin: 0; + padding: 0 0 0 1.5em; +} + +li { + margin: 1.5em 0; + padding: 0; +} + +b { /* used for event dates/times */ + margin-right: 3px; +} + +.demo-app { + display: flex; + min-height: 100%; + font-family: Arial, Helvetica Neue, Helvetica, sans-serif; + font-size: 14px; +} + +.demo-app-sidebar { + width: 300px; + line-height: 1.5; + background: #eaf9ff; + border-right: 1px solid #d3e2e8; +} + +.demo-app-sidebar-section { + padding: 2em; +} + +.demo-app-main { + flex-grow: 1; + padding: 3em; +} + +.fc { /* the calendar root */ + max-width: 1100px; + margin: 0 auto; +} From 5e0b4012f5f9f085503c67ba41d145b5d49648a8 Mon Sep 17 00:00:00 2001 From: sosokker Date: Tue, 7 Nov 2023 03:32:24 +0700 Subject: [PATCH 6/7] rename nav folder --- frontend/src/App.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index cfa3a5a..67360d3 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -4,7 +4,7 @@ import { BrowserRouter, Route, Routes, Link } from 'react-router-dom'; import TestAuth from './components/testAuth'; import LoginPage from './components/authentication/LoginPage'; import SignUpPage from './components/authentication/SignUpPage'; -import NavBar from './components/Nav/Navbar'; +import NavBar from './components/nav/Navbar'; import Home from './components/Home'; import ProfileUpdate from './components/ProfileUpdatePage'; import Calendar from './components/calendar/calendar'; From 67a30ce114f02ac1d2e73870da167ca0e1623e88 Mon Sep 17 00:00:00 2001 From: sosokker Date: Tue, 7 Nov 2023 03:38:51 +0700 Subject: [PATCH 7/7] Update test to match Todoviewset --- backend/tasks/tests/test_todo_creation.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/backend/tasks/tests/test_todo_creation.py b/backend/tasks/tests/test_todo_creation.py index 0852fbe..9912126 100644 --- a/backend/tasks/tests/test_todo_creation.py +++ b/backend/tasks/tests/test_todo_creation.py @@ -1,21 +1,18 @@ from datetime import datetime, timedelta - from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase - from tasks.tests.utils import create_test_user, login_user -from ..models import Todo +from tasks.models import Todo -class TodoCreateViewTests(APITestCase): + +class TodoViewSetTests(APITestCase): def setUp(self): - self.user = create_test_user() self.client = login_user(self.user) - self.url = reverse("add-task") + self.url = reverse("todo-list") self.due_date = datetime.now() + timedelta(days=5) - def test_create_valid_todo(self): """ Test creating a valid task using the API. @@ -28,7 +25,7 @@ class TodoCreateViewTests(APITestCase): 'priority': 1, 'difficulty': 1, 'user': self.user.id, - 'end_event': self.due_date, + 'end_event': self.due_date.strftime('%Y-%m-%dT%H:%M:%S'), } response = self.client.post(self.url, data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -42,7 +39,6 @@ class TodoCreateViewTests(APITestCase): data = { 'type': 'invalid', # Invalid task type } - response = self.client.post(self.url, data, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(Todo.objects.count(), 0) # No task should be created @@ -55,7 +51,6 @@ class TodoCreateViewTests(APITestCase): 'title': 'Incomplete Task', 'type': 'habit', } - response = self.client.post(self.url, data, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(Todo.objects.count(), 0) # No task should be created @@ -71,9 +66,8 @@ class TodoCreateViewTests(APITestCase): 'priority': 1, 'difficulty': 1, 'user': 999, # Invalid user ID - 'end_event': self.due_date, + 'end_event': self.due_date.strftime('%Y-%m-%dT%H:%M:%S'), } - response = self.client.post(self.url, data, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(Todo.objects.count(), 0) # No task should be created