@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.
Files changed (268) hide show
  1. package/components/AppBar/index.js +84 -0
  2. package/components/AppBar/styles.js +27 -0
  3. package/components/BookDetail/index.js +268 -0
  4. package/components/BookDetail/styles.js +124 -0
  5. package/components/ComponentJobsFilter/index.js +188 -0
  6. package/components/ComponentJobsFilter/styles.js +12 -0
  7. package/components/ConnectivityWarning/index.js +65 -0
  8. package/components/ConnectivityWarning/styles.js +19 -0
  9. package/components/ContactDetail/index.js +232 -0
  10. package/components/ContactDetail/styles.js +32 -0
  11. package/components/CourseDetail/index.js +357 -0
  12. package/components/CourseDetail/styles.js +59 -0
  13. package/components/CourseDetailDialog/index.js +169 -0
  14. package/components/CourseDetailDialog/styles.js +116 -0
  15. package/components/CourseInfo/index.js +219 -0
  16. package/components/CourseInfo/styles.js +40 -0
  17. package/components/DevelopmentDialog/index.js +214 -0
  18. package/components/DevelopmentDialog/styles.js +10 -0
  19. package/components/EventCodeInput/index.js +149 -0
  20. package/components/EventCodeInput/styles.js +108 -0
  21. package/components/FlexMenuEntry/index.js +84 -0
  22. package/components/FlexMenuEntry/styles.js +27 -0
  23. package/components/MainMenuEntry/index.js +88 -0
  24. package/components/MainMenuEntry/styles.js +28 -0
  25. package/components/MealItem/index.js +87 -0
  26. package/components/MealItem/styles.js +84 -0
  27. package/components/MensaMenu/index.js +305 -0
  28. package/components/MensaMenu/styles.js +94 -0
  29. package/components/MensaSlider/index.js +188 -0
  30. package/components/MensaSlider/styles.js +53 -0
  31. package/components/Modal/index.js +106 -0
  32. package/components/Modal/styles.js +8 -0
  33. package/components/NewsDetail/index.js +377 -0
  34. package/components/NewsDetail/styles.js +77 -0
  35. package/components/NewsList/index.js +120 -0
  36. package/components/NewsList/styles.js +19 -0
  37. package/components/NewsListItem/index.js +89 -0
  38. package/components/NewsListItem/styles.js +32 -0
  39. package/components/OtherCourses/index.js +152 -0
  40. package/components/OtherCourses/styles.js +10 -0
  41. package/components/PtsDeparture/index.js +140 -0
  42. package/components/PtsDeparture/styles.js +7 -0
  43. package/components/PtsStation/index.js +186 -0
  44. package/components/PtsStation/styles.js +47 -0
  45. package/components/QuickLinks/index.js +127 -0
  46. package/components/QuickLinks/styles.js +45 -0
  47. package/components/RoomDetail/index.js +281 -0
  48. package/components/RoomDetail/styles.js +56 -0
  49. package/components/ScaledImage/index.js +92 -0
  50. package/components/SearchResults/index.js +362 -0
  51. package/components/SearchResults/styles.js +59 -0
  52. package/components/SettingSection/index.js +54 -0
  53. package/components/SettingSection/styles.js +15 -0
  54. package/components/SettingsDialog/index.js +52 -0
  55. package/components/SettingsDialog/styles.js +12 -0
  56. package/components/SettingsDialogRadio/index.js +66 -0
  57. package/components/SettingsDialogRadio/styles.js +7 -0
  58. package/components/SettingsDialogSelect/index.js +73 -0
  59. package/components/SettingsDialogSelect/styles.js +7 -0
  60. package/components/TimetableCodeInput/index.js +205 -0
  61. package/components/TimetableCodeInput/styles.js +28 -0
  62. package/components/TimetableDay/index.js +252 -0
  63. package/components/TimetableDay/styles.js +103 -0
  64. package/components/TimetableEvent/index.js +163 -0
  65. package/components/TimetableEvent/styles.js +108 -0
  66. package/components/TimetableList/index.js +180 -0
  67. package/components/TimetableList/styles.js +106 -0
  68. package/components/TimetableMonth/index.js +156 -0
  69. package/components/TimetableMonth/styles.js +29 -0
  70. package/components/TimetableWeek/index.js +230 -0
  71. package/components/TimetableWeek/styles.js +58 -0
  72. package/components/TopNews/index.js +282 -0
  73. package/components/TopNews/styles.js +125 -0
  74. package/components/TopNewsHtwk/index.js +279 -0
  75. package/components/TopNewsHtwk/styles.js +142 -0
  76. package/components/WebView/index.js +108 -0
  77. package/components/WebView/styles.js +11 -0
  78. package/context/context-callmanager/TucCallManager.js +74 -0
  79. package/context/context-callmanager/index.js +128 -0
  80. package/context/context-canteen/AsistServerApiProvider.js +126 -0
  81. package/context/context-canteen/CollektorVersion2ApiProvider.js +100 -0
  82. package/context/context-canteen/index.js +692 -0
  83. package/context/context-connectivity/index.js +85 -0
  84. package/context/context-event/AsistServerClient.js +82 -0
  85. package/context/context-event/index.js +205 -0
  86. package/context/context-flex-menu/AsistServerApiProvider.js +0 -0
  87. package/context/context-flex-menu/CollectorVersion2ApiProvider.js +32 -0
  88. package/context/context-flex-menu/index.js +160 -0
  89. package/context/context-info-dialog/CollektorVersion2ApiProvider.js +53 -0
  90. package/context/context-info-dialog/ProviderErrors.js +22 -0
  91. package/context/context-info-dialog/index.js +190 -0
  92. package/context/context-mails/MailService.js +147 -0
  93. package/context/context-mails/TucUnseenApiProvider.js +65 -0
  94. package/context/context-mails/index.js +131 -0
  95. package/context/context-news/CollektorVersion2ApiProvider.js +68 -0
  96. package/context/context-news/index.js +155 -0
  97. package/context/context-public-transport-ticket/CollektorVersion2ApiProvider.js +45 -0
  98. package/context/context-public-transport-ticket/ProviderErrors.js +11 -0
  99. package/context/context-public-transport-ticket/index.js +175 -0
  100. package/context/context-timetable/CollectorVersion2ApiProvider.js +102 -0
  101. package/context/context-timetable/ProviderErrors.js +22 -0
  102. package/context/context-timetable/TimetableService.js +357 -0
  103. package/context/context-timetable/index.js +215 -0
  104. package/context/context-user/index.js +586 -0
  105. package/index.js +178 -0
  106. package/libraries/base-api-provider/hooks.js +24 -0
  107. package/libraries/base-api-provider/http-api-provider.js +168 -0
  108. package/libraries/base-api-provider/index.js +20 -0
  109. package/libraries/core/api/canteens.js +88 -0
  110. package/libraries/core/api/corona.js +45 -0
  111. package/libraries/core/api/courses.js +54 -0
  112. package/libraries/core/api/device.js +98 -0
  113. package/libraries/core/api/feed.js +144 -0
  114. package/libraries/core/api/feedback.js +123 -0
  115. package/libraries/core/api/jobs.js +48 -0
  116. package/libraries/core/api/library.js +67 -0
  117. package/libraries/core/api/lostfound.js +77 -0
  118. package/libraries/core/api/occupancy.js +44 -0
  119. package/libraries/core/api/officehours.js +25 -0
  120. package/libraries/core/api/poi.js +25 -0
  121. package/libraries/core/api/pts.js +68 -0
  122. package/libraries/core/api/rooms.js +31 -0
  123. package/libraries/core/api/survey.js +121 -0
  124. package/libraries/core/api/telephone.js +32 -0
  125. package/libraries/core/api/tucrooms.js +31 -0
  126. package/libraries/core/constants/actions.js +75 -0
  127. package/libraries/core/constants/api.js +146 -0
  128. package/libraries/core/constants/enums.js +5 -0
  129. package/libraries/core/helper/date.js +9 -0
  130. package/libraries/core/helper/format.helper.js +2 -0
  131. package/libraries/core/index.js +60 -0
  132. package/libraries/core/redux/actions/notifications.js +6 -0
  133. package/libraries/core/redux/actions/setting.js +75 -0
  134. package/libraries/core/redux/actions/state.js +74 -0
  135. package/libraries/core/redux/asyncDispatch.js +27 -0
  136. package/libraries/core/redux/reducers/api.js +190 -0
  137. package/libraries/core/redux/reducers/index.js +32 -0
  138. package/libraries/core/redux/reducers/notifications.js +16 -0
  139. package/libraries/core/redux/reducers/setting.js +99 -0
  140. package/libraries/core/redux/reducers/state.js +122 -0
  141. package/libraries/core/redux/selectors.js +123 -0
  142. package/libraries/core/redux/store.js +40 -0
  143. package/libraries/core/services/data.js +96 -0
  144. package/libraries/core/services/root-navigation.js +36 -0
  145. package/libraries/core/services/search.js +175 -0
  146. package/libraries/core-plugins/enums/replaceTypes.js +53 -0
  147. package/libraries/core-plugins/index.js +21 -0
  148. package/libraries/core-plugins/redux/actions/plugin.js +13 -0
  149. package/libraries/core-plugins/redux/reducers/plugin.js +210 -0
  150. package/libraries/icons-openasist/index.js +143 -0
  151. package/libraries/notifications/index.js +268 -0
  152. package/libraries/notifications/services/subscriber.service.js +123 -0
  153. package/libraries/react-native-webview-autoheight/README.md +47 -0
  154. package/libraries/react-native-webview-autoheight/index.js +140 -0
  155. package/libraries/react-native-webview-autoheight/package.json +37 -0
  156. package/libraries/react-native-webview-autoheight/utils.js +268 -0
  157. package/libraries/redux-offline/.eslintignore +1 -0
  158. package/libraries/redux-offline/.github/ISSUE_TEMPLATE/redux-offline-core-issues-template.md +25 -0
  159. package/libraries/redux-offline/.prettierrc +6 -0
  160. package/libraries/redux-offline/LICENSE +21 -0
  161. package/libraries/redux-offline/README.md +133 -0
  162. package/libraries/redux-offline/flow-typed/npm/redux-logger_vx.x.x.js +109 -0
  163. package/libraries/redux-offline/flow-typed/npm/redux_v4.x.x.js +100 -0
  164. package/libraries/redux-offline/lib/actions.js +46 -0
  165. package/libraries/redux-offline/lib/config.js +15 -0
  166. package/libraries/redux-offline/lib/constants.js +17 -0
  167. package/libraries/redux-offline/lib/defaults/defaultCommit.js +11 -0
  168. package/libraries/redux-offline/lib/defaults/defaultRollback.js +11 -0
  169. package/libraries/redux-offline/lib/defaults/detectNetwork.js +33 -0
  170. package/libraries/redux-offline/lib/defaults/detectNetwork.native.js +211 -0
  171. package/libraries/redux-offline/lib/defaults/discard.js +18 -0
  172. package/libraries/redux-offline/lib/defaults/effect.js +87 -0
  173. package/libraries/redux-offline/lib/defaults/index.js +32 -0
  174. package/libraries/redux-offline/lib/defaults/offlineStateLens.js +24 -0
  175. package/libraries/redux-offline/lib/defaults/persist.js +9 -0
  176. package/libraries/redux-offline/lib/defaults/persist.native.js +17 -0
  177. package/libraries/redux-offline/lib/defaults/persistAutoRehydrate.js +8 -0
  178. package/libraries/redux-offline/lib/defaults/queue.js +27 -0
  179. package/libraries/redux-offline/lib/defaults/retry.js +29 -0
  180. package/libraries/redux-offline/lib/index.js +115 -0
  181. package/libraries/redux-offline/lib/middleware.js +56 -0
  182. package/libraries/redux-offline/lib/offlineActionTracker.js +43 -0
  183. package/libraries/redux-offline/lib/send.js +112 -0
  184. package/libraries/redux-offline/lib/types.js +3 -0
  185. package/libraries/redux-offline/lib/updater.js +111 -0
  186. package/libraries/redux-offline/package.json +69 -0
  187. package/libraries/redux-offline/src/__tests__/defaults/discard.js +22 -0
  188. package/libraries/redux-offline/src/__tests__/defaults/effect.js +118 -0
  189. package/libraries/redux-offline/src/__tests__/index.js +116 -0
  190. package/libraries/redux-offline/src/__tests__/middleware.js +185 -0
  191. package/libraries/redux-offline/src/__tests__/offlineActionTracker.js +54 -0
  192. package/libraries/redux-offline/src/__tests__/send.js +208 -0
  193. package/libraries/redux-offline/src/actions.js +36 -0
  194. package/libraries/redux-offline/src/config.js +9 -0
  195. package/libraries/redux-offline/src/constants.js +18 -0
  196. package/libraries/redux-offline/src/defaults/defaultCommit.js +7 -0
  197. package/libraries/redux-offline/src/defaults/defaultRollback.js +7 -0
  198. package/libraries/redux-offline/src/defaults/detectNetwork.js +16 -0
  199. package/libraries/redux-offline/src/defaults/detectNetwork.native.js +148 -0
  200. package/libraries/redux-offline/src/defaults/discard.js +19 -0
  201. package/libraries/redux-offline/src/defaults/effect.js +86 -0
  202. package/libraries/redux-offline/src/defaults/index.js +25 -0
  203. package/libraries/redux-offline/src/defaults/offlineStateLens.js +11 -0
  204. package/libraries/redux-offline/src/defaults/persist.js +4 -0
  205. package/libraries/redux-offline/src/defaults/persist.native.js +9 -0
  206. package/libraries/redux-offline/src/defaults/persistAutoRehydrate.js +4 -0
  207. package/libraries/redux-offline/src/defaults/queue.js +20 -0
  208. package/libraries/redux-offline/src/defaults/retry.js +18 -0
  209. package/libraries/redux-offline/src/index.js +138 -0
  210. package/libraries/redux-offline/src/middleware.js +52 -0
  211. package/libraries/redux-offline/src/offlineActionTracker.js +40 -0
  212. package/libraries/redux-offline/src/send.js +111 -0
  213. package/libraries/redux-offline/src/types.js +127 -0
  214. package/libraries/redux-offline/src/updater.js +141 -0
  215. package/libraries/redux-offline/typings.d.ts +150 -0
  216. package/libraries/redux-offline/yarn.lock +6460 -0
  217. package/libraries/stored-state/index.js +155 -0
  218. package/package.json +68 -0
  219. package/views/Callmanager/index.js +148 -0
  220. package/views/Callmanager/styles.js +62 -0
  221. package/views/Canteens/index.js +383 -0
  222. package/views/Canteens/styles.js +89 -0
  223. package/views/Dashboard/index.js +176 -0
  224. package/views/Dashboard/styles.js +16 -0
  225. package/views/DashboardHtwk/index.js +197 -0
  226. package/views/DashboardHtwk/styles.js +24 -0
  227. package/views/Event/index.js +373 -0
  228. package/views/Event/styles.js +63 -0
  229. package/views/FeedList/index.js +165 -0
  230. package/views/FeedList/styles.js +15 -0
  231. package/views/FeedNews/index.js +243 -0
  232. package/views/FeedNews/styles.js +32 -0
  233. package/views/Flexmenu/index.js +185 -0
  234. package/views/Flexmenu/styles.js +62 -0
  235. package/views/FlexmenuWebview/index.js +167 -0
  236. package/views/FlexmenuWebview/styles.js +16 -0
  237. package/views/Howhy/index.js +151 -0
  238. package/views/Howhy/styles.js +11 -0
  239. package/views/Jobs/index.js +217 -0
  240. package/views/Jobs/styles.js +41 -0
  241. package/views/MainMenu/index.js +283 -0
  242. package/views/MainMenu/styles.js +36 -0
  243. package/views/NewsTabbar/index.js +164 -0
  244. package/views/NewsTabbar/styles.js +27 -0
  245. package/views/Opal/index.js +136 -0
  246. package/views/Opal/styles.js +11 -0
  247. package/views/PublicTransportTicket/index.js +173 -0
  248. package/views/PublicTransportTicket/styles.js +17 -0
  249. package/views/Search/index.js +186 -0
  250. package/views/Search/styles.js +67 -0
  251. package/views/SettingsAccessibility/index.js +148 -0
  252. package/views/SettingsAccessibility/styles.js +13 -0
  253. package/views/SettingsAppInfo/index.js +86 -0
  254. package/views/SettingsAppInfo/styles.js +18 -0
  255. package/views/SettingsCanteens/index.js +249 -0
  256. package/views/SettingsCanteens/styles.js +33 -0
  257. package/views/SettingsGeneral/index.js +173 -0
  258. package/views/SettingsGeneral/styles.js +28 -0
  259. package/views/SettingsNotifications/index.js +204 -0
  260. package/views/SettingsNotifications/styles.js +38 -0
  261. package/views/SettingsUser/index.js +170 -0
  262. package/views/SettingsUser/styles.js +17 -0
  263. package/views/TimetableCalendar/index.js +387 -0
  264. package/views/TimetableCalendar/styles.js +121 -0
  265. package/views/TimetableList/index.js +402 -0
  266. package/views/TimetableList/styles.js +55 -0
  267. package/views/Webviews/index.js +158 -0
  268. package/views/Webviews/styles.js +11 -0
@@ -0,0 +1,402 @@
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 { useState, useMemo, useCallback } from 'react';
16
+ import {
17
+ SafeAreaView,
18
+ StyleSheet,
19
+ View,
20
+ ScrollView,
21
+ TouchableOpacity,
22
+ RefreshControl,
23
+ ActivityIndicator,
24
+ Linking,
25
+ } from 'react-native';
26
+ import { connect } from 'react-redux'
27
+ import { TabView, TabBar, TabBarItem } from 'react-native-tab-view';
28
+ import { Appbar, useTheme, Text } from 'react-native-paper';
29
+ import { useTranslation } from 'react-i18next';
30
+ import { useFocusEffect } from '@react-navigation/native';
31
+
32
+ import { DateTime, Duration } from 'luxon';
33
+
34
+ import { onUpdateRefreshing, store } from '../../libraries/core';
35
+ import {
36
+ useCourses,
37
+ useTimetableCode,
38
+ ApiProviderNotInitializedError,
39
+ } from '../../context/context-timetable';
40
+ import AppbarComponent from '../../components/AppBar';
41
+ import OtherCoursesComponent from '../../components/OtherCourses';
42
+ import TimetableListComponent from '../../components/TimetableList';
43
+ import TimetableCodeInput from '../../components/TimetableCodeInput';
44
+ import CourseDetailDialog from '../../components/CourseDetailDialog';
45
+
46
+ import componentStyles from './styles';
47
+
48
+ /**
49
+ * Timetable View
50
+ *
51
+ * Displays the timetable, if the has imported one. If no timetable
52
+ * is available, the view will provide a import. The view also
53
+ * provides a button to import a new timetable.
54
+ *
55
+ * Parameters:
56
+ * - none
57
+ *
58
+ * Navigation-Parameters:
59
+ * - none
60
+ */
61
+ function TimetableViewList(props) {
62
+ const theme = useTheme();
63
+ const { t } = useTranslation();
64
+ const [selectedCourse, setSelectedCourse] = useState(null);
65
+
66
+ // Get all required constants from props
67
+ const {
68
+ settings: { settingsGeneral: { language } },
69
+ } = props;
70
+
71
+ const { colors, themeStyles, appSettings: { modules: { timetable: { downloadEnabled } } } } = theme;
72
+
73
+ const componentName = TimetableViewList.name;
74
+ const timetableSettings = theme?.appSettings?.modules?.timetable;
75
+ const disabledWeekdays = timetableSettings?.disabledWeekdays ?? [];
76
+ const weeksToRender = timetableSettings?.weeksToRender ?? 2;
77
+ // Jetziger Zeitpunkt
78
+ const now = DateTime.now();
79
+ // Zeitpunkt, der auf den Wochenanfang zeigt
80
+ const startDate = now.startOf('week');
81
+ // Zeitpunkt, der auf den letzten anzuzeigenen Tag zeigt
82
+ const endDate = startDate.plus({ weeks: weeksToRender }).endOf('week');
83
+
84
+ // Generiert die Tabs beginnend beim Wochenanfang bis zum letzten Tag der Ansicht
85
+ // Es werden die nicht anzuzeigenden Wochentage herausgefiltert
86
+ const daysTabViewRoutes = useMemo(
87
+ () => {
88
+ // Berechenen der Anzahl der zu zeigenden Tage bzw. Anzahl der Tabs
89
+ const daysToRender = Duration.fromDurationLike({ weeks: weeksToRender }).as('days');
90
+
91
+ // Erstellen der Tabs
92
+ return Array.from(
93
+ // Es wird ein Array erzeugt, welches so lang ist wie die Anzahl der zu zeigenden Tage
94
+ { length: daysToRender },
95
+ // Tabs anhand des Indexes berechnen
96
+ (_, index) => {
97
+
98
+ // Festlegen des Tages des entsprechenden Tabs beim Index
99
+ const currentDay = startDate
100
+ // Es wird der Start genommen und um index-viele Tage in die Zukunft verschoben
101
+ .plus({ days: index })
102
+ // Abschliesend wird die Uhrzeit auf 00:00, also den Anfang des Tages, gesetzt.
103
+ .startOf('day');
104
+
105
+ // Tab wird als Objekt zurückgeben
106
+ return {
107
+ // Der Schlüssel des Tabs ist das Datum des Tabs im ISO-Format
108
+ // Somit lässt sich über das Datum der entsprechende Tab aktivieren
109
+ key: currentDay.toISODate(),
110
+ // Für die weiter Verarbeitung, wird das Datum als Datumsobjekt mitgeben
111
+ // Dem Datumsobject wird die eingestellt Sprache gegeben
112
+ date: currentDay.setLocale(language),
113
+ }
114
+ }
115
+ )
116
+ .filter(dayRoute => !disabledWeekdays.includes(dayRoute.date.weekday))
117
+ },
118
+ [weeksToRender, disabledWeekdays, startDate, language]
119
+ );
120
+ // Create state for tab view index
121
+ const [daysTabViewActiveRouteIndex, setDaysTabViewActiveRouteIndex] = useState(() => {
122
+ // Present day
123
+ const today = DateTime.now().startOf('day');
124
+ // Search for the index of today or the day after. If no index can be found, -1 is taken.
125
+ let initialDayTabIndex = daysTabViewRoutes.findIndex(dayTab => dayTab.date >= today);
126
+ // If no index could be found, the last tab is taken.
127
+ // If only one week is rendered and the weekend days are switched off, no following day will be found.
128
+ initialDayTabIndex = initialDayTabIndex === -1 ? daysTabViewRoutes.length - 1 : initialDayTabIndex;
129
+ return initialDayTabIndex;
130
+ });
131
+
132
+ const [timetableCode] = useTimetableCode();
133
+ const [courses, refreshCourses] = useCourses();
134
+
135
+ /**
136
+ * State der speichert, ob die Code-Eingabe gezeigt werden soll.
137
+ *
138
+ * Der State kann 3 Zustände annehmen:
139
+ * - null : Es wurde noch kein Stundenplan importiert -> Code-Eingabe wird angezeigt
140
+ * - true : Der Nutzer möchte die Code-Eingabe sehen -> Code-Eingabe wird angezeigt
141
+ * - false: Die Nutzer möchte die Code-Eingabe nicht sehen -> Stundenplan wird angezeigt
142
+ *
143
+ * Der null-Wert wird benutzt um festzustellen, dass die App die Code-Eingabe anzeigt, weil bisher kein Stundenplan importiert wurde.
144
+ * Somit kann nach dem Import geprüft werden, ob der State den null-Wert hält und automatisch zu den Stundenplan schalten.
145
+ */
146
+ const [showImport, setShowImport] = useState(timetableCode === null && courses === null ? true : false);
147
+ const [coursesRefreshing, setCoursesRefreshing] = useState(false);
148
+
149
+ // Generate styles. Will be generated only if not present or the theme property changes.
150
+ const styles = useMemo(
151
+ () => StyleSheet.create(componentStyles(theme)),
152
+ [theme]
153
+ )
154
+
155
+ const otherCourses = courses?.[undefined] ?? [];
156
+ const activeTabDate = daysTabViewRoutes[daysTabViewActiveRouteIndex]?.date;
157
+ const activeTabWeek = activeTabDate.weekNumber;
158
+
159
+ // Refreshen der Vorlesungen, wenn die View angeziegt wird und den Fokus vom nutzer bekommt.
160
+ useFocusEffect(
161
+ useCallback(
162
+ () => {
163
+ refreshCourses(startDate.toISODate(), endDate.toISODate())
164
+ .catch((reason) => {
165
+ if (reason instanceof ApiProviderNotInitializedError) {
166
+ console.error(componentName, ': ', reason);
167
+ } else {
168
+ console.debug(componentName, ': ', reason);
169
+ }
170
+ });
171
+ },
172
+ []
173
+ )
174
+ )
175
+
176
+ /*
177
+ Depending on the existence of a timetable, either the timetable or the view for the input of a timetablecode will be rendered
178
+ To decide which components have to rendered, the flag showImport is used.
179
+ If its value is true, there already is an imported timetable as well as a list of courses
180
+ and the function for rendering the timetable-tabview(renderTabView) is called.
181
+ Otherwise, the function for entering a timetablecode will be called(renderTimetableCodeInput)
182
+ */
183
+ return (
184
+ <SafeAreaView style={[styles.container, themeStyles.appSafeAreaContainer]}>
185
+ <AppbarComponent {...props}
186
+ title={t('timetable:title')}
187
+ subtitle={`${t('timetable:weekNumber', { kw: activeTabWeek })} / ${t(activeTabWeek % 2 === 0 ? 'timetable:evenWeek' : 'timetable:oddWeek')}`}
188
+ // in addition to the selection of the icon for the right Action in the app-bar the color for the icon also has to be defined
189
+ rightAction={
190
+ <>
191
+ {
192
+ downloadEnabled
193
+ ? <Appbar.Action
194
+ icon={'download'}
195
+ onPress={
196
+ async () => {
197
+ const { modules: { timetable: { downloadUrl } } } = props.theme.appSettings;
198
+ await Linking.openURL(downloadUrl + timetableCode);
199
+ }
200
+ }
201
+ color={colors.appbarIconColor}
202
+ accessibilityLabel={t('accessibility:timetable:downloadTimetableButton')}
203
+ />
204
+ : null
205
+ }
206
+ <Appbar.Action
207
+ icon={showImport ? 'table' : 'table-plus'}
208
+ color={colors.appbarIconColor}
209
+ onPress={
210
+ () => setShowImport(currentValue => !currentValue)
211
+ }
212
+ accessibilityLabel={t(
213
+ showImport
214
+ ? 'accessibility:timetable:showImportButton'
215
+ : 'accessibility:timetable:showTimetableButton'
216
+ )}
217
+ />
218
+ </>
219
+ }
220
+ />
221
+ {
222
+ !(showImport) // !FIXME: If-Cases sollten getauscht werden, damit Code einfacher wird
223
+ ? <View style={themeStyles.container}>
224
+ <TabView
225
+ style={props.style}
226
+ navigationState={{ index: daysTabViewActiveRouteIndex, routes: daysTabViewRoutes }}
227
+ onIndexChange={setDaysTabViewActiveRouteIndex}
228
+ renderTabBar={
229
+ (props) =>
230
+ <TabBar
231
+ {...props}
232
+ scrollEnabled
233
+ style={themeStyles.tabs}
234
+ labelStyle={themeStyles.tab}
235
+ activeColor={themeStyles.tabs.activeColor}
236
+ inactiveColor={themeStyles.tabs.inactiveColor}
237
+ indicatorStyle={themeStyles.tabIndicator}
238
+ tabStyle={{ width: 'auto', paddingHorizontal: 20 }}
239
+ renderTabBarItem={({ route, navigationState, ...rest }) =>
240
+ <TabBarItem
241
+ {...rest}
242
+ key={route.key}
243
+ route={route}
244
+ navigationState={navigationState}
245
+ labelStyle={themeStyles.tab}
246
+ activeColor={themeStyles.tabs.activeColor}
247
+ inactiveColor={themeStyles.tabs.inactiveColor}
248
+ // Die einbindung von moment.js zum Anzeigen des Wochentages sollte langfristig entfernt werden.
249
+ // Funktioniert die Luxon funktionalität der Wochenanzeige nicht unter iOS datetime.toFormat('ccc')
250
+ label={
251
+ // Generieren das Tab-Textes
252
+ ({ route }) => {
253
+ // Datumsobject aus dem Tab holen
254
+ const date = route.date;
255
+ // Kurzbezeichnung des Wochentages bestimmen
256
+ const shortWeekDay = t(`common:isoWeekDay:${date.weekday}:short`); // Falls hermes Intl soweit ist, lieber folgende Zeile verwenden: const shortWeekDay = date.weekdayShort;
257
+ // Datum, bestehend aus Tag und Monat, bestimmen
258
+ const localeDate = date.toLocaleString(
259
+ {
260
+ day: '2-digit',
261
+ month: '2-digit',
262
+ }
263
+ );
264
+
265
+ // Tab-Text aus Wochentag und Datum generieren
266
+ return <Text>{shortWeekDay}, {localeDate}</Text>;
267
+ }
268
+ }
269
+ accessible={true}
270
+ accessibilityLabel={route.date.toLocaleString(DateTime.DATE_FULL)}
271
+ />
272
+ }
273
+ />
274
+ }
275
+ renderScene={
276
+ ({ route }) => {
277
+ const dayIsoDate = route.key;
278
+ const coursesOfDay = courses?.[dayIsoDate];
279
+
280
+ return (
281
+ <View style={themeStyles.container}>
282
+ <View style={styles.horizontalSeperator} />
283
+ <ScrollView
284
+ refreshControl={
285
+ <RefreshControl
286
+ refreshing={coursesRefreshing}
287
+ onRefresh={
288
+ () => {
289
+ setCoursesRefreshing(true);
290
+ refreshCourses(dayIsoDate, dayIsoDate)
291
+ .finally(() => setCoursesRefreshing(false));
292
+ }
293
+ }
294
+ />
295
+ }>
296
+ <View style={styles.renderList}>
297
+ {
298
+ coursesOfDay?.length
299
+ ? coursesOfDay.map(
300
+ (course, index) => {
301
+ const courseTime = course?.times?.[0];
302
+
303
+ return (
304
+ <TimetableListComponent
305
+ {...props}
306
+ key={`${course?.title?.data}${course?.type?.data}${courseTime.start}${courseTime.end}`}
307
+ course={course}
308
+ times={courseTime}
309
+ onCourseSelected={course => setSelectedCourse(course)}
310
+ />
311
+ )
312
+ }
313
+ )
314
+ : <View style={styles.emptyListContainer}>
315
+ <Text style={styles.emptyText}>{t('timetable:noEvents')}</Text>
316
+ </View>
317
+ }
318
+ </View>
319
+ </ScrollView>
320
+ </View>
321
+ );
322
+ }
323
+ }
324
+ lazy
325
+ lazyPreloadDistance={2}
326
+ renderLazyPlaceholder={(route) =>
327
+ <View style={styles.centerContainer}>
328
+ <ActivityIndicator
329
+ style={styles.activity}
330
+ size={'large'}
331
+ color={theme.colors.loadingIndicator}
332
+ />
333
+ </View>
334
+ }
335
+ />
336
+ {
337
+ otherCourses?.length
338
+ ? <TouchableOpacity
339
+ style={styles.otherContainer}
340
+ onPress={
341
+ () => {
342
+ // Never provide props directly if you are using translations in this or a parent component
343
+ const otherCoursesComponentProps = { navigation: { ...props.navigation } };
344
+
345
+ store.dispatch(
346
+ {
347
+ type: 'UPDATE_MODAL_CONTENT',
348
+ modalContent: (
349
+ <View style={styles.modalContainer}>
350
+ <OtherCoursesComponent
351
+ {...otherCoursesComponentProps}
352
+ course={otherCourses}
353
+ />
354
+ </View>
355
+ )
356
+ }
357
+ );
358
+ props.navigation.navigate('Modal');
359
+ }
360
+ }
361
+ >
362
+ <Text
363
+ style={styles.otherTitle}
364
+ >
365
+ {t('timetable:moreEvents')}
366
+ </Text>
367
+ </TouchableOpacity>
368
+ : null
369
+ }
370
+
371
+
372
+ <CourseDetailDialog
373
+ course={selectedCourse}
374
+ visible={selectedCourse ? true : false}
375
+ onClose={() => setSelectedCourse(null)}
376
+ onDismiss={() => setSelectedCourse(null)}
377
+ />
378
+
379
+ </View>
380
+ : <TimetableCodeInput
381
+ onImportSuccessfullyFinished={
382
+ // Wenn Stundenplan erfolgreich importiert wurde, wird der Stundenplan angezeigt
383
+ () => setShowImport(false)
384
+ }
385
+ />
386
+ }
387
+ </SafeAreaView>
388
+ );
389
+ }
390
+
391
+ const mapStateToProps = state => {
392
+ return {
393
+ pluginComponent: state.pluginReducer.timetable.component,
394
+ pluginStyles: state.pluginReducer.timetable.styles,
395
+ courses: state.apiReducer.courses,
396
+ coursesStatus: state.apiReducer.coursesStatus,
397
+ refreshing: state.stateReducer.refreshing,
398
+ settings: state.settingReducer
399
+ };
400
+ };
401
+
402
+ export default connect(mapStateToProps, { onUpdateRefreshing })(TimetableViewList)
@@ -0,0 +1,55 @@
1
+ import {Dimensions} from "react-native";
2
+
3
+ export default function(theme) {
4
+ const width = Dimensions.get('window').width;
5
+ return {
6
+ horizontalSeperator: {
7
+ height: 1,
8
+ width: "100%",
9
+ backgroundColor: theme.colors.listSeperator
10
+ },
11
+ otherContainer: {
12
+ width: width,
13
+ height: "10%",
14
+ backgroundColor: theme.colors.primary,
15
+ shadowColor: theme.colors.shadow,
16
+ shadowOffset: {
17
+ width: 0,
18
+ height: 1,
19
+ },
20
+ shadowOpacity: 0.5,
21
+ shadowRadius: 10,
22
+ elevation: 3,
23
+ justifyContent: 'center'
24
+ },
25
+ otherTitle: {
26
+ fontSize: theme.fontSizes.xxl,
27
+ ...theme.fonts.medium,
28
+ textAlign: "center",
29
+ padding: theme.paddings.small,
30
+ color: theme.colors.primaryText,
31
+ },
32
+ container: {
33
+ flex: 1,
34
+ backgroundColor: theme.colors.contentBackground,
35
+ },
36
+ modalContainer: {
37
+ flex: 1,
38
+ },
39
+ renderList: {
40
+ marginBottom: theme.paddings.small
41
+ },
42
+ emptyListContainer: {
43
+ alignItems: "center",
44
+ justifyContent: "center",
45
+ width: "100%",
46
+ height: 400,
47
+ padding: theme.paddings.default,
48
+ marginTop: theme.paddings.default
49
+ },
50
+ emptyText: {
51
+ textAlign: "center",
52
+ fontSize: theme.fontSizes.title
53
+ }
54
+ }
55
+ };
@@ -0,0 +1,158 @@
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 React from 'react';
16
+ import {SafeAreaView, StyleSheet, ActivityIndicator, View, Linking} from 'react-native';
17
+ import {connect} from 'react-redux'
18
+ import {Appbar, withTheme} from "react-native-paper";
19
+ import { WebView } from 'react-native-webview';
20
+ import merge from 'lodash/merge';
21
+
22
+ import componentStyles from "./styles";
23
+ import AppbarComponent from '../../components/AppBar';
24
+ import IconsOpenasist from '../../libraries/icons-openasist';
25
+
26
+
27
+ /**
28
+ * Webview View
29
+ *
30
+ * Use this víew to show a webpage (via url).
31
+ *
32
+ * Parameters:
33
+ * - none
34
+ *
35
+ * Navigation-Parameters:
36
+ * - title: Header title
37
+ * - url: Webpage Url
38
+ */
39
+ class WebviewsView extends React.Component {
40
+ static navigationOptions = {
41
+ header: null
42
+ };
43
+
44
+ state = {
45
+ refreshing: false,
46
+ };
47
+
48
+ // Styles of this component
49
+ styles;
50
+
51
+
52
+
53
+ webView = {
54
+ canGoBack: false,
55
+ ref: null,
56
+ };
57
+
58
+ jsScript = `
59
+ const meta = document.createElement('meta');
60
+ meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0');
61
+ meta.setAttribute('name', 'viewport');
62
+ document.head.appendChild(meta);
63
+ `;
64
+
65
+ constructor(props) {
66
+ super(props);
67
+ // ------------------------------------------------------------------------
68
+ // PLUGIN FUNCTIONALITY
69
+ // ------------------------------------------------------------------------
70
+
71
+ const {pluginStyles, theme} = this.props;
72
+ this.styles = componentStyles(theme);
73
+
74
+ if (pluginStyles) {
75
+ this.styles = merge(this.styles, pluginStyles);
76
+ }
77
+
78
+ this.styles = StyleSheet.create(this.styles);
79
+
80
+ // ------------------------------------------------------------------------
81
+ }
82
+
83
+ /**
84
+ * Intercept URL loading in the WebView.
85
+ * If the base URL of the event is different from the initial base URL, open it in the external browser.
86
+ * Still allows url navigation with # values in the URL by comparing the base URL of the event with the base URL of the initial URL.
87
+ */
88
+ onShouldStartLoadWithRequest = (event) => {
89
+ const {url} = this.props.route.params;
90
+ const baseUrl = url.split('#')[0];
91
+ const eventBaseUrl = event.url.split('#')[0];
92
+
93
+ if (eventBaseUrl !== baseUrl) {
94
+ Linking.openURL(event.url);
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+
100
+ render() {
101
+ const {route} = this.props;
102
+ const {colors, themeStyles, customScript} = this.props.theme;
103
+ // The language is necessary because it is needed in the header in the source-prop of the webview elemnent
104
+ // to display the website in the selected system-language
105
+ const {language} = this.props.settings.settingsGeneral
106
+
107
+ // Get the current title of the element, that should be displayed e.g. Imprint, data policy, etc.
108
+ const title = route.params && route.params.title || null;
109
+ // Get the url for the current element defined in the settings
110
+ const url = route.params && route.params.url || null;
111
+
112
+ // The returned View contains a Appbar followed by the webview that calls the websites provided in the URL
113
+ return (
114
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
115
+ <View style={{zIndex: 100, position: 'relative'}}>
116
+ <AppbarComponent {...this.props}
117
+ title={title}
118
+ leftAction={
119
+ <Appbar.Action
120
+ icon={props => <IconsOpenasist {...props} icon={'back'} color={colors.primaryText} /> }
121
+ onPress={() => {
122
+ if (this.webView.canGoBack) {
123
+ this.webView.ref.goBack();
124
+ } else {
125
+ this.props.navigation.goBack(null);
126
+ }
127
+ }} />
128
+ }
129
+ rightAction={<Appbar.Action icon="refresh" onPress={() => this.webView.ref.reload()}/>}/>
130
+ </View>
131
+ <WebView
132
+ ref={ref => this.webView.ref = ref}
133
+ // In addition to only providing the url as a source, headers can be defined that will contain additional information
134
+ // In this case the header provides information about the current system-language in order to display a given translation of the website
135
+ source={{ uri: url, headers: {
136
+ "Accept-Language": `${language}`,
137
+ } }}
138
+ startInLoadingState={true}
139
+ renderLoading={() => <ActivityIndicator style={this.styles.activity} size="large" color={colors.loadingIndicator} />}
140
+ onNavigationStateChange={(navState) => { this.webView.canGoBack = navState.canGoBack; }}
141
+ injectedJavaScript={this.jsScript + customScript}
142
+ onMessage={() => {}}
143
+ onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
144
+ />
145
+ </SafeAreaView>
146
+ );
147
+ }
148
+ }
149
+
150
+ const mapStateToProps = state => {
151
+ return {
152
+ // The settings are necessary to determine the current system-language so that the websites in the webview can be
153
+ // translated in the selected language
154
+ settings: state.settingReducer
155
+ };
156
+ };
157
+
158
+ export default connect(mapStateToProps, null)(withTheme(WebviewsView))
@@ -0,0 +1,11 @@
1
+ export default function(theme) {
2
+ return {
3
+ container: {
4
+ flex: 1,
5
+ backgroundColor: theme.colors.background,
6
+ },
7
+ activity: {
8
+ padding: 20
9
+ }
10
+ }
11
+ };