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

Export to Calendar (URL) #126

Merged
merged 84 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from 77 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
952e6cb
update tailwind & add forms
diogogmatos Aug 25, 2023
41d0d37
create settings & improvements
diogogmatos Aug 25, 2023
d1644ea
install tools
diogogmatos Aug 25, 2023
f4490df
add custom themes by year
diogogmatos Aug 25, 2023
581b86a
add design system colors
diogogmatos Aug 26, 2023
74bb965
add checked indicators to every collapse
diogogmatos Aug 26, 2023
3474f27
customize theme by subject
diogogmatos Aug 26, 2023
e8edbf4
bug fix
diogogmatos Aug 26, 2023
572e52e
close sidebar when theme is updated (mobile)
diogogmatos Aug 26, 2023
a4acc80
apply themes to schedule & improvements
diogogmatos Aug 26, 2023
b8d8447
bug fix
diogogmatos Aug 26, 2023
39d7d73
Add new features to README
diogogmatos Aug 31, 2023
0fad2c1
Format
diogogmatos Aug 31, 2023
6273c45
add color themes notification
diogogmatos Aug 31, 2023
490e4cc
format
diogogmatos Aug 31, 2023
c59c024
fix bg color of notifications
diogogmatos Aug 31, 2023
22f4cfb
install ics, update react, update next
diogogmatos Sep 4, 2023
4acda64
fix next13 compatibility issue
diogogmatos Sep 4, 2023
eb419cc
add export api
diogogmatos Sep 4, 2023
68b3922
updates
diogogmatos Sep 4, 2023
a3c60da
Merge branch 'master' into dm/ics
diogogmatos Sep 4, 2023
0332129
fix
diogogmatos Sep 4, 2023
fb5d173
add schedule compatibility
diogogmatos Sep 5, 2023
14e92a9
apply suggestions
diogogmatos Sep 5, 2023
343d816
add frontend
diogogmatos Sep 5, 2023
856d076
tweak
diogogmatos Sep 5, 2023
f2ef5fe
fix lint errors
diogogmatos Sep 5, 2023
1b858aa
format
diogogmatos Sep 5, 2023
7bc4070
refactor api
diogogmatos Sep 6, 2023
9118909
debug api netlify error
diogogmatos Sep 6, 2023
b1998aa
debug api netlify error
diogogmatos Sep 6, 2023
e92c778
debug api netlify error
diogogmatos Sep 6, 2023
47be600
debug api netlify error
diogogmatos Sep 6, 2023
ff0280a
bug fix
diogogmatos Sep 6, 2023
57ab87f
bug fix
diogogmatos Sep 6, 2023
00614be
bug fix
diogogmatos Sep 6, 2023
20292ef
timezone fix
diogogmatos Sep 6, 2023
3be5387
bug fix
diogogmatos Sep 6, 2023
f393bf9
debug timezone bug
diogogmatos Sep 6, 2023
8bb7066
bug fix
diogogmatos Sep 6, 2023
cadc1a2
bug fix
diogogmatos Sep 6, 2023
3a30265
update dependency version
diogogmatos Sep 6, 2023
51e6d9b
debug timezone bug
diogogmatos Sep 6, 2023
c1c049e
debug timezone bug
diogogmatos Sep 6, 2023
2057051
update netlify nextjs plugin
diogogmatos Sep 6, 2023
66e4f49
debug timezone bug
diogogmatos Sep 6, 2023
94f014b
debug timezone
diogogmatos Sep 6, 2023
6b64435
debug timezone
diogogmatos Sep 6, 2023
f8c6bd4
debug timezone
diogogmatos Sep 6, 2023
2308049
debug timezone
diogogmatos Sep 6, 2023
da6dd11
debug timezone
diogogmatos Sep 6, 2023
8e08ec1
debug timezone
diogogmatos Sep 6, 2023
0ef5026
install ical-generator
diogogmatos Sep 6, 2023
1db9e28
debug timezone
diogogmatos Sep 6, 2023
a9ee4fc
debug timezone
diogogmatos Sep 6, 2023
d2eea0e
remove ics package
diogogmatos Sep 6, 2023
90f8fb5
fix timezone bug
diogogmatos Sep 6, 2023
42146db
fix wrong import
diogogmatos Sep 6, 2023
483d1e5
debug bad request
diogogmatos Sep 7, 2023
b5229ad
fix bad request bug
diogogmatos Sep 7, 2023
632b151
all day events
diogogmatos Sep 7, 2023
c3d5f42
revert changes
diogogmatos Sep 7, 2023
f34b2eb
back
diogogmatos Sep 7, 2023
adac4d1
add timezone
diogogmatos Sep 7, 2023
afbb9aa
debug timezone
diogogmatos Sep 7, 2023
5e144ad
debug timezone
diogogmatos Sep 7, 2023
7cd7559
format
diogogmatos Sep 7, 2023
63a5450
set calendar timezone
diogogmatos Sep 7, 2023
319f3eb
improve all day events
diogogmatos Sep 7, 2023
86eb183
add urls to description
diogogmatos Sep 7, 2023
3d1f4ab
add dynamic domain with environment variables
diogogmatos Sep 7, 2023
b906cb9
finish frontend
diogogmatos Sep 7, 2023
241cd8e
fix character
diogogmatos Sep 7, 2023
b6ea9a6
add warning
diogogmatos Sep 7, 2023
88be34e
fix character
diogogmatos Sep 7, 2023
c84cbb3
filter events by academic year
diogogmatos Sep 7, 2023
c25ba77
Merge branch 'master' into dm/ics
diogogmatos Sep 7, 2023
d4d0606
add notification
diogogmatos Sep 7, 2023
ed0b722
add info to modal
diogogmatos Sep 7, 2023
f3f5589
Update notifications.json
diogogmatos Sep 7, 2023
e95cf2c
add margins to max height
diogogmatos Sep 9, 2023
7654c51
add api documentation
diogogmatos Sep 9, 2023
c9c19ca
fix paragraph
diogogmatos Sep 9, 2023
021998a
fix paragraph
diogogmatos Sep 9, 2023
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
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_DOMAIN=http://localhost:3000
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_DOMAIN=https://calendario.cesium.di.uminho.pt
2 changes: 1 addition & 1 deletion components/ActiveLink/ActiveLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const ActiveLink = ({
const className = asPath === rest.href ? activeClassName : "";

return (
<Link {...rest}>
<Link legacyBehavior {...rest}>
ruilopesm marked this conversation as resolved.
Show resolved Hide resolved
{cloneElement(children, {
className,
})}
Expand Down
311 changes: 311 additions & 0 deletions components/CalendarExportModal/CalendarExportModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
import { Modal, Box, Typography, Fade, Backdrop } from "@mui/material";

import { useState, useEffect } from "react";

import { Collapse } from "antd";

import { IFilterDTO } from "../../dtos";

type CalendarExportModalProps = {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
isHome: boolean;
filters: IFilterDTO[];
};

const CalendarExportModal = ({
isOpen,
setIsOpen,
isHome,
filters,
}: CalendarExportModalProps) => {
const [isCopied, setIsCopied] = useState<boolean>(false);
const [URL, setURL] = useState<string>("");

function generateURL(): string {
const domain = process.env.NEXT_PUBLIC_DOMAIN;
const baseURL: string =
domain + "/api/export/" + (isHome ? "events" : "schedule") + "?";

var queries: string = "";
if (isHome) {
const checkedEvents: number[] = JSON.parse(
localStorage.getItem("checked")
);

if (checkedEvents && checkedEvents.length > 0) {
const checkedEventsNames: string[] = checkedEvents.map((filterId) => {
return filters.find((f) => f.id === filterId).name;
});

queries = checkedEventsNames.join("&");
} else {
return "";
}
} else {
const checkedShifts: { id: number; shift: string }[] = JSON.parse(
localStorage.getItem("shifts")
);

const toString = (shift: { name: string; shift: string }) => {
return `${shift.name}=${shift.shift}`;
};

if (checkedShifts && checkedShifts.length > 0) {
const checkedShiftsNames: { name: string; shift: string }[] =
checkedShifts.map((shift) => {
return {
name: filters.find((f) => f.id === shift.id).name,
shift: shift.shift,
};
});

queries = `${checkedShiftsNames
.map((shift) => toString(shift))
.join("&")}`;
} else {
return "";
}
}

return baseURL + queries;
}

useEffect(() => {
setURL(generateURL());
});

function copyToClipboard() {
navigator.clipboard.writeText(URL);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 1000);
}

return (
<div>
<Modal
open={isOpen}
onClose={() => setIsOpen(false)}
closeAfterTransition
slots={{ backdrop: Backdrop }}
slotProps={{ backdrop: { timeout: 300 } }}
>
<Fade in={isOpen}>
<Box className="absolute left-1/2 top-1/2 h-fit max-h-full w-fit -translate-x-1/2 -translate-y-1/2 transform overflow-scroll rounded-3xl border bg-white p-6 text-center shadow-xl">
<Typography
id="modal-modal-title"
className="select-none place-content-center items-center text-gray-900"
variant="h6"
component="h2"
>
Export by URL <i className="bi bi-link-45deg"></i>
</Typography>
{URL === "" ? (
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
<div className="text-gray-900">
<div className="text-center">
<i className="bi bi-exclamation-circle-fill text-error"></i>{" "}
{isHome
? "Select at least one subject."
: "Select at least one shift."}
</div>
</div>
</Typography>
) : (
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
<div className="space-y-4">
<div>
<div className="w- mt-2 flex rounded-xl shadow-sm">
<div className="relative flex flex-grow focus-within:z-10">
<div className="whitespace-nowrap rounded-none rounded-l-xl border-0 px-3 py-1.5 text-left text-gray-900 ring-1 ring-inset ring-gray-300 sm:text-sm sm:leading-6">
<div className="w-56 overflow-y-hidden overflow-x-scroll pb-2 lg:w-80">
{URL}
</div>
</div>
</div>
<button
type="button"
title={isCopied ? "Copied" : "Copy"}
className="text-md relative -ml-px inline-flex w-full items-center gap-x-1.5 rounded-r-xl px-3 py-2 font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 transition-colors hover:bg-gray-100"
onClick={copyToClipboard}
>
{isCopied ? (
<i className="bi bi-clipboard-check-fill text-cesium-900"></i>
) : (
<i className="bi bi-clipboard"></i>
)}
</button>
</div>
</div>

<Collapse className="w-72 rounded-xl border-gray-300 bg-white text-left shadow-sm lg:w-96">
<Collapse.Panel header="How does it work?" key="1">
<div className="text-justify">
The URL above allows you to{" "}
<a className="font-medium">subscribe</a> to your active{" "}
{isHome ? "events" : "schedule"} in Calendarium, using
your favorite calendar app.
<p />
This means that you will be able to see your{" "}
{isHome ? "events" : "schedule"} in your calendar app,
and add event notifications, change colors and make
other customizations.
<p />
Your {isHome ? "events" : "schedule"} will be
automatically synced with Calendarium.
<p />
<div className="rounded-lg bg-warning/20 p-3">
<i className="bi bi-exclamation-triangle-fill text-warning"></i>{" "}
If you make any changes to your{" "}
{isHome ? "events" : "schedule"} in Calendarium, you
{"'"}ll need to{" "}
<a className="font-medium">
re-export and re-subscribe to the calendar
</a>
.
</div>
</div>
</Collapse.Panel>
</Collapse>

<Collapse
accordion
className="w-72 rounded-xl border-gray-300 bg-white text-left shadow-sm lg:w-96"
>
<Collapse.Panel header="Google Calendar" key="1">
<div className="text-gray-900">
<text className="font-bold">1.</text> On your computer,
open{" "}
<a
href="https://calendar.google.com"
className="text-blue-500"
>
Google Calendar{" "}
<i className="bi bi-box-arrow-up-right"></i>
</a>
.
<p />
<text className="font-bold">2.</text> On the left, next
to {'"Other calendars"'}, click Add{" "}
<i className="bi bi-plus"></i>{" "}
<i className="bi bi-chevron-right"></i>{" "}
<text className="font-medium">From URL</text>.
<p />
<text className="font-bold">3.</text> Enter the above
calendar
{"'"}s address.
<p />
<text className="font-bold">4.</text> Click{" "}
<a className="font-medium">Add calendar</a>. The
calendar appears on the left, under{" "}
{'"Other calendars"'}.
<p />
<a
href="https://support.google.com/calendar/answer/37100?hl=en&co=GENIE.Platform=Desktop"
className="text-blue-500"
>
Know more <i className="bi bi-box-arrow-up-right"></i>
</a>
</div>
</Collapse.Panel>
<Collapse.Panel header="Apple Calendar" key="2">
<div className="text-gray-900">
<text className="font-bold">1.</text> On your iPhone,
open <a className="font-medium">Calendar</a>.
<p />
<text className="font-bold">2.</text> On the bottom,
click {'"Calendars"'}.
<p />
<text className="font-bold">3.</text> On the bottom
left, click {'"Add Calendar"'}{" "}
<i className="bi bi-chevron-right"></i>{" "}
<a className="font-medium">Add Subscription Calendar</a>
.
<p />
<text className="font-bold">3.</text> Enter the above
calendar
{"'"}s address.
<p />
<text className="font-bold">4.</text> Click{" "}
<a className="font-medium">Subscribe</a>. The calendar
appears under {'"Calendars"'}.
<p />
<i className="bi bi-lightbulb"></i> You can also{" "}
<a
href="https://support.apple.com/guide/calendar/subscribe-to-calendars-icl1022/mac"
className="text-blue-500"
>
use your Mac{" "}
<i className="bi bi-box-arrow-up-right"></i>
</a>
</div>
</Collapse.Panel>
<Collapse.Panel header="Outlook Calendar" key="3">
<div className="text-gray-900">
<text className="font-bold">1.</text> Sign in to{" "}
<a
href="https://go.microsoft.com/fwlink/p/?linkid=843379"
className="text-blue-500"
>
Outlook.com{" "}
<i className="bi bi-box-arrow-up-right"></i>
</a>
<p />
<text className="font-bold">2.</text> At the bottom of
the page, select the calendar icon.
<p />
<text className="font-bold">3.</text> In the navigation
pane, select <a className="font-medium">Add Calendar</a>
.
<p />
<text className="font-bold">4.</text> Select{" "}
<a className="font-medium">Subscribe from web</a>.
<p />
<text className="font-bold">5.</text> Enter the above
calendar{"'"}s address.
<p />
<text className="font-bold">6.</text> Select{" "}
<a className="font-medium">Import</a>.
<p />
<a
href="https://support.microsoft.com/en-gb/office/import-or-subscribe-to-a-calendar-in-outlook-com-cff1429c-5af6-41ec-a5b4-74f2c278e98c"
className="text-blue-500"
>
Know more <i className="bi bi-box-arrow-up-right"></i>
</a>
</div>
</Collapse.Panel>
</Collapse>

<div className="cursor-pointer select-none text-sm text-gray-500">
{isHome ? (
<div title="To export your schedule please go to /schedule.">
<i className="bi bi-info-circle-fill"></i> Currently
exporting your visible{" "}
<a className="font-medium">events</a>
</div>
) : (
<div title="To export your events please go to the main page.">
<i className="bi bi-info-circle-fill"></i> Currently
exporting your <a className="font-medium">schedule</a>
</div>
)}
</div>

<div className="cursor-pointer select-none text-sm text-gray-500">
<i className="bi bi-lightbulb"></i> You can also{" "}
<a className="font-medium text-blue-400" href={URL}>
download as .ics file
</a>
</div>
</div>
</Typography>
)}
</Box>
</Fade>
</Modal>
</div>
);
};

export default CalendarExportModal;
1 change: 1 addition & 0 deletions components/CalendarExportModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./CalendarExportModal";
41 changes: 41 additions & 0 deletions components/ClearScheduleButton/ClearScheduleButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Popconfirm } from "antd";

const ClearScheduleButton = ({
isSettings,
clearSchedule,
}: {
isSettings: boolean;
clearSchedule: () => void;
}) => {
return (
<Popconfirm
title={isSettings ? "ERROR" : "Are you sure?"}
description={
isSettings
? "You can't clear your schedule while in settings."
: "This will remove all your classes."
}
onConfirm={() => clearSchedule()}
onCancel={() => {}}
okText="Ok"
cancelText={"Cancel"}
icon={
isSettings ? (
<i className="bi bi-exclamation-circle-fill text-error"></i>
) : (
<i className="bi bi-question-circle-fill text-warning"></i>
)
}
okButtonProps={{
className: `${isSettings ? "hidden" : "bg-blue-500"}`,
}}
cancelButtonProps={{ className: `${isSettings && "hidden"}` }}
>
<button className="mb-3 h-10 w-full rounded-2xl bg-highlight p-2 font-medium text-white shadow-md transition-shadow duration-300 hover:shadow-lg hover:shadow-highlight/40 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
Clear Schedule <i className="bi bi-stars"></i>
</button>
</Popconfirm>
);
};

export default ClearScheduleButton;
1 change: 1 addition & 0 deletions components/ClearScheduleButton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./ClearScheduleButton";
Loading