Skip to content
Snippets Groups Projects
Commit 738c09ec authored by Dorian Koch's avatar Dorian Koch
Browse files

ts: Fix import

parent 9fae76eb
Branches
No related tags found
No related merge requests found
...@@ -238,11 +238,43 @@ function UserField() { ...@@ -238,11 +238,43 @@ function UserField() {
); );
} }
function Search() {
const router = useRouter();
const [query, setQuery] = useState("");
const onSearchSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
let form = e.currentTarget;
let query = form.query.value;
if (query === "") return;
router.push("/search?q=" + encodeURIComponent(query));
};
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setQuery(e.target.value);
};
return (
<form role="search" className="d-flex" onSubmit={onSearchSubmit}>
<div className="input-group">
<input
className="form-control"
type="text"
name="query"
placeholder="Suche"
value={query}
onChange={onChange}
/>
<button className="btn btn-primary" type="submit">
<span className="bi bi-search"></span>
</button>
</div>
</form>
);
}
function NavBar() { function NavBar() {
const DEBUG = false; const DEBUG = false;
const togglerRef = useRef(null); const togglerRef = useRef(null);
const router = useRouter();
useEffect(() => { useEffect(() => {
// lazy load bootstrap collapse // lazy load bootstrap collapse
...@@ -294,14 +326,6 @@ function NavBar() { ...@@ -294,14 +326,6 @@ function NavBar() {
} }
}; };
const onSearchSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
let form = e.currentTarget;
let query = form.query.value;
if (query === "") return;
router.push("/search?q=" + encodeURIComponent(query));
};
return ( return (
<nav <nav
className="hidden-print navbar navbar-expand-md bg-body-tertiary mb-3" className="hidden-print navbar navbar-expand-md bg-body-tertiary mb-3"
...@@ -414,20 +438,7 @@ function NavBar() { ...@@ -414,20 +438,7 @@ function NavBar() {
</ul> </ul>
<div className="flex-grow-1"></div> <div className="flex-grow-1"></div>
<UserField /> <UserField />
<form role="search" className="d-flex" onSubmit={onSearchSubmit}> <Search />
<div className="input-group">
<input
className="form-control"
type="text"
name="query"
placeholder="Suche"
defaultValue=""
/>
<button className="btn btn-primary" type="submit">
<span className="bi bi-search"></span>
</button>
</div>
</form>
<div className="p-1"> <div className="p-1">
<button className={"btn"} type="button" onClick={switchTheme}> <button className={"btn"} type="button" onClick={switchTheme}>
<span aria-hidden="true" className={"bi bi-moon-stars"} /> <span aria-hidden="true" className={"bi bi-moon-stars"} />
......
...@@ -2,7 +2,7 @@ import { DateTime } from "luxon"; ...@@ -2,7 +2,7 @@ import { DateTime } from "luxon";
export interface ICalEvent { export interface ICalEvent {
summary?: string; summary?: string;
startDate?: DateTime; startDate: DateTime;
endDate?: DateTime; endDate?: DateTime;
duration?: number; duration?: number;
location?: string; location?: string;
...@@ -46,7 +46,11 @@ export function parseICal(fileContent: string): ICalEvent[] { ...@@ -46,7 +46,11 @@ export function parseICal(fileContent: string): ICalEvent[] {
.diff(currentEvent.startDate) .diff(currentEvent.startDate)
.as("minutes"); .as("minutes");
} }
if (currentEvent.startDate) {
events.push(currentEvent as ICalEvent); events.push(currentEvent as ICalEvent);
} else {
console.error("Event without start date");
}
} else if (inEvent) { } else if (inEvent) {
// Parse individual lines within the event // Parse individual lines within the event
const [key, value] = line.trim().split(":"); const [key, value] = line.trim().split(":");
......
...@@ -2,6 +2,7 @@ import { useBackendContext } from "@/components/BackendProvider"; ...@@ -2,6 +2,7 @@ import { useBackendContext } from "@/components/BackendProvider";
import { useEditMode } from "@/components/EditModeProvider"; import { useEditMode } from "@/components/EditModeProvider";
import { FallbackErrorBoundary } from "@/components/FallbackErrorBoundary"; import { FallbackErrorBoundary } from "@/components/FallbackErrorBoundary";
import { OMCreate, OMEdit } from "@/components/OMConfigComponent"; import { OMCreate, OMEdit } from "@/components/OMConfigComponent";
import { ReloadBoundary } from "@/components/ReloadBoundary";
import { useUserContext } from "@/components/UserDataProvider"; import { useUserContext } from "@/components/UserDataProvider";
import { semesterToHuman } from "@/misc/Formatting"; import { semesterToHuman } from "@/misc/Formatting";
import { ResourceType, fetchDataWrapper } from "@/misc/PromiseHelpers"; import { ResourceType, fetchDataWrapper } from "@/misc/PromiseHelpers";
...@@ -171,11 +172,12 @@ function CourseImpl() { ...@@ -171,11 +172,12 @@ function CourseImpl() {
const userContext = useUserContext(); const userContext = useUserContext();
const hasUserInfo = userContext.hasUserInfo(); const hasUserInfo = userContext.hasUserInfo();
const { editMode } = useEditMode(); const { editMode } = useEditMode();
const [forceReload, setForceReload] = useState(0);
const [courseData, setCourseData] = useState<ResourceType<GetCoursesResponse>>(); const [courseData, setCourseData] = useState<ResourceType<GetCoursesResponse>>();
useEffect(() => { useEffect(() => {
setCourseData(fetchDataWrapper(api.getCourses())); setCourseData(fetchDataWrapper(api.getCourses()));
}, [api, hasUserInfo]); }, [api, hasUserInfo, forceReload]);
const [groupedBy, setGroupedBy] = useState<GroupByTypes>("semester"); const [groupedBy, setGroupedBy] = useState<GroupByTypes>("semester");
...@@ -196,7 +198,7 @@ function CourseImpl() { ...@@ -196,7 +198,7 @@ function CourseImpl() {
} }
return ( return (
<> <ReloadBoundary reloadFunc={() => setForceReload((x) => x + 1)}>
<div> <div>
<div className="col-12 p-0"> <div className="col-12 p-0">
<ul className="list-inline d-flex"> <ul className="list-inline d-flex">
...@@ -235,7 +237,7 @@ function CourseImpl() { ...@@ -235,7 +237,7 @@ function CourseImpl() {
<Suspense> <Suspense>
<CourseList courseData={courseData} groupBy={groupedBy} /> <CourseList courseData={courseData} groupBy={groupedBy} />
</Suspense> </Suspense>
</> </ReloadBoundary>
); );
} }
......
...@@ -21,18 +21,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -21,18 +21,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
return obj; return obj;
}); });
// find events that are new (place, duration and time unique) const removeDuplicates = (event, index, self) => {
let new_events = imported_events
.filter((event) => {
return !existingEvents.some((existing) => {
return (
existing.location === event.location &&
existing.duration === event.duration &&
existing.startDate === event.startDate
);
});
})
.filter((event, index, self) => {
// remove duplicates // remove duplicates
return ( return (
index === index ===
...@@ -40,11 +29,23 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -40,11 +29,23 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
(e) => (e) =>
e.location === event.location && e.location === event.location &&
e.duration === event.duration && e.duration === event.duration &&
e.startDate === event.startDate, Math.abs(e.startDate.diff(event.startDate).as("seconds")) < 1,
) )
); );
};
// find events that are new (place, duration and time unique)
const new_events = imported_events
.filter((event) => {
const eventMatch = existingEvents.some((existing) => {
const match =
existing.location === event.location &&
existing.duration === event.duration &&
Math.abs(existing.startDate.diff(event.startDate).as("seconds")) < 1;
return match;
}); });
return !eventMatch;
})
.filter(removeDuplicates);
// find existing events that are not in the imported events // find existing events that are not in the imported events
const not_imported_events = existingEvents const not_imported_events = existingEvents
.filter((event) => { .filter((event) => {
...@@ -52,22 +53,23 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -52,22 +53,23 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
return ( return (
imported.location === event.location && imported.location === event.location &&
imported.duration === event.duration && imported.duration === event.duration &&
imported.startDate === event.startDate Math.abs(imported.startDate.diff(event.startDate).as("seconds")) < 1
); );
}); });
}) })
.filter((event, index, self) => { .filter(removeDuplicates);
// remove duplicates // number of full matches
const full_matches = imported_events
.filter((event) => {
return existingEvents.some((existing) => {
return ( return (
index === existing.location === event.location &&
self.findIndex( existing.duration === event.duration &&
(e) => Math.abs(existing.startDate.diff(event.startDate).as("seconds")) < 1
e.location === event.location &&
e.duration === event.duration &&
e.startDate === event.startDate,
)
); );
}); });
})
.filter(removeDuplicates).length;
const importEvent = (event: ICalEvent) => { const importEvent = (event: ICalEvent) => {
// time must be YYYY-MM-ddTHH:mm:ss // time must be YYYY-MM-ddTHH:mm:ss
...@@ -107,8 +109,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -107,8 +109,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
}; };
const importAllEvents = () => { const importAllEvents = () => {
const promises = api api.getNewOMConfiguration("lecture")
.getNewOMConfiguration("lecture")
.then((res) => { .then((res) => {
const defaultValues: any = {}; const defaultValues: any = {};
res.fields?.forEach((field) => { res.fields?.forEach((field) => {
...@@ -175,9 +176,25 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -175,9 +176,25 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
return ( return (
<div> <div>
<table className="table">
<thead>
<tr>
<th>Nur im Import</th>
<th>Durchschnitt</th>
<th>Nur bei uns</th>
</tr>
</thead>
<tbody>
<tr>
<td>{imported_events.length}</td>
<td>{full_matches}</td>
<td>{existingEvents.length}</td>
</tr>
</tbody>
</table>
<div className="card mb-2"> <div className="card mb-2">
<div className="card-header d-flex align-items-center"> <div className="card-header d-flex align-items-center">
<span className="flex-grow-1">Termine im die nicht bei uns sind</span> <span className="flex-grow-1">Im Import, nicht bei uns</span>
<button className="btn btn-primary" onClick={importAllEvents}> <button className="btn btn-primary" onClick={importAllEvents}>
Alle anlegen Alle anlegen
...@@ -219,7 +236,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even ...@@ -219,7 +236,7 @@ function TerminBody({ course, imported_events }: { course: course; imported_even
</div> </div>
<div className="card"> <div className="card">
<div className="card-header d-flex align-items-center"> <div className="card-header d-flex align-items-center">
<span className="flex-grow-1">Termine bei uns nicht RWTHOnline</span> <span className="flex-grow-1">Bei uns, nicht im Import</span>
<button className="btn btn-primary" onClick={removeAllEvents}> <button className="btn btn-primary" onClick={removeAllEvents}>
Alle entfernen Alle entfernen
...@@ -299,7 +316,8 @@ function RWTHOnlineImportImpl() { ...@@ -299,7 +316,8 @@ function RWTHOnlineImportImpl() {
const onImport = () => { const onImport = () => {
if (inputRef.current === null) return; if (inputRef.current === null) return;
const url = inputRef.current.value; const url =
"https://online.rwth-aachen.de/RWTHonline/pl/ui/%24ctx/wbTvw_List.lehrveranstaltung?pStpSpNr=485837"; /*inputRef.current.value*/
// check if url contains pStpSpNr // check if url contains pStpSpNr
if (!url.includes("pStpSpNr=")) { if (!url.includes("pStpSpNr=")) {
...@@ -310,6 +328,7 @@ function RWTHOnlineImportImpl() { ...@@ -310,6 +328,7 @@ function RWTHOnlineImportImpl() {
const pStpSpNr = parseInt(url.split("pStpSpNr=")[1].split("&")[0]); const pStpSpNr = parseInt(url.split("pStpSpNr=")[1].split("&")[0]);
api.importRWTHOnlineCourse(pStpSpNr).then((ical) => { api.importRWTHOnlineCourse(pStpSpNr).then((ical) => {
const parsed = parseICal(ical); const parsed = parseICal(ical);
console.log(parsed);
setImportedEvents(parsed); setImportedEvents(parsed);
}); });
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment