@olea-bps/base 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/AppBar/index.js +84 -0
- package/components/AppBar/styles.js +27 -0
- package/components/BookDetail/index.js +268 -0
- package/components/BookDetail/styles.js +124 -0
- package/components/ComponentJobsFilter/index.js +188 -0
- package/components/ComponentJobsFilter/styles.js +12 -0
- package/components/ConnectivityWarning/index.js +65 -0
- package/components/ConnectivityWarning/styles.js +19 -0
- package/components/ContactDetail/index.js +232 -0
- package/components/ContactDetail/styles.js +32 -0
- package/components/CourseDetail/index.js +357 -0
- package/components/CourseDetail/styles.js +59 -0
- package/components/CourseDetailDialog/index.js +169 -0
- package/components/CourseDetailDialog/styles.js +116 -0
- package/components/CourseInfo/index.js +219 -0
- package/components/CourseInfo/styles.js +40 -0
- package/components/DevelopmentDialog/index.js +214 -0
- package/components/DevelopmentDialog/styles.js +10 -0
- package/components/EventCodeInput/index.js +149 -0
- package/components/EventCodeInput/styles.js +108 -0
- package/components/FlexMenuEntry/index.js +84 -0
- package/components/FlexMenuEntry/styles.js +27 -0
- package/components/MainMenuEntry/index.js +88 -0
- package/components/MainMenuEntry/styles.js +28 -0
- package/components/MealItem/index.js +87 -0
- package/components/MealItem/styles.js +84 -0
- package/components/MensaMenu/index.js +305 -0
- package/components/MensaMenu/styles.js +94 -0
- package/components/MensaSlider/index.js +188 -0
- package/components/MensaSlider/styles.js +53 -0
- package/components/Modal/index.js +106 -0
- package/components/Modal/styles.js +8 -0
- package/components/NewsDetail/index.js +377 -0
- package/components/NewsDetail/styles.js +77 -0
- package/components/NewsList/index.js +120 -0
- package/components/NewsList/styles.js +19 -0
- package/components/NewsListItem/index.js +89 -0
- package/components/NewsListItem/styles.js +32 -0
- package/components/OtherCourses/index.js +152 -0
- package/components/OtherCourses/styles.js +10 -0
- package/components/PtsDeparture/index.js +140 -0
- package/components/PtsDeparture/styles.js +7 -0
- package/components/PtsStation/index.js +186 -0
- package/components/PtsStation/styles.js +47 -0
- package/components/QuickLinks/index.js +127 -0
- package/components/QuickLinks/styles.js +45 -0
- package/components/RoomDetail/index.js +281 -0
- package/components/RoomDetail/styles.js +56 -0
- package/components/ScaledImage/index.js +92 -0
- package/components/SearchResults/index.js +362 -0
- package/components/SearchResults/styles.js +59 -0
- package/components/SettingSection/index.js +54 -0
- package/components/SettingSection/styles.js +15 -0
- package/components/SettingsDialog/index.js +52 -0
- package/components/SettingsDialog/styles.js +12 -0
- package/components/SettingsDialogRadio/index.js +66 -0
- package/components/SettingsDialogRadio/styles.js +7 -0
- package/components/SettingsDialogSelect/index.js +73 -0
- package/components/SettingsDialogSelect/styles.js +7 -0
- package/components/TimetableCodeInput/index.js +205 -0
- package/components/TimetableCodeInput/styles.js +28 -0
- package/components/TimetableDay/index.js +252 -0
- package/components/TimetableDay/styles.js +103 -0
- package/components/TimetableEvent/index.js +163 -0
- package/components/TimetableEvent/styles.js +108 -0
- package/components/TimetableList/index.js +180 -0
- package/components/TimetableList/styles.js +106 -0
- package/components/TimetableMonth/index.js +156 -0
- package/components/TimetableMonth/styles.js +29 -0
- package/components/TimetableWeek/index.js +230 -0
- package/components/TimetableWeek/styles.js +58 -0
- package/components/TopNews/index.js +282 -0
- package/components/TopNews/styles.js +125 -0
- package/components/TopNewsHtwk/index.js +279 -0
- package/components/TopNewsHtwk/styles.js +142 -0
- package/components/WebView/index.js +108 -0
- package/components/WebView/styles.js +11 -0
- package/context/context-callmanager/TucCallManager.js +74 -0
- package/context/context-callmanager/index.js +128 -0
- package/context/context-canteen/AsistServerApiProvider.js +126 -0
- package/context/context-canteen/CollektorVersion2ApiProvider.js +100 -0
- package/context/context-canteen/index.js +692 -0
- package/context/context-connectivity/index.js +85 -0
- package/context/context-event/AsistServerClient.js +82 -0
- package/context/context-event/index.js +205 -0
- package/context/context-flex-menu/AsistServerApiProvider.js +0 -0
- package/context/context-flex-menu/CollectorVersion2ApiProvider.js +32 -0
- package/context/context-flex-menu/index.js +160 -0
- package/context/context-info-dialog/CollektorVersion2ApiProvider.js +53 -0
- package/context/context-info-dialog/ProviderErrors.js +22 -0
- package/context/context-info-dialog/index.js +190 -0
- package/context/context-mails/MailService.js +147 -0
- package/context/context-mails/TucUnseenApiProvider.js +65 -0
- package/context/context-mails/index.js +131 -0
- package/context/context-news/CollektorVersion2ApiProvider.js +68 -0
- package/context/context-news/index.js +155 -0
- package/context/context-public-transport-ticket/CollektorVersion2ApiProvider.js +45 -0
- package/context/context-public-transport-ticket/ProviderErrors.js +11 -0
- package/context/context-public-transport-ticket/index.js +175 -0
- package/context/context-timetable/CollectorVersion2ApiProvider.js +102 -0
- package/context/context-timetable/ProviderErrors.js +22 -0
- package/context/context-timetable/TimetableService.js +357 -0
- package/context/context-timetable/index.js +215 -0
- package/context/context-user/index.js +586 -0
- package/index.js +178 -0
- package/libraries/base-api-provider/hooks.js +24 -0
- package/libraries/base-api-provider/http-api-provider.js +168 -0
- package/libraries/base-api-provider/index.js +20 -0
- package/libraries/core/api/canteens.js +88 -0
- package/libraries/core/api/corona.js +45 -0
- package/libraries/core/api/courses.js +54 -0
- package/libraries/core/api/device.js +98 -0
- package/libraries/core/api/feed.js +144 -0
- package/libraries/core/api/feedback.js +123 -0
- package/libraries/core/api/jobs.js +48 -0
- package/libraries/core/api/library.js +67 -0
- package/libraries/core/api/lostfound.js +77 -0
- package/libraries/core/api/occupancy.js +44 -0
- package/libraries/core/api/officehours.js +25 -0
- package/libraries/core/api/poi.js +25 -0
- package/libraries/core/api/pts.js +68 -0
- package/libraries/core/api/rooms.js +31 -0
- package/libraries/core/api/survey.js +121 -0
- package/libraries/core/api/telephone.js +32 -0
- package/libraries/core/api/tucrooms.js +31 -0
- package/libraries/core/constants/actions.js +75 -0
- package/libraries/core/constants/api.js +146 -0
- package/libraries/core/constants/enums.js +5 -0
- package/libraries/core/helper/date.js +9 -0
- package/libraries/core/helper/format.helper.js +2 -0
- package/libraries/core/index.js +60 -0
- package/libraries/core/redux/actions/notifications.js +6 -0
- package/libraries/core/redux/actions/setting.js +75 -0
- package/libraries/core/redux/actions/state.js +74 -0
- package/libraries/core/redux/asyncDispatch.js +27 -0
- package/libraries/core/redux/reducers/api.js +190 -0
- package/libraries/core/redux/reducers/index.js +32 -0
- package/libraries/core/redux/reducers/notifications.js +16 -0
- package/libraries/core/redux/reducers/setting.js +99 -0
- package/libraries/core/redux/reducers/state.js +122 -0
- package/libraries/core/redux/selectors.js +123 -0
- package/libraries/core/redux/store.js +40 -0
- package/libraries/core/services/data.js +96 -0
- package/libraries/core/services/root-navigation.js +36 -0
- package/libraries/core/services/search.js +175 -0
- package/libraries/core-plugins/enums/replaceTypes.js +53 -0
- package/libraries/core-plugins/index.js +21 -0
- package/libraries/core-plugins/redux/actions/plugin.js +13 -0
- package/libraries/core-plugins/redux/reducers/plugin.js +210 -0
- package/libraries/icons-openasist/index.js +143 -0
- package/libraries/notifications/index.js +268 -0
- package/libraries/notifications/services/subscriber.service.js +123 -0
- package/libraries/react-native-webview-autoheight/README.md +47 -0
- package/libraries/react-native-webview-autoheight/index.js +140 -0
- package/libraries/react-native-webview-autoheight/package.json +37 -0
- package/libraries/react-native-webview-autoheight/utils.js +268 -0
- package/libraries/redux-offline/.eslintignore +1 -0
- package/libraries/redux-offline/.github/ISSUE_TEMPLATE/redux-offline-core-issues-template.md +25 -0
- package/libraries/redux-offline/.prettierrc +6 -0
- package/libraries/redux-offline/LICENSE +21 -0
- package/libraries/redux-offline/README.md +133 -0
- package/libraries/redux-offline/flow-typed/npm/redux-logger_vx.x.x.js +109 -0
- package/libraries/redux-offline/flow-typed/npm/redux_v4.x.x.js +100 -0
- package/libraries/redux-offline/lib/actions.js +46 -0
- package/libraries/redux-offline/lib/config.js +15 -0
- package/libraries/redux-offline/lib/constants.js +17 -0
- package/libraries/redux-offline/lib/defaults/defaultCommit.js +11 -0
- package/libraries/redux-offline/lib/defaults/defaultRollback.js +11 -0
- package/libraries/redux-offline/lib/defaults/detectNetwork.js +33 -0
- package/libraries/redux-offline/lib/defaults/detectNetwork.native.js +211 -0
- package/libraries/redux-offline/lib/defaults/discard.js +18 -0
- package/libraries/redux-offline/lib/defaults/effect.js +87 -0
- package/libraries/redux-offline/lib/defaults/index.js +32 -0
- package/libraries/redux-offline/lib/defaults/offlineStateLens.js +24 -0
- package/libraries/redux-offline/lib/defaults/persist.js +9 -0
- package/libraries/redux-offline/lib/defaults/persist.native.js +17 -0
- package/libraries/redux-offline/lib/defaults/persistAutoRehydrate.js +8 -0
- package/libraries/redux-offline/lib/defaults/queue.js +27 -0
- package/libraries/redux-offline/lib/defaults/retry.js +29 -0
- package/libraries/redux-offline/lib/index.js +115 -0
- package/libraries/redux-offline/lib/middleware.js +56 -0
- package/libraries/redux-offline/lib/offlineActionTracker.js +43 -0
- package/libraries/redux-offline/lib/send.js +112 -0
- package/libraries/redux-offline/lib/types.js +3 -0
- package/libraries/redux-offline/lib/updater.js +111 -0
- package/libraries/redux-offline/package.json +69 -0
- package/libraries/redux-offline/src/__tests__/defaults/discard.js +22 -0
- package/libraries/redux-offline/src/__tests__/defaults/effect.js +118 -0
- package/libraries/redux-offline/src/__tests__/index.js +116 -0
- package/libraries/redux-offline/src/__tests__/middleware.js +185 -0
- package/libraries/redux-offline/src/__tests__/offlineActionTracker.js +54 -0
- package/libraries/redux-offline/src/__tests__/send.js +208 -0
- package/libraries/redux-offline/src/actions.js +36 -0
- package/libraries/redux-offline/src/config.js +9 -0
- package/libraries/redux-offline/src/constants.js +18 -0
- package/libraries/redux-offline/src/defaults/defaultCommit.js +7 -0
- package/libraries/redux-offline/src/defaults/defaultRollback.js +7 -0
- package/libraries/redux-offline/src/defaults/detectNetwork.js +16 -0
- package/libraries/redux-offline/src/defaults/detectNetwork.native.js +148 -0
- package/libraries/redux-offline/src/defaults/discard.js +19 -0
- package/libraries/redux-offline/src/defaults/effect.js +86 -0
- package/libraries/redux-offline/src/defaults/index.js +25 -0
- package/libraries/redux-offline/src/defaults/offlineStateLens.js +11 -0
- package/libraries/redux-offline/src/defaults/persist.js +4 -0
- package/libraries/redux-offline/src/defaults/persist.native.js +9 -0
- package/libraries/redux-offline/src/defaults/persistAutoRehydrate.js +4 -0
- package/libraries/redux-offline/src/defaults/queue.js +20 -0
- package/libraries/redux-offline/src/defaults/retry.js +18 -0
- package/libraries/redux-offline/src/index.js +138 -0
- package/libraries/redux-offline/src/middleware.js +52 -0
- package/libraries/redux-offline/src/offlineActionTracker.js +40 -0
- package/libraries/redux-offline/src/send.js +111 -0
- package/libraries/redux-offline/src/types.js +127 -0
- package/libraries/redux-offline/src/updater.js +141 -0
- package/libraries/redux-offline/typings.d.ts +150 -0
- package/libraries/redux-offline/yarn.lock +6460 -0
- package/libraries/stored-state/index.js +155 -0
- package/package.json +68 -0
- package/views/Callmanager/index.js +148 -0
- package/views/Callmanager/styles.js +62 -0
- package/views/Canteens/index.js +383 -0
- package/views/Canteens/styles.js +89 -0
- package/views/Dashboard/index.js +176 -0
- package/views/Dashboard/styles.js +16 -0
- package/views/DashboardHtwk/index.js +197 -0
- package/views/DashboardHtwk/styles.js +24 -0
- package/views/Event/index.js +373 -0
- package/views/Event/styles.js +63 -0
- package/views/FeedList/index.js +165 -0
- package/views/FeedList/styles.js +15 -0
- package/views/FeedNews/index.js +243 -0
- package/views/FeedNews/styles.js +32 -0
- package/views/Flexmenu/index.js +185 -0
- package/views/Flexmenu/styles.js +62 -0
- package/views/FlexmenuWebview/index.js +167 -0
- package/views/FlexmenuWebview/styles.js +16 -0
- package/views/Howhy/index.js +151 -0
- package/views/Howhy/styles.js +11 -0
- package/views/Jobs/index.js +217 -0
- package/views/Jobs/styles.js +41 -0
- package/views/MainMenu/index.js +283 -0
- package/views/MainMenu/styles.js +36 -0
- package/views/NewsTabbar/index.js +164 -0
- package/views/NewsTabbar/styles.js +27 -0
- package/views/Opal/index.js +136 -0
- package/views/Opal/styles.js +11 -0
- package/views/PublicTransportTicket/index.js +173 -0
- package/views/PublicTransportTicket/styles.js +17 -0
- package/views/Search/index.js +186 -0
- package/views/Search/styles.js +67 -0
- package/views/SettingsAccessibility/index.js +148 -0
- package/views/SettingsAccessibility/styles.js +13 -0
- package/views/SettingsAppInfo/index.js +86 -0
- package/views/SettingsAppInfo/styles.js +18 -0
- package/views/SettingsCanteens/index.js +249 -0
- package/views/SettingsCanteens/styles.js +33 -0
- package/views/SettingsGeneral/index.js +173 -0
- package/views/SettingsGeneral/styles.js +28 -0
- package/views/SettingsNotifications/index.js +204 -0
- package/views/SettingsNotifications/styles.js +38 -0
- package/views/SettingsUser/index.js +170 -0
- package/views/SettingsUser/styles.js +17 -0
- package/views/TimetableCalendar/index.js +387 -0
- package/views/TimetableCalendar/styles.js +121 -0
- package/views/TimetableList/index.js +402 -0
- package/views/TimetableList/styles.js +55 -0
- package/views/Webviews/index.js +158 -0
- package/views/Webviews/styles.js +11 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
|
|
3
|
+
import * as SecureStore from 'expo-secure-store';
|
|
4
|
+
|
|
5
|
+
import { groupBy } from 'lodash';
|
|
6
|
+
import { DateTime, Duration } from 'luxon';
|
|
7
|
+
|
|
8
|
+
import CollectorVersion2ApiProvider from './CollectorVersion2ApiProvider';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef TimetableProvider
|
|
12
|
+
* @property {(timetableCode: string, startDate: string, startDate: string) => Course[]} getByCode Ruft zu einem Stundenplancode die entsprechenden Vorlesungen in einem bestimmten Zeitraum ab
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef CourseDataField
|
|
17
|
+
* @property {string} data
|
|
18
|
+
* @property {string} displayname
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef CourseDataField
|
|
23
|
+
* @property {string} data
|
|
24
|
+
* @property {string} displayname
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef CourseTime
|
|
29
|
+
* @property {number} dayOfWeek
|
|
30
|
+
* @property {string} date ISO Datum
|
|
31
|
+
* @property {string} start ISO Uhrzeit
|
|
32
|
+
* @property {string} end ISO Uhrzeit
|
|
33
|
+
* @property {string} displayname
|
|
34
|
+
* @property {string} weekmode
|
|
35
|
+
* @property {string} mode
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef Course
|
|
40
|
+
* @property {CourseDataField} title
|
|
41
|
+
* @property {CourseDataField} room
|
|
42
|
+
* @property {CourseDataField} type
|
|
43
|
+
* @property {CourseDataField[]} lecturer
|
|
44
|
+
* @property {CourseTime[]} times
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
const TimetableCodeStoreKey = 'timetable.code';
|
|
48
|
+
const TimetableCoursesStoreKey = 'timetable.courses';
|
|
49
|
+
|
|
50
|
+
export class ApiProviderNotInitializedError extends Error {
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = this.constructor.name;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class TimetableCodeNotInitializedError extends Error {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = this.constructor.name;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Eine Serviceklasse, die Zugriff auf die Daten des Stundenplan-Moduls ermöglicht.
|
|
66
|
+
*
|
|
67
|
+
* Der Stundenplan-Service ist Klasse für die Datenverwaltung der für das Stundenplan-Modul benötigten Daten.
|
|
68
|
+
* Dieser ist außerhalb des React-Kontextes angesiedelt, damit auf die Daten zugegriffen werden kann, wenn kein React-Kontext verfügbar ist.
|
|
69
|
+
* Alle Daten werden in lokalen Speichern zwischengespeichert, um beim ersten Zugriff veraltet Daten anzeigen zu können.
|
|
70
|
+
*
|
|
71
|
+
* Der Service sollte über {@linkcode TimetableService.fromProviderSettingsObject} initialisert werden.
|
|
72
|
+
*/
|
|
73
|
+
export default class TimetableService {
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @type {TimetableProvider}
|
|
77
|
+
*/
|
|
78
|
+
#provider;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Konstruktor des Stundenplan-Services.
|
|
82
|
+
* Es muss ein Provider Übergeben werden, damit der Stundenplan-Service Daten über den Provider abrufen kann.
|
|
83
|
+
* Es wird empfohlen {@linkcode TimetableService.fromProviderSettingsObject} zu verwenden.
|
|
84
|
+
*
|
|
85
|
+
* @param {TimetableProvider} provider Provider, welcher für den Datenabruf zuständig ist
|
|
86
|
+
* @example
|
|
87
|
+
* const language = 'de';
|
|
88
|
+
* const providerSettings {
|
|
89
|
+
* name: 'normal-provider',
|
|
90
|
+
* url: 'https://provider.com/api/v1/'
|
|
91
|
+
* };
|
|
92
|
+
*
|
|
93
|
+
* const timetableService = TimetableService.fromProviderSettingsObject(providerSettings, language);
|
|
94
|
+
*/
|
|
95
|
+
constructor(provider) {
|
|
96
|
+
this.#provider = provider;
|
|
97
|
+
|
|
98
|
+
this.#code = SecureStore.getItem(TimetableCodeStoreKey);
|
|
99
|
+
this.#courses = JSON.parse(SecureStore.getItem(TimetableCoursesStoreKey));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
#code = undefined;
|
|
105
|
+
#codeSubscribers = new Set();
|
|
106
|
+
|
|
107
|
+
code() {
|
|
108
|
+
return this.#code;
|
|
109
|
+
}
|
|
110
|
+
codeCallback = () => this.code();
|
|
111
|
+
|
|
112
|
+
#setCode(code) {
|
|
113
|
+
this.#code = code;
|
|
114
|
+
this.#codeSubscribers.forEach(subscriber => subscriber(code));
|
|
115
|
+
}
|
|
116
|
+
async setCode(code) {
|
|
117
|
+
await SecureStore.setItemAsync(TimetableCodeStoreKey, code);
|
|
118
|
+
this.#setCode(code);
|
|
119
|
+
}
|
|
120
|
+
setCodeCallback = async (code) => this.setCode(code);
|
|
121
|
+
|
|
122
|
+
async deleteCode() {
|
|
123
|
+
|
|
124
|
+
await Promise.all([
|
|
125
|
+
SecureStore.deleteItemAsync(TimetableCodeStoreKey),
|
|
126
|
+
SecureStore.deleteItemAsync(TimetableCoursesStoreKey),
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
this.#setCode(null);
|
|
130
|
+
this.#setCourses(null);
|
|
131
|
+
}
|
|
132
|
+
deleteCodeCallback = () => this.deleteCode();
|
|
133
|
+
|
|
134
|
+
codeSubscribe(subscriber) {
|
|
135
|
+
this.#codeSubscribers.add(subscriber);
|
|
136
|
+
|
|
137
|
+
return () => this.codeUnsubscribe(subscriber);
|
|
138
|
+
}
|
|
139
|
+
codeSubscribeCallback = (subscriber) => this.codeSubscribe(subscriber);
|
|
140
|
+
|
|
141
|
+
codeUnsubscribe(subscriber) {
|
|
142
|
+
return this.#codeSubscribers.delete(subscriber);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @type {Object.<string, Course[]>}
|
|
149
|
+
*/
|
|
150
|
+
#courses = undefined;
|
|
151
|
+
#coursesSubscribers = new Set();
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Liefert die Vorlesungen, die von dem Service respeichert werden zurück.
|
|
155
|
+
* Dabei werden die Vorlesungen nach Vorlesungstagen gruppiert.
|
|
156
|
+
* Somit wird ein Object zurückgegeben, bei dem die Schlüssel ISO-Datums der Vorlesungstage sind und die Werte sind Listen mit Vorlesungen
|
|
157
|
+
*
|
|
158
|
+
* @returns {Object.<string, Course[]>} Vorlesungen gruppiert nach Vorlesungstagen
|
|
159
|
+
*/
|
|
160
|
+
courses() {
|
|
161
|
+
return this.#courses;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#setCourses(courses) {
|
|
165
|
+
// Neue Vorlesungsdaten im Service hinterlegen
|
|
166
|
+
this.#courses = courses;
|
|
167
|
+
|
|
168
|
+
// Jedem Subscriber werden die neuen Vorlesungstage bekannt gemacht
|
|
169
|
+
this.#coursesSubscribers.forEach(subscriber => subscriber(this.#courses));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
coursesCallback = () => this.courses();
|
|
173
|
+
|
|
174
|
+
async refreshCourses(startDate, endDate) {
|
|
175
|
+
|
|
176
|
+
if (this.#provider === null) {
|
|
177
|
+
throw new ApiProviderNotInitializedError('Api Provider is not initilized');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (this.#code === null) {
|
|
181
|
+
throw new TimetableCodeNotInitializedError('Timetable code is not initilized');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const courses = await this.#provider.getByCode(this.#code, startDate, endDate);
|
|
185
|
+
const transformedCourses = courses.map(
|
|
186
|
+
course => {
|
|
187
|
+
// Erstes Time-Element aus dem times-Array nehmen, da im neuen Format nur noch eine Zeit enthalten ist
|
|
188
|
+
const courseTime = course?.times?.[0];
|
|
189
|
+
if (courseTime) {
|
|
190
|
+
const courseDate = DateTime.fromISO(courseTime?.date);
|
|
191
|
+
// Startzeit und Endzeit der Vorlesung in ein DateTime umwandeln
|
|
192
|
+
const courseStartTime = Duration.fromISOTime(courseTime.start);
|
|
193
|
+
const courseStartDateTime = courseDate.plus(courseStartTime);
|
|
194
|
+
const courseEndTime = Duration.fromISOTime(courseTime.end);
|
|
195
|
+
const courseEndDateTime = courseDate.plus(courseEndTime);
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
...course,
|
|
199
|
+
startDateTime: courseStartDateTime.toISO(),
|
|
200
|
+
endDateTime: courseEndDateTime.toISO(),
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
return course;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
// Gruppieren der vom Provider abgeholten Vorlesungen
|
|
209
|
+
// Es wird nach dem Datum der Vorlesungen gruppiert
|
|
210
|
+
// Vorlesungen, die keinem Tag zugeordnet werden können, werden untder dem Schlüssel `undefined` zusammengefasst
|
|
211
|
+
const addingCourses = groupBy(
|
|
212
|
+
transformedCourses,
|
|
213
|
+
course => {
|
|
214
|
+
// Datum der Vorlesung aus der Vorlesung holen
|
|
215
|
+
const courseDate = course?.times?.[0]?.date;
|
|
216
|
+
|
|
217
|
+
// Prüfen ob die Vorlesung einen Wert als Datum vorweist
|
|
218
|
+
return courseDate
|
|
219
|
+
// Ist ein Wert vorhanden, wird dieser für die Gruppierung verwendet
|
|
220
|
+
? courseDate
|
|
221
|
+
// Ansonsten wird undefined zurückgeben (lerrer String, null, undefined, ...)
|
|
222
|
+
: undefined;
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
//Entfernen der Vorlesungstage zwischen Startdatum und Enddatum
|
|
227
|
+
const rangeRemovedCourses = Object.fromEntries(
|
|
228
|
+
Object.entries(this.#courses ?? {})
|
|
229
|
+
.filter(([coursesDate,]) => startDate >= coursesDate && coursesDate <= endDate)
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Zusammenführen der neuen Vorlesungstagen der Vorlesungen des Providers und der schon vorhandenen Vorlesungstagen
|
|
233
|
+
const newCourses = {
|
|
234
|
+
...rangeRemovedCourses,
|
|
235
|
+
...addingCourses,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Neue Vorlesungsdaten in den Cache ablegen
|
|
239
|
+
SecureStore.setItem(TimetableCoursesStoreKey, JSON.stringify(newCourses));
|
|
240
|
+
|
|
241
|
+
// Neue Vorlesungen hin Service hinterlegen und Äanderun bekannt geben
|
|
242
|
+
this.#setCourses(newCourses);
|
|
243
|
+
}
|
|
244
|
+
refreshCoursesCallback = (startDate, endDate) => this.refreshCourses(startDate, endDate);
|
|
245
|
+
|
|
246
|
+
coursesSubscribe(subscriber) {
|
|
247
|
+
this.#coursesSubscribers.add(subscriber);
|
|
248
|
+
|
|
249
|
+
return () => this.coursesUnsubscribe(subscriber);
|
|
250
|
+
}
|
|
251
|
+
coursesSubscribeCallback = (subscriber) => this.coursesSubscribe(subscriber);
|
|
252
|
+
|
|
253
|
+
coursesUnsubscribe(subscriber) {
|
|
254
|
+
return this.#coursesSubscribers.delete(subscriber);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Erstellen eines Stundenplanservices mit Hilfe der Provider-Einstellungen und Sprache
|
|
261
|
+
*
|
|
262
|
+
* @param {ProviderSetting} providerSettingsObject
|
|
263
|
+
* @param {string} language
|
|
264
|
+
* @returns
|
|
265
|
+
*/
|
|
266
|
+
static fromProviderSettingsObject(providerSettingsObject, language) {
|
|
267
|
+
const provider = TimetableService.#createProvider(providerSettingsObject, language);
|
|
268
|
+
|
|
269
|
+
return new TimetableService(provider);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Erstellen des Providers mit Hilfe eines Provider-Einstellungen-Objektes und einer Sprache
|
|
274
|
+
*
|
|
275
|
+
* @param {ProviderSetting} providerSettingsObject Einstellungen welche zum auswählen und Initialisieren des Provider verwendet werden
|
|
276
|
+
* @param {string} language Sprachcode welcher für den Datenabruf verwendet werden soll
|
|
277
|
+
*/
|
|
278
|
+
static #createProvider(providerSettingsObject, language) {
|
|
279
|
+
const { provider } = providerSettingsObject;
|
|
280
|
+
|
|
281
|
+
switch (provider) {
|
|
282
|
+
case CollectorVersion2ApiProvider.name:
|
|
283
|
+
return CollectorVersion2ApiProvider.fromSettingsObject(providerSettingsObject, language);
|
|
284
|
+
default:
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Ein React-Hook, um den Stundenplancode des Stundenplan-Services in den React-Kontext einzubinden.
|
|
292
|
+
*
|
|
293
|
+
* @param {TimetableService} timetableService Der Stundenplan-Service welche den Stundenplancode bereitstellen soll
|
|
294
|
+
* @returns {[string|null, (code: string) => Promise<void>, () => void]}
|
|
295
|
+
* @example
|
|
296
|
+
* const timetableService = TimetableService.fromProviderSettingsObject(
|
|
297
|
+
* {
|
|
298
|
+
* provider: 'hs-collector-v2',
|
|
299
|
+
* url: 'https://hsc-production.hrz.tu-chemnitz.de/hs_collector/api/v1/',
|
|
300
|
+
* },
|
|
301
|
+
* 'de',
|
|
302
|
+
* );
|
|
303
|
+
*
|
|
304
|
+
* const [timetableCode, saveTimetableCode, deleteTimetableCode] = useSyncTimetableCode(timetableService);
|
|
305
|
+
*
|
|
306
|
+
* saveTimetableCode('testcode');
|
|
307
|
+
*
|
|
308
|
+
* return (
|
|
309
|
+
* <Text>
|
|
310
|
+
* {timetableCode}
|
|
311
|
+
* </Text>
|
|
312
|
+
* );
|
|
313
|
+
*/
|
|
314
|
+
export function useSyncTimetableCode(timetableService) {
|
|
315
|
+
const timetableCode = useSyncExternalStore(
|
|
316
|
+
timetableService.codeSubscribeCallback,
|
|
317
|
+
timetableService.codeCallback,
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
return [timetableCode, timetableService.setCodeCallback, timetableService.deleteCodeCallback];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* React-Hook, welcher die Vorlesungen nach Vorlesungtagen gruppoert für React zur verfügung stellt.
|
|
325
|
+
* Zusätzlich wird eine Funktion zurückgegeben, welche für die Aktualisierung der Daten in einem bestimmten Zeitraum verwendet werden kann.
|
|
326
|
+
*
|
|
327
|
+
* @param {TimetableService} timetableService
|
|
328
|
+
* @returns {[Object.<string, Course[]>, (startDate: string, endDate: string)=> Promise<void>]}
|
|
329
|
+
* @example
|
|
330
|
+
* const timetableService = TimetableService.fromProviderSettingsObject(
|
|
331
|
+
* {
|
|
332
|
+
* provider: 'hs-collector-v2',
|
|
333
|
+
* url: 'https://hsc-production.hrz.tu-chemnitz.de/hs_collector/api/v1/',
|
|
334
|
+
* },
|
|
335
|
+
* 'de',
|
|
336
|
+
* );
|
|
337
|
+
*
|
|
338
|
+
* const [courses, refreshCourses] = useSyncCourses(timetableService);
|
|
339
|
+
*
|
|
340
|
+
* useEffect(
|
|
341
|
+
* () => {
|
|
342
|
+
* refreshCourses('2025-01-01', '2026-01-01');
|
|
343
|
+
* },
|
|
344
|
+
* []
|
|
345
|
+
* );
|
|
346
|
+
*
|
|
347
|
+
* return (
|
|
348
|
+
* );
|
|
349
|
+
*/
|
|
350
|
+
export function useSyncCourses(timetableService) {
|
|
351
|
+
const courses = useSyncExternalStore(
|
|
352
|
+
timetableService.coursesSubscribeCallback,
|
|
353
|
+
timetableService.coursesCallback,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
return [courses, timetableService.refreshCoursesCallback];
|
|
357
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { createContext, useEffect, useContext, useMemo } from 'react'
|
|
16
|
+
|
|
17
|
+
import { useSelector } from 'react-redux';
|
|
18
|
+
import { useTheme } from 'react-native-paper';
|
|
19
|
+
|
|
20
|
+
import { DateTime, Duration } from 'luxon';
|
|
21
|
+
|
|
22
|
+
import { TimetableNotFoundError } from './ProviderErrors';
|
|
23
|
+
import TimetableService, {
|
|
24
|
+
ApiProviderNotInitializedError,
|
|
25
|
+
TimetableCodeNotInitializedError,
|
|
26
|
+
useSyncCourses,
|
|
27
|
+
useSyncTimetableCode
|
|
28
|
+
} from './TimetableService';
|
|
29
|
+
|
|
30
|
+
const CourseWeekModeWeekly = 'weekly';
|
|
31
|
+
const CourseWeekModeOdd = 'odd';
|
|
32
|
+
const CourseWeekModeEven = 'even';
|
|
33
|
+
|
|
34
|
+
const CourseWeekModes = {
|
|
35
|
+
weekly: CourseWeekModeWeekly,
|
|
36
|
+
odd: CourseWeekModeOdd,
|
|
37
|
+
even: CourseWeekModeEven,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const TimetableContext = createContext({
|
|
41
|
+
code: null,
|
|
42
|
+
courses: {},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Ein Monat ist die standart Zeispanne für das Vorladen der Stundenplandaten
|
|
47
|
+
*
|
|
48
|
+
* @constant
|
|
49
|
+
* @type {string} Zeitspanne im ISO Format(https://de.wikipedia.org/wiki/ISO_8601#Zeitspannen)
|
|
50
|
+
*/
|
|
51
|
+
const defaultPrefetchDistance = 'P1M';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Selector für Wert, der anzeigt ob die Staging-Server genutzt werden sollen.
|
|
55
|
+
* @param {Object} reduxState
|
|
56
|
+
* @returns {boolean} true, wenn die Staging-Server verwendet werden sollen, ansonsten false
|
|
57
|
+
*/
|
|
58
|
+
function selectUseStagingServer(reduxState) {
|
|
59
|
+
return reduxState?.settingReducer?.settingsDevelop?.useStaging ?? false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Provider for timetable context
|
|
64
|
+
*/
|
|
65
|
+
function TimetableContextProvider({ children }) {
|
|
66
|
+
const componentName = TimetableContextProvider.name;
|
|
67
|
+
const theme = useTheme();
|
|
68
|
+
const useStagingServers = useSelector(selectUseStagingServer);
|
|
69
|
+
const language = 'de';
|
|
70
|
+
|
|
71
|
+
// Einstellungen für das Stundenplan-Modul
|
|
72
|
+
const timetableSettings = theme?.appSettings?.modules?.timetable
|
|
73
|
+
|
|
74
|
+
// Einstellungen für Vorladen der Stundenplandaten
|
|
75
|
+
const timetablePrefetchSettings = timetableSettings?.prefetch;
|
|
76
|
+
const beginPrefetchDistance = timetablePrefetchSettings?.beginDistance ?? defaultPrefetchDistance;
|
|
77
|
+
const endPrefetchDistance = timetablePrefetchSettings?.beginDistance ?? defaultPrefetchDistance;
|
|
78
|
+
|
|
79
|
+
// Einstellungen für API-Provider
|
|
80
|
+
const timetableApiSettings = theme?.appSettings?.modules?.timetable?.api
|
|
81
|
+
// Soll der Staging-Provider verwendet werden?
|
|
82
|
+
const timetableApiProviderSettings = useStagingServers
|
|
83
|
+
// Wenn ja, werden die Staging Provider-Einstellungen geladen
|
|
84
|
+
? timetableApiSettings?.staging
|
|
85
|
+
// Wenn nein, werden die productiven Provider-Einstellungen geladen
|
|
86
|
+
: timetableApiSettings?.production;
|
|
87
|
+
|
|
88
|
+
// Erstellen des Stundenplan-Services
|
|
89
|
+
const timetableService = useMemo(
|
|
90
|
+
() => TimetableService.fromProviderSettingsObject(
|
|
91
|
+
timetableApiProviderSettings,
|
|
92
|
+
language,
|
|
93
|
+
),
|
|
94
|
+
[timetableApiProviderSettings, language]
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// Stundenplan-Code aus dem Stundenplan-Service holen
|
|
98
|
+
// Es werden noch 2 Funktionen aus dem Stundenplan-Service geladen, um den Code zu speichern und zu löschen
|
|
99
|
+
const [timetableCode, saveTimetableCode, deleteTimetableCode] = useSyncTimetableCode(timetableService);
|
|
100
|
+
|
|
101
|
+
// Vorlesungen gruppiert nach Vorlesungstagen werden aus dem Stundenplan-Service geholt
|
|
102
|
+
// Es wird zusätzlich eine Funktion zum aktuallisieren der Vorlesungen mit geladen
|
|
103
|
+
const [courses, refreshCourses] = useSyncCourses(timetableService);
|
|
104
|
+
|
|
105
|
+
// Aktualiseren des course-States, wenn Provider oder Stundenplan-Code sich ändern.
|
|
106
|
+
useEffect(
|
|
107
|
+
() => {
|
|
108
|
+
// Stundenplan wird nur einmal geholt, wenn der Stundenplancode geladen ist
|
|
109
|
+
if ((timetableCode ?? false)) {
|
|
110
|
+
// Berechnen des Vorladezeitraumes
|
|
111
|
+
// ISO Zeitspannen(string) werden in Luxon Zeitspannen umgewandelt
|
|
112
|
+
const beginPrefetchDuration = Duration.fromISO(beginPrefetchDistance);
|
|
113
|
+
const endPrefetchDuration = Duration.fromISO(endPrefetchDistance);
|
|
114
|
+
// Jetztige Zeit ermitteln
|
|
115
|
+
const today = DateTime.now();
|
|
116
|
+
// Für den Anfang des Vorladezeitraumes das Datum berechnen
|
|
117
|
+
const prefetchStartDate = today.minus(beginPrefetchDuration).toISODate();
|
|
118
|
+
// Für das Ende des Vorlesungszeitraumes das Datum berechnen
|
|
119
|
+
const prefetchEndDate = today.plus(endPrefetchDuration).toISODate();
|
|
120
|
+
|
|
121
|
+
console.debug(componentName, 'prefetch timetable courses from', prefetchStartDate, 'to', prefetchEndDate);
|
|
122
|
+
|
|
123
|
+
refreshCourses(prefetchStartDate, prefetchEndDate)
|
|
124
|
+
.then(() => setSynchronizationCompleted(true))
|
|
125
|
+
.catch(
|
|
126
|
+
reason => {
|
|
127
|
+
if (!reason instanceof ApiProviderNotInitializedError || !reason instanceof TimetableCodeNotInitializedError) {
|
|
128
|
+
console.error(componentName, ': Error while update courses by timetable code: ', reason, 'base url: ', timetableApiBaseUrl);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}, [timetableService, beginPrefetchDistance, endPrefetchDistance, timetableCode]
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<TimetableContext.Provider
|
|
138
|
+
value={{
|
|
139
|
+
timetableCode: timetableCode,
|
|
140
|
+
saveTimetableCode: saveTimetableCode,
|
|
141
|
+
deleteTimetableCode: deleteTimetableCode,
|
|
142
|
+
courses: courses,
|
|
143
|
+
refreshCourses: refreshCourses,
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
{children}
|
|
147
|
+
</TimetableContext.Provider>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Liefert den derzeitigen Stundenplan-Code und eine Funktion zum Speichern eines neues Stundenplan-Codes.
|
|
153
|
+
* @function
|
|
154
|
+
* @returns {[string, (timetableCode: string) => Promise<void>, () => Promise<void>]} Array mit 3 Elementen. Das erste Element ist der derzeitige gespeicherte Stundenplan-Code.
|
|
155
|
+
* Das zweite Element ist eine Funktion, welche das Speichern eines neuen Stundenplan-Codes ermlöglicht.
|
|
156
|
+
* Das dritte Element ist eine Funktion, die das Löschen des derzeitigen Stundenplan-Codes und der Courses ermöglicht.
|
|
157
|
+
* @example
|
|
158
|
+
* [timetableCode, saveTimetableCode, deleteTimetableCode] = useTimetableCode();
|
|
159
|
+
* saveTimetableCode(newTimetableCode);
|
|
160
|
+
* deleteTimetableCode();
|
|
161
|
+
*/
|
|
162
|
+
function useTimetableCode() {
|
|
163
|
+
const { timetableCode, saveTimetableCode, deleteTimetableCode } = useContext(TimetableContext);
|
|
164
|
+
|
|
165
|
+
return [timetableCode, saveTimetableCode, deleteTimetableCode];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Dieser Hook stellt die Vorlesungen aus dem Stundenplan-Kontext zur Verfügung.
|
|
170
|
+
* Es werden 2 Rückgabewerte in einem Array zurückgegeben.
|
|
171
|
+
* Der erste Parameter ist eine Map der Vorlesungen für den derzeitigen Stundenplan-Code im Stundenplan-Kontext.
|
|
172
|
+
* Die Schlüsel sind die Vorlesungstage und die Werte sind Listen der entsprechenden Vorlesungen zu dem im Schlüssel enthaltenen Datum.
|
|
173
|
+
* Der zweite Parameter ist eine parameterlose Funktion, welche die Vorlesungen im Stundenplan-Kontext aktuallisiert.
|
|
174
|
+
* @returns {[Object.<string, Course[]>, (startDate: string, endDate: string) => Promise<void>]} Array, welches aus 2 Elementen besteht.
|
|
175
|
+
* @example
|
|
176
|
+
* const [courses, refreshCourses] = useCourses();
|
|
177
|
+
*
|
|
178
|
+
* refreshCourses('2025-01-01', '2025-02-01');
|
|
179
|
+
*
|
|
180
|
+
* const coursesOfDay = courses['2025-01-01'];
|
|
181
|
+
*/
|
|
182
|
+
function useCourses() {
|
|
183
|
+
const { courses, refreshCourses } = useContext(TimetableContext);
|
|
184
|
+
|
|
185
|
+
return [courses, refreshCourses];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
*
|
|
190
|
+
*
|
|
191
|
+
* @param {string} date ISO Datum der Vorlesungen
|
|
192
|
+
* @returns {[Course[], (date : string) => Promise<void>]}
|
|
193
|
+
* @example
|
|
194
|
+
* const [dateCourses, refreshDateCourses] = useDateCourses('2025-01-01');
|
|
195
|
+
*
|
|
196
|
+
* refreshDateCourses();
|
|
197
|
+
*/
|
|
198
|
+
function useDateCourses(date) {
|
|
199
|
+
const [courses, refreshCourses] = useCourses();
|
|
200
|
+
|
|
201
|
+
const dateCourses = courses?.[date] ?? [];
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
return [dateCourses, refreshCourses]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
TimetableContext as default,
|
|
209
|
+
TimetableContextProvider,
|
|
210
|
+
CourseWeekModes as weekModes,
|
|
211
|
+
useTimetableCode,
|
|
212
|
+
useCourses,
|
|
213
|
+
useDateCourses,
|
|
214
|
+
TimetableNotFoundError,
|
|
215
|
+
}
|