Browse Source

Improved project structure

Arnaud Vergnet 4 years ago
parent
commit
7e90b80ca2

+ 6
- 6
App.js View File

@@ -2,17 +2,17 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {Platform, StatusBar} from 'react-native';
5
-import LocaleManager from './utils/LocaleManager';
6
-import AsyncStorageManager from "./utils/AsyncStorageManager";
5
+import LocaleManager from './managers/LocaleManager';
6
+import AsyncStorageManager from "./managers/AsyncStorageManager";
7 7
 import CustomIntroSlider from "./components/CustomIntroSlider";
8 8
 import {SplashScreen} from 'expo';
9
-import ThemeManager from './utils/ThemeManager';
9
+import ThemeManager from './managers/ThemeManager';
10 10
 import {NavigationContainer} from '@react-navigation/native';
11 11
 import {createStackNavigator} from '@react-navigation/stack';
12 12
 import DrawerNavigator from './navigation/DrawerNavigator';
13
-import NotificationsManager from "./utils/NotificationsManager";
13
+import {initExpoToken} from "./utils/Notifications";
14 14
 import {Provider as PaperProvider} from 'react-native-paper';
15
-import AprilFoolsManager from "./utils/AprilFoolsManager";
15
+import AprilFoolsManager from "./managers/AprilFoolsManager";
16 16
 import Update from "./constants/Update";
17 17
 
18 18
 type Props = {};
@@ -90,7 +90,7 @@ export default class App extends React.Component<Props, State> {
90 90
         // Wait for custom fonts to be loaded before showing the app
91 91
         await AsyncStorageManager.getInstance().loadPreferences();
92 92
         ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
93
-        await NotificationsManager.initExpoToken();
93
+        await initExpoToken();
94 94
         this.onLoadFinished();
95 95
     }
96 96
 

+ 210
- 0
__tests__/utils/PlanningEventManager.test.js View File

@@ -0,0 +1,210 @@
1
+import React from 'react';
2
+import * as Planning from "../../utils/Planning";
3
+
4
+test('isDescriptionEmpty', () => {
5
+    expect(Planning.isDescriptionEmpty("")).toBeTrue();
6
+    expect(Planning.isDescriptionEmpty("   ")).toBeTrue();
7
+    // noinspection CheckTagEmptyBody
8
+    expect(Planning.isDescriptionEmpty("<p></p>")).toBeTrue();
9
+    expect(Planning.isDescriptionEmpty("<p>   </p>")).toBeTrue();
10
+    expect(Planning.isDescriptionEmpty("<p><br></p>")).toBeTrue();
11
+    expect(Planning.isDescriptionEmpty("<p><br></p><p><br></p>")).toBeTrue();
12
+    expect(Planning.isDescriptionEmpty("<p><br><br><br></p>")).toBeTrue();
13
+    expect(Planning.isDescriptionEmpty("<p><br>")).toBeTrue();
14
+    expect(Planning.isDescriptionEmpty(null)).toBeTrue();
15
+    expect(Planning.isDescriptionEmpty(undefined)).toBeTrue();
16
+    expect(Planning.isDescriptionEmpty("coucou")).toBeFalse();
17
+    expect(Planning.isDescriptionEmpty("<p>coucou</p>")).toBeFalse();
18
+});
19
+
20
+test('isEventDateStringFormatValid', () => {
21
+    expect(Planning.isEventDateStringFormatValid("2020-03-21 09:00")).toBeTrue();
22
+    expect(Planning.isEventDateStringFormatValid("3214-64-12 01:16")).toBeTrue();
23
+
24
+    expect(Planning.isEventDateStringFormatValid("3214-64-12 01:16:00")).toBeFalse();
25
+    expect(Planning.isEventDateStringFormatValid("3214-64-12 1:16")).toBeFalse();
26
+    expect(Planning.isEventDateStringFormatValid("3214-f4-12 01:16")).toBeFalse();
27
+    expect(Planning.isEventDateStringFormatValid("sqdd 09:00")).toBeFalse();
28
+    expect(Planning.isEventDateStringFormatValid("2020-03-21")).toBeFalse();
29
+    expect(Planning.isEventDateStringFormatValid("2020-03-21 truc")).toBeFalse();
30
+    expect(Planning.isEventDateStringFormatValid("3214-64-12 1:16:65")).toBeFalse();
31
+    expect(Planning.isEventDateStringFormatValid("garbage")).toBeFalse();
32
+    expect(Planning.isEventDateStringFormatValid("")).toBeFalse();
33
+    expect(Planning.isEventDateStringFormatValid(undefined)).toBeFalse();
34
+    expect(Planning.isEventDateStringFormatValid(null)).toBeFalse();
35
+});
36
+
37
+test('stringToDate', () => {
38
+    let testDate = new Date();
39
+    expect(Planning.stringToDate(undefined)).toBeNull();
40
+    expect(Planning.stringToDate("")).toBeNull();
41
+    expect(Planning.stringToDate("garbage")).toBeNull();
42
+    expect(Planning.stringToDate("2020-03-21")).toBeNull();
43
+    expect(Planning.stringToDate("09:00:00")).toBeNull();
44
+    expect(Planning.stringToDate("2020-03-21 09:g0")).toBeNull();
45
+    expect(Planning.stringToDate("2020-03-21 09:g0:")).toBeNull();
46
+    testDate.setFullYear(2020, 2, 21);
47
+    testDate.setHours(9, 0, 0, 0);
48
+    expect(Planning.stringToDate("2020-03-21 09:00")).toEqual(testDate);
49
+    testDate.setFullYear(2020, 0, 31);
50
+    testDate.setHours(18, 30, 0, 0);
51
+    expect(Planning.stringToDate("2020-01-31 18:30")).toEqual(testDate);
52
+    testDate.setFullYear(2020, 50, 50);
53
+    testDate.setHours(65, 65, 0, 0);
54
+    expect(Planning.stringToDate("2020-51-50 65:65")).toEqual(testDate);
55
+});
56
+
57
+test('getFormattedEventTime', () => {
58
+    expect(Planning.getFormattedEventTime(null, null))
59
+        .toBe('/ - /');
60
+    expect(Planning.getFormattedEventTime(undefined, undefined))
61
+        .toBe('/ - /');
62
+    expect(Planning.getFormattedEventTime("20:30", "23:00"))
63
+        .toBe('/ - /');
64
+    expect(Planning.getFormattedEventTime("2020-03-30", "2020-03-31"))
65
+        .toBe('/ - /');
66
+
67
+
68
+    expect(Planning.getFormattedEventTime("2020-03-21 09:00", "2020-03-21 09:00"))
69
+        .toBe('09:00');
70
+    expect(Planning.getFormattedEventTime("2020-03-21 09:00", "2020-03-22 17:00"))
71
+        .toBe('09:00 - 23:59');
72
+    expect(Planning.getFormattedEventTime("2020-03-30 20:30", "2020-03-30 23:00"))
73
+        .toBe('20:30 - 23:00');
74
+});
75
+
76
+test('getDateOnlyString', () => {
77
+    expect(Planning.getDateOnlyString("2020-03-21 09:00")).toBe("2020-03-21");
78
+    expect(Planning.getDateOnlyString("2021-12-15 09:00")).toBe("2021-12-15");
79
+    expect(Planning.getDateOnlyString("2021-12-o5 09:00")).toBeNull();
80
+    expect(Planning.getDateOnlyString("2021-12-15 09:")).toBeNull();
81
+    expect(Planning.getDateOnlyString("2021-12-15")).toBeNull();
82
+    expect(Planning.getDateOnlyString("garbage")).toBeNull();
83
+});
84
+
85
+test('isEventBefore', () => {
86
+    expect(Planning.isEventBefore(
87
+        "2020-03-21 09:00", "2020-03-21 10:00")).toBeTrue();
88
+    expect(Planning.isEventBefore(
89
+        "2020-03-21 10:00", "2020-03-21 10:15")).toBeTrue();
90
+    expect(Planning.isEventBefore(
91
+        "2020-03-21 10:15", "2021-03-21 10:15")).toBeTrue();
92
+    expect(Planning.isEventBefore(
93
+        "2020-03-21 10:15", "2020-05-21 10:15")).toBeTrue();
94
+    expect(Planning.isEventBefore(
95
+        "2020-03-21 10:15", "2020-03-30 10:15")).toBeTrue();
96
+
97
+    expect(Planning.isEventBefore(
98
+        "2020-03-21 10:00", "2020-03-21 10:00")).toBeFalse();
99
+    expect(Planning.isEventBefore(
100
+        "2020-03-21 10:00", "2020-03-21 09:00")).toBeFalse();
101
+    expect(Planning.isEventBefore(
102
+        "2020-03-21 10:15", "2020-03-21 10:00")).toBeFalse();
103
+    expect(Planning.isEventBefore(
104
+        "2021-03-21 10:15", "2020-03-21 10:15")).toBeFalse();
105
+    expect(Planning.isEventBefore(
106
+        "2020-05-21 10:15", "2020-03-21 10:15")).toBeFalse();
107
+    expect(Planning.isEventBefore(
108
+        "2020-03-30 10:15", "2020-03-21 10:15")).toBeFalse();
109
+
110
+    expect(Planning.isEventBefore(
111
+        "garbage", "2020-03-21 10:15")).toBeFalse();
112
+    expect(Planning.isEventBefore(
113
+        undefined, undefined)).toBeFalse();
114
+});
115
+
116
+test('dateToString', () => {
117
+    let testDate = new Date();
118
+    testDate.setFullYear(2020, 2, 21);
119
+    testDate.setHours(9, 0, 0, 0);
120
+    expect(Planning.dateToString(testDate)).toBe("2020-03-21 09:00");
121
+    testDate.setFullYear(2021, 0, 12);
122
+    testDate.setHours(9, 10, 0, 0);
123
+    expect(Planning.dateToString(testDate)).toBe("2021-01-12 09:10");
124
+    testDate.setFullYear(2022, 11, 31);
125
+    testDate.setHours(9, 10, 15, 0);
126
+    expect(Planning.dateToString(testDate)).toBe("2022-12-31 09:10");
127
+});
128
+
129
+test('generateEmptyCalendar', () => {
130
+    jest.spyOn(Date, 'now')
131
+        .mockImplementation(() =>
132
+            new Date('2020-01-14T00:00:00.000Z').getTime()
133
+        );
134
+    let calendar = Planning.generateEmptyCalendar(1);
135
+    expect(calendar).toHaveProperty("2020-01-14");
136
+    expect(calendar).toHaveProperty("2020-01-20");
137
+    expect(calendar).toHaveProperty("2020-02-10");
138
+    expect(Object.keys(calendar).length).toBe(32);
139
+    calendar = Planning.generateEmptyCalendar(3);
140
+    expect(calendar).toHaveProperty("2020-01-14");
141
+    expect(calendar).toHaveProperty("2020-01-20");
142
+    expect(calendar).toHaveProperty("2020-02-10");
143
+    expect(calendar).toHaveProperty("2020-02-14");
144
+    expect(calendar).toHaveProperty("2020-03-20");
145
+    expect(calendar).toHaveProperty("2020-04-12");
146
+    expect(Object.keys(calendar).length).toBe(92);
147
+});
148
+
149
+test('pushEventInOrder', () => {
150
+    let eventArray = [];
151
+    let event1 = {date_begin: "2020-01-14 09:15"};
152
+    Planning.pushEventInOrder(eventArray, event1);
153
+    expect(eventArray.length).toBe(1);
154
+    expect(eventArray[0]).toBe(event1);
155
+
156
+    let event2 = {date_begin: "2020-01-14 10:15"};
157
+    Planning.pushEventInOrder(eventArray, event2);
158
+    expect(eventArray.length).toBe(2);
159
+    expect(eventArray[0]).toBe(event1);
160
+    expect(eventArray[1]).toBe(event2);
161
+
162
+    let event3 = {date_begin: "2020-01-14 10:15", title: "garbage"};
163
+    Planning.pushEventInOrder(eventArray, event3);
164
+    expect(eventArray.length).toBe(3);
165
+    expect(eventArray[0]).toBe(event1);
166
+    expect(eventArray[1]).toBe(event2);
167
+    expect(eventArray[2]).toBe(event3);
168
+
169
+    let event4 = {date_begin: "2020-01-13 09:00"};
170
+    Planning.pushEventInOrder(eventArray, event4);
171
+    expect(eventArray.length).toBe(4);
172
+    expect(eventArray[0]).toBe(event4);
173
+    expect(eventArray[1]).toBe(event1);
174
+    expect(eventArray[2]).toBe(event2);
175
+    expect(eventArray[3]).toBe(event3);
176
+});
177
+
178
+test('generateEventAgenda', () => {
179
+    jest.spyOn(Date, 'now')
180
+        .mockImplementation(() =>
181
+            new Date('2020-01-14T00:00:00.000Z').getTime()
182
+        );
183
+    let eventList = [
184
+        {date_begin: "2020-01-14 09:15"},
185
+        {date_begin: "2020-02-01 09:15"},
186
+        {date_begin: "2020-01-15 09:15"},
187
+        {date_begin: "2020-02-01 09:30"},
188
+        {date_begin: "2020-02-01 08:30"},
189
+    ];
190
+    const calendar = Planning.generateEventAgenda(eventList, 2);
191
+    expect(calendar["2020-01-14"].length).toBe(1);
192
+    expect(calendar["2020-01-14"][0]).toBe(eventList[0]);
193
+    expect(calendar["2020-01-15"].length).toBe(1);
194
+    expect(calendar["2020-01-15"][0]).toBe(eventList[2]);
195
+    expect(calendar["2020-02-01"].length).toBe(3);
196
+    expect(calendar["2020-02-01"][0]).toBe(eventList[4]);
197
+    expect(calendar["2020-02-01"][1]).toBe(eventList[1]);
198
+    expect(calendar["2020-02-01"][2]).toBe(eventList[3]);
199
+});
200
+
201
+test('getCurrentDateString', () => {
202
+    jest.spyOn(Date, 'now')
203
+        .mockImplementation(() => {
204
+            let date = new Date();
205
+            date.setFullYear(2020, 0, 14);
206
+            date.setHours(15, 30, 54, 65);
207
+            return date.getTime();
208
+        });
209
+    expect(Planning.getCurrentDateString()).toBe('2020-01-14 15:30');
210
+});

+ 4
- 4
components/PreviewEventDashboardItem.js View File

@@ -5,7 +5,7 @@ import {StyleSheet, View} from "react-native";
5 5
 import HTML from "react-native-render-html";
6 6
 import i18n from "i18n-js";
7 7
 import {Avatar, Button, Card, withTheme} from 'react-native-paper';
8
-import PlanningEventManager from "../utils/PlanningEventManager";
8
+import {getFormattedEventTime, isDescriptionEmpty} from "../utils/Planning";
9 9
 
10 10
 /**
11 11
  * Component used to display an event preview if an event is available
@@ -17,7 +17,7 @@ function PreviewEventDashboardItem(props) {
17 17
     const {colors} = props.theme;
18 18
     const isEmpty = props.event === undefined
19 19
         ? true
20
-        : PlanningEventManager.isDescriptionEmpty(props.event['description']);
20
+        : isDescriptionEmpty(props.event['description']);
21 21
 
22 22
     if (props.event !== undefined && props.event !== null) {
23 23
         const hasImage = props.event['logo'] !== '' && props.event['logo'] !== null;
@@ -34,12 +34,12 @@ function PreviewEventDashboardItem(props) {
34 34
                 {hasImage ?
35 35
                     <Card.Title
36 36
                         title={props.event['title']}
37
-                        subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
37
+                        subtitle={getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
38 38
                         left={getImage}
39 39
                     /> :
40 40
                     <Card.Title
41 41
                         title={props.event['title']}
42
-                        subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
42
+                        subtitle={getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
43 43
                     />}
44 44
                 {!isEmpty ?
45 45
                     <Card.Content style={styles.content}>

+ 2
- 5
components/WebSectionList.js View File

@@ -1,7 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import WebDataManager from "../utils/WebDataManager";
4
+import {readData} from "../utils/WebData";
5 5
 import i18n from "i18n-js";
6 6
 import {Snackbar} from 'react-native-paper';
7 7
 import {RefreshControl, SectionList, View} from "react-native";
@@ -42,8 +42,6 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
42 42
         updateData: 0,
43 43
     };
44 44
 
45
-    webDataManager: WebDataManager;
46
-
47 45
     refreshInterval: IntervalID;
48 46
     lastRefresh: Date;
49 47
 
@@ -79,7 +77,6 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
79 77
      * Allows to detect when the screen is focused
80 78
      */
81 79
     componentDidMount() {
82
-        this.webDataManager = new WebDataManager(this.props.fetchUrl);
83 80
         const onScreenFocus = this.onScreenFocus.bind(this);
84 81
         const onScreenBlur = this.onScreenBlur.bind(this);
85 82
         this.props.navigation.addListener('focus', onScreenFocus);
@@ -144,7 +141,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
144 141
             canRefresh = true;
145 142
         if (canRefresh) {
146 143
             this.setState({refreshing: true});
147
-            this.webDataManager.readData()
144
+            readData(this.props.fetchUrl)
148 145
                 .then(this.onFetchSuccess)
149 146
                 .catch(this.onFetchError);
150 147
         }

+ 1
- 1
coverage/clover.xml View File

@@ -2,7 +2,7 @@
2 2
 <coverage generated="1584889501493" clover="3.2.0">
3 3
   <project timestamp="1584889501493" name="All files">
4 4
     <metrics statements="65" coveredstatements="65" conditionals="39" coveredconditionals="36" methods="11" coveredmethods="11" elements="115" coveredelements="112" complexity="0" loc="65" ncloc="65" packages="1" files="1" classes="1"/>
5
-    <file name="PlanningEventManager.js" path="/home/keplyx/expo-projects/application-amicale/utils/PlanningEventManager.js">
5
+    <file name="Planning.js" path="/home/keplyx/expo-projects/application-amicale/utils/Planning.js">
6 6
       <metrics statements="65" coveredstatements="65" conditionals="39" coveredconditionals="36" methods="11" coveredmethods="11"/>
7 7
       <line num="18" count="1" type="stmt"/>
8 8
       <line num="27" count="1" type="stmt"/>

+ 12
- 13
coverage/lcov-report/PlanningEventManager.js.html View File

@@ -3,7 +3,7 @@
3 3
 <html lang="en">
4 4
 
5 5
 <head>
6
-    <title>Code coverage report for PlanningEventManager.js</title>
6
+    <title>Code coverage report for Planning.js</title>
7 7
     <meta charset="utf-8" />
8 8
     <link rel="stylesheet" href="prettify.css" />
9 9
     <link rel="stylesheet" href="base.css" />
@@ -15,41 +15,41 @@
15 15
         }
16 16
     </style>
17 17
 </head>
18
-    
18
+
19 19
 <body>
20 20
 <div class='wrapper'>
21 21
     <div class='pad1'>
22
-        <h1><a href="index.html">All files</a> PlanningEventManager.js</h1>
22
+        <h1><a href="index.html">All files</a> Planning.js</h1>
23 23
         <div class='clearfix'>
24
-            
24
+
25 25
             <div class='fl pad1y space-right2'>
26 26
                 <span class="strong">100% </span>
27 27
                 <span class="quiet">Statements</span>
28 28
                 <span class='fraction'>68/68</span>
29 29
             </div>
30
-        
31
-            
30
+
31
+
32 32
             <div class='fl pad1y space-right2'>
33 33
                 <span class="strong">92.31% </span>
34 34
                 <span class="quiet">Branches</span>
35 35
                 <span class='fraction'>36/39</span>
36 36
             </div>
37
-        
38
-            
37
+
38
+
39 39
             <div class='fl pad1y space-right2'>
40 40
                 <span class="strong">100% </span>
41 41
                 <span class="quiet">Functions</span>
42 42
                 <span class='fraction'>11/11</span>
43 43
             </div>
44
-        
45
-            
44
+
45
+
46 46
             <div class='fl pad1y space-right2'>
47 47
                 <span class="strong">100% </span>
48 48
                 <span class="quiet">Lines</span>
49 49
                 <span class='fraction'>65/65</span>
50 50
             </div>
51
-        
52
-            
51
+
52
+
53 53
         </div>
54 54
         <p class="quiet">
55 55
             Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
@@ -806,4 +806,3 @@ export default class PlanningEventManager {
806 806
         <script src="block-navigation.js"></script>
807 807
     </body>
808 808
 </html>
809
-    

+ 11
- 12
coverage/lcov-report/index.html View File

@@ -15,41 +15,41 @@
15 15
         }
16 16
     </style>
17 17
 </head>
18
-    
18
+
19 19
 <body>
20 20
 <div class='wrapper'>
21 21
     <div class='pad1'>
22 22
         <h1>All files</h1>
23 23
         <div class='clearfix'>
24
-            
24
+
25 25
             <div class='fl pad1y space-right2'>
26 26
                 <span class="strong">100% </span>
27 27
                 <span class="quiet">Statements</span>
28 28
                 <span class='fraction'>68/68</span>
29 29
             </div>
30
-        
31
-            
30
+
31
+
32 32
             <div class='fl pad1y space-right2'>
33 33
                 <span class="strong">92.31% </span>
34 34
                 <span class="quiet">Branches</span>
35 35
                 <span class='fraction'>36/39</span>
36 36
             </div>
37
-        
38
-            
37
+
38
+
39 39
             <div class='fl pad1y space-right2'>
40 40
                 <span class="strong">100% </span>
41 41
                 <span class="quiet">Functions</span>
42 42
                 <span class='fraction'>11/11</span>
43 43
             </div>
44
-        
45
-            
44
+
45
+
46 46
             <div class='fl pad1y space-right2'>
47 47
                 <span class="strong">100% </span>
48 48
                 <span class="quiet">Lines</span>
49 49
                 <span class='fraction'>65/65</span>
50 50
             </div>
51
-        
52
-            
51
+
52
+
53 53
         </div>
54 54
         <p class="quiet">
55 55
             Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
@@ -73,7 +73,7 @@
73 73
 </tr>
74 74
 </thead>
75 75
 <tbody><tr>
76
-	<td class="file high" data-value="PlanningEventManager.js"><a href="PlanningEventManager.js.html">PlanningEventManager.js</a></td>
76
+	<td class="file high" data-value="Planning.js"><a href="PlanningEventManager.js.html">Planning.js</a></td>
77 77
 	<td data-value="100" class="pic high">
78 78
 	<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
79 79
 	</td>
@@ -108,4 +108,3 @@
108 108
         <script src="block-navigation.js"></script>
109 109
     </body>
110 110
 </html>
111
-    

+ 1
- 1
coverage/lcov.info View File

@@ -1,5 +1,5 @@
1 1
 TN:
2
-SF:utils/PlanningEventManager.js
2
+SF:utils/Planning.js
3 3
 FN:26,(anonymous_0)
4 4
 FN:37,(anonymous_1)
5 5
 FN:53,(anonymous_2)

utils/AprilFoolsManager.js → managers/AprilFoolsManager.js View File


utils/AsyncStorageManager.js → managers/AsyncStorageManager.js View File


utils/DateManager.js → managers/DateManager.js View File


utils/LocaleManager.js → managers/LocaleManager.js View File


utils/ThemeManager.js → managers/ThemeManager.js View File


+ 1
- 1
navigation/MainTabNavigator.js View File

@@ -12,7 +12,7 @@ import ProximoListScreen from "../screens/Proximo/ProximoListScreen";
12 12
 import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
13 13
 import PlanexScreen from '../screens/Websites/PlanexScreen';
14 14
 import {MaterialCommunityIcons} from "@expo/vector-icons";
15
-import AsyncStorageManager from "../utils/AsyncStorageManager";
15
+import AsyncStorageManager from "../managers/AsyncStorageManager";
16 16
 import HeaderButton from "../components/HeaderButton";
17 17
 import {withTheme} from 'react-native-paper';
18 18
 import i18n from "i18n-js";

+ 1
- 1
screens/About/AboutScreen.js View File

@@ -4,7 +4,7 @@ import * as React from 'react';
4 4
 import {FlatList, Linking, Platform, View} from 'react-native';
5 5
 import i18n from "i18n-js";
6 6
 import appJson from '../../app';
7
-import AsyncStorageManager from "../../utils/AsyncStorageManager";
7
+import AsyncStorageManager from "../../managers/AsyncStorageManager";
8 8
 import CustomModal from "../../components/CustomModal";
9 9
 import {Avatar, Button, Card, List, Text, Title, withTheme} from 'react-native-paper';
10 10
 

+ 1
- 1
screens/About/DebugScreen.js View File

@@ -2,7 +2,7 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {ScrollView, View} from "react-native";
5
-import AsyncStorageManager from "../../utils/AsyncStorageManager";
5
+import AsyncStorageManager from "../../managers/AsyncStorageManager";
6 6
 import CustomModal from "../../components/CustomModal";
7 7
 import {Button, Card, List, Subheading, TextInput, Title, withTheme} from 'react-native-paper';
8 8
 

+ 6
- 6
screens/HomeScreen.js View File

@@ -10,7 +10,7 @@ import {Text, withTheme} from 'react-native-paper';
10 10
 import FeedItem from "../components/FeedItem";
11 11
 import SquareDashboardItem from "../components/SquareDashboardItem";
12 12
 import PreviewEventDashboardItem from "../components/PreviewEventDashboardItem";
13
-import PlanningEventManager from "../utils/PlanningEventManager";
13
+import {stringToDate} from "../utils/Planning";
14 14
 // import DATA from "../dashboard_data.json";
15 15
 
16 16
 
@@ -201,8 +201,8 @@ class HomeScreen extends React.Component<Props> {
201 201
      * @return {number} The number of milliseconds
202 202
      */
203 203
     getEventDuration(event: Object): number {
204
-        let start = PlanningEventManager.stringToDate(event['date_begin']);
205
-        let end = PlanningEventManager.stringToDate(event['date_end']);
204
+        let start = stringToDate(event['date_begin']);
205
+        let end = stringToDate(event['date_end']);
206 206
         let duration = 0;
207 207
         if (start !== undefined && start !== null && end !== undefined && end !== null)
208 208
             duration = end - start;
@@ -219,7 +219,7 @@ class HomeScreen extends React.Component<Props> {
219 219
     getEventsAfterLimit(events: Object, limit: Date): Array<Object> {
220 220
         let validEvents = [];
221 221
         for (let event of events) {
222
-            let startDate = PlanningEventManager.stringToDate(event['date_begin']);
222
+            let startDate = stringToDate(event['date_begin']);
223 223
             if (startDate !== undefined && startDate !== null && startDate >= limit) {
224 224
                 validEvents.push(event);
225 225
             }
@@ -255,8 +255,8 @@ class HomeScreen extends React.Component<Props> {
255 255
         let validEvents = [];
256 256
         let now = new Date();
257 257
         for (let event of events) {
258
-            let startDate = PlanningEventManager.stringToDate(event['date_begin']);
259
-            let endDate = PlanningEventManager.stringToDate(event['date_end']);
258
+            let startDate = stringToDate(event['date_begin']);
259
+            let endDate = stringToDate(event['date_end']);
260 260
             if (startDate !== undefined && startDate !== null) {
261 261
                 if (startDate > now)
262 262
                     validEvents.push(event);

+ 4
- 4
screens/Planning/PlanningDisplayScreen.js View File

@@ -4,9 +4,9 @@ import * as React from 'react';
4 4
 import {Image, ScrollView, View} from 'react-native';
5 5
 import HTML from "react-native-render-html";
6 6
 import {Linking} from "expo";
7
-import PlanningEventManager from '../../utils/PlanningEventManager';
7
+import {getDateOnlyString, getFormattedEventTime} from '../../utils/Planning';
8 8
 import {Card, withTheme} from 'react-native-paper';
9
-import DateManager from "../../utils/DateManager";
9
+import DateManager from "../../managers/DateManager";
10 10
 
11 11
 type Props = {
12 12
     navigation: Object,
@@ -33,9 +33,9 @@ class PlanningDisplayScreen extends React.Component<Props> {
33 33
 
34 34
     render() {
35 35
         // console.log("rendering planningDisplayScreen");
36
-        let subtitle = PlanningEventManager.getFormattedEventTime(
36
+        let subtitle = getFormattedEventTime(
37 37
             this.displayData["date_begin"], this.displayData["date_end"]);
38
-        let dateString = PlanningEventManager.getDateOnlyString(this.displayData["date_begin"]);
38
+        let dateString = getDateOnlyString(this.displayData["date_begin"]);
39 39
         if (dateString !== null)
40 40
             subtitle += ' | ' + DateManager.getInstance().getTranslatedDate(dateString);
41 41
         return (

+ 13
- 10
screens/Planning/PlanningScreen.js View File

@@ -4,9 +4,14 @@ import * as React from 'react';
4 4
 import {BackHandler, View} from 'react-native';
5 5
 import i18n from "i18n-js";
6 6
 import {LocaleConfig} from 'react-native-calendars';
7
-import WebDataManager from "../../utils/WebDataManager";
8
-import type {eventObject} from "../../utils/PlanningEventManager";
9
-import PlanningEventManager from '../../utils/PlanningEventManager';
7
+import {readData} from "../../utils/WebData";
8
+import type {eventObject} from "../../utils/Planning";
9
+import {
10
+    generateEventAgenda,
11
+    getCurrentDateString,
12
+    getDateOnlyString,
13
+    getFormattedEventTime,
14
+} from '../../utils/Planning';
10 15
 import {Avatar, Divider, List} from 'react-native-paper';
11 16
 import CustomAgenda from "../../components/CustomAgenda";
12 17
 
@@ -38,7 +43,6 @@ const AGENDA_MONTH_SPAN = 3;
38 43
 export default class PlanningScreen extends React.Component<Props, State> {
39 44
 
40 45
     agendaRef: Object;
41
-    webDataManager: WebDataManager;
42 46
 
43 47
     lastRefresh: Date;
44 48
     minTimeBetweenRefresh = 60;
@@ -59,11 +63,10 @@ export default class PlanningScreen extends React.Component<Props, State> {
59 63
     onAgendaRef: Function;
60 64
     onCalendarToggled: Function;
61 65
     onBackButtonPressAndroid: Function;
62
-    currentDate = PlanningEventManager.getDateOnlyString(PlanningEventManager.getCurrentDateString());
66
+    currentDate = getDateOnlyString(getCurrentDateString());
63 67
 
64 68
     constructor(props: any) {
65 69
         super(props);
66
-        this.webDataManager = new WebDataManager(FETCH_URL);
67 70
         if (i18n.currentLocale().startsWith("fr")) {
68 71
             LocaleConfig.defaultLocale = 'fr';
69 72
         }
@@ -141,11 +144,11 @@ export default class PlanningScreen extends React.Component<Props, State> {
141 144
 
142 145
         if (canRefresh) {
143 146
             this.setState({refreshing: true});
144
-            this.webDataManager.readData()
147
+            readData(FETCH_URL)
145 148
                 .then((fetchedData) => {
146 149
                     this.setState({
147 150
                         refreshing: false,
148
-                        agendaItems: PlanningEventManager.generateEventAgenda(fetchedData, AGENDA_MONTH_SPAN)
151
+                        agendaItems: generateEventAgenda(fetchedData, AGENDA_MONTH_SPAN)
149 152
                     });
150 153
                     this.lastRefresh = new Date();
151 154
                 })
@@ -189,7 +192,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
189 192
                     <Divider/>
190 193
                     <List.Item
191 194
                         title={item.title}
192
-                        description={PlanningEventManager.getFormattedEventTime(item["date_begin"], item["date_end"])}
195
+                        description={getFormattedEventTime(item["date_begin"], item["date_end"])}
193 196
                         left={() => <Avatar.Image
194 197
                             source={{uri: item.logo}}
195 198
                             style={{backgroundColor: 'transparent'}}
@@ -204,7 +207,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
204 207
                     <Divider/>
205 208
                     <List.Item
206 209
                         title={item.title}
207
-                        description={PlanningEventManager.getFormattedEventTime(item["date_begin"], item["date_end"])}
210
+                        description={getFormattedEventTime(item["date_begin"], item["date_end"])}
208 211
                         onPress={onPress}
209 212
                     />
210 213
                 </View>

+ 7
- 7
screens/Proxiwash/ProxiwashScreen.js View File

@@ -4,15 +4,15 @@ import * as React from 'react';
4 4
 import {Alert, Platform, View} from 'react-native';
5 5
 import i18n from "i18n-js";
6 6
 import WebSectionList from "../../components/WebSectionList";
7
-import NotificationsManager from "../../utils/NotificationsManager";
8
-import AsyncStorageManager from "../../utils/AsyncStorageManager";
7
+import * as Notifications from "../../utils/Notifications";
8
+import AsyncStorageManager from "../../managers/AsyncStorageManager";
9 9
 import * as Expo from "expo";
10 10
 import {Avatar, Banner, Button, Card, Text, withTheme} from 'react-native-paper';
11 11
 import HeaderButton from "../../components/HeaderButton";
12 12
 import ProxiwashListItem from "../../components/ProxiwashListItem";
13 13
 import ProxiwashConstants from "../../constants/ProxiwashConstants";
14 14
 import CustomModal from "../../components/CustomModal";
15
-import AprilFoolsManager from "../../utils/AprilFoolsManager";
15
+import AprilFoolsManager from "../../managers/AprilFoolsManager";
16 16
 
17 17
 const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json";
18 18
 
@@ -118,12 +118,12 @@ class ProxiwashScreen extends React.Component<Props, State> {
118 118
         });
119 119
         if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') {
120 120
             // Get latest watchlist from server
121
-            NotificationsManager.getMachineNotificationWatchlist((fetchedList) => {
121
+            Notifications.getMachineNotificationWatchlist((fetchedList) => {
122 122
                 this.setState({machinesWatched: fetchedList})
123 123
             });
124 124
             // Get updated watchlist after received notification
125 125
             Expo.Notifications.addListener(() => {
126
-                NotificationsManager.getMachineNotificationWatchlist((fetchedList) => {
126
+                Notifications.getMachineNotificationWatchlist((fetchedList) => {
127 127
                     this.setState({machinesWatched: fetchedList})
128 128
                 });
129 129
             });
@@ -175,7 +175,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
175 175
     setupNotifications(machineId: string) {
176 176
         if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') {
177 177
             if (!this.isMachineWatched(machineId)) {
178
-                NotificationsManager.setupMachineNotification(machineId, true);
178
+                Notifications.setupMachineNotification(machineId, true);
179 179
                 this.saveNotificationToState(machineId);
180 180
             } else
181 181
                 this.disableNotification(machineId);
@@ -205,7 +205,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
205 205
         if (data.length > 0) {
206 206
             let arrayIndex = data.indexOf(machineId);
207 207
             if (arrayIndex !== -1) {
208
-                NotificationsManager.setupMachineNotification(machineId, false);
208
+                Notifications.setupMachineNotification(machineId, false);
209 209
                 this.removeNotificationFroState(arrayIndex);
210 210
             }
211 211
         }

+ 2
- 2
screens/SelfMenuScreen.js View File

@@ -2,10 +2,10 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {View} from 'react-native';
5
-import DateManager from "../utils/DateManager";
5
+import DateManager from "../managers/DateManager";
6 6
 import WebSectionList from "../components/WebSectionList";
7 7
 import {Card, Text, withTheme} from 'react-native-paper';
8
-import AprilFoolsManager from "../utils/AprilFoolsManager";
8
+import AprilFoolsManager from "../managers/AprilFoolsManager";
9 9
 
10 10
 const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/menu/menu_data.json";
11 11
 

+ 4
- 4
screens/SettingsScreen.js View File

@@ -2,10 +2,10 @@
2 2
 
3 3
 import * as React from 'react';
4 4
 import {ScrollView} from "react-native";
5
-import ThemeManager from '../utils/ThemeManager';
5
+import ThemeManager from '../managers/ThemeManager';
6 6
 import i18n from "i18n-js";
7
-import AsyncStorageManager from "../utils/AsyncStorageManager";
8
-import NotificationsManager from "../utils/NotificationsManager";
7
+import AsyncStorageManager from "../managers/AsyncStorageManager";
8
+import {setMachineReminderNotificationTime} from "../utils/Notifications";
9 9
 import {Card, List, Switch, ToggleButton} from 'react-native-paper';
10 10
 import {Appearance} from "react-native-appearance";
11 11
 
@@ -60,7 +60,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
60 60
             let intVal = 0;
61 61
             if (value !== 'never')
62 62
                 intVal = parseInt(value);
63
-            NotificationsManager.setMachineReminderNotificationTime(intVal);
63
+            setMachineReminderNotificationTime(intVal);
64 64
         }
65 65
     }
66 66
 

+ 2
- 2
screens/Websites/PlanexScreen.js View File

@@ -1,12 +1,12 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import ThemeManager from "../../utils/ThemeManager";
4
+import ThemeManager from "../../managers/ThemeManager";
5 5
 import WebViewScreen from "../../components/WebViewScreen";
6 6
 import {Avatar, Banner} from "react-native-paper";
7 7
 import i18n from "i18n-js";
8 8
 import {View} from "react-native";
9
-import AsyncStorageManager from "../../utils/AsyncStorageManager";
9
+import AsyncStorageManager from "../../managers/AsyncStorageManager";
10 10
 
11 11
 type Props = {
12 12
     navigation: Object,

+ 125
- 0
utils/Notifications.js View File

@@ -0,0 +1,125 @@
1
+// @flow
2
+
3
+import * as Permissions from 'expo-permissions';
4
+import {Notifications} from 'expo';
5
+import AsyncStorageManager from "../managers/AsyncStorageManager";
6
+import LocaleManager from "../managers/LocaleManager";
7
+import passwords from "../passwords";
8
+
9
+const EXPO_TOKEN_SERVER = 'https://etud.insa-toulouse.fr/~amicale_app/expo_notifications/save_token.php';
10
+
11
+/**
12
+ * Async function asking permission to send notifications to the user
13
+ *
14
+ * @returns {Promise}
15
+ */
16
+export async function askPermissions() {
17
+    const {status: existingStatus} = await Permissions.getAsync(Permissions.NOTIFICATIONS);
18
+    let finalStatus = existingStatus;
19
+    if (existingStatus !== 'granted') {
20
+        const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
21
+        finalStatus = status;
22
+    }
23
+    return finalStatus === 'granted';
24
+}
25
+
26
+/**
27
+ * Save expo token to allow sending notifications to this device.
28
+ * This token is unique for each device and won't change.
29
+ * It only needs to be fetched once, then it will be saved in storage.
30
+ *
31
+ * @return {Promise<void>}
32
+ */
33
+export async function initExpoToken() {
34
+    let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
35
+    if (token === '') {
36
+        try {
37
+            await askPermissions();
38
+            let expoToken = await Notifications.getExpoPushTokenAsync();
39
+            // Save token for instant use later on
40
+            AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.expoToken.key, expoToken);
41
+        } catch (e) {
42
+            console.log(e);
43
+        }
44
+    }
45
+}
46
+
47
+/**
48
+ * Gets the machines watched from the server
49
+ *
50
+ * @param callback Function to execute with the fetched data
51
+ */
52
+export function getMachineNotificationWatchlist(callback: Function) {
53
+    let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
54
+    if (token !== '') {
55
+        let data = {
56
+            function: 'get_machine_watchlist',
57
+            password: passwords.expoNotifications,
58
+            token: token,
59
+        };
60
+        fetch(EXPO_TOKEN_SERVER, {
61
+            method: 'POST',
62
+            headers: new Headers({
63
+                Accept: 'application/json',
64
+                'Content-Type': 'application/json',
65
+            }),
66
+            body: JSON.stringify(data) // <-- Post parameters
67
+        }).then((response) => response.json())
68
+            .then((responseJson) => {
69
+                callback(responseJson);
70
+            });
71
+    }
72
+}
73
+
74
+/**
75
+ * Asks the server to enable/disable notifications for the specified machine
76
+ *
77
+ * @param machineID The machine ID
78
+ * @param isEnabled True to enable notifications, false to disable
79
+ */
80
+export function setupMachineNotification(machineID: string, isEnabled: boolean) {
81
+    let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
82
+    if (token !== '') {
83
+        let data = {
84
+            function: 'setup_machine_notification',
85
+            password: passwords.expoNotifications,
86
+            locale: LocaleManager.getCurrentLocale(),
87
+            token: token,
88
+            machine_id: machineID,
89
+            enabled: isEnabled
90
+        };
91
+        fetch(EXPO_TOKEN_SERVER, {
92
+            method: 'POST',
93
+            headers: new Headers({
94
+                Accept: 'application/json',
95
+                'Content-Type': 'application/json',
96
+            }),
97
+            body: JSON.stringify(data) // <-- Post parameters
98
+        });
99
+    }
100
+}
101
+
102
+/**
103
+ * Sends the selected reminder time for notifications to the server
104
+ *
105
+ * @param time The reminder time to use
106
+ */
107
+export function setMachineReminderNotificationTime(time: number) {
108
+    let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
109
+    if (token !== '') {
110
+        let data = {
111
+            function: 'set_machine_reminder',
112
+            password: passwords.expoNotifications,
113
+            token: token,
114
+            time: time,
115
+        };
116
+        fetch(EXPO_TOKEN_SERVER, {
117
+            method: 'POST',
118
+            headers: new Headers({
119
+                Accept: 'application/json',
120
+                'Content-Type': 'application/json',
121
+            }),
122
+            body: JSON.stringify(data) // <-- Post parameters
123
+        });
124
+    }
125
+}

+ 0
- 131
utils/NotificationsManager.js View File

@@ -1,131 +0,0 @@
1
-// @flow
2
-
3
-import * as Permissions from 'expo-permissions';
4
-import {Notifications} from 'expo';
5
-import AsyncStorageManager from "./AsyncStorageManager";
6
-import LocaleManager from "./LocaleManager";
7
-import passwords from "../passwords";
8
-
9
-const EXPO_TOKEN_SERVER = 'https://etud.insa-toulouse.fr/~amicale_app/expo_notifications/save_token.php';
10
-
11
-/**
12
- * Static class used to manage notifications sent to the user
13
- */
14
-export default class NotificationsManager {
15
-
16
-    /**
17
-     * Async function asking permission to send notifications to the user
18
-     *
19
-     * @returns {Promise}
20
-     */
21
-    static async askPermissions() {
22
-        const {status: existingStatus} = await Permissions.getAsync(Permissions.NOTIFICATIONS);
23
-        let finalStatus = existingStatus;
24
-        if (existingStatus !== 'granted') {
25
-            const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
26
-            finalStatus = status;
27
-        }
28
-        return finalStatus === 'granted';
29
-    }
30
-
31
-    /**
32
-     * Save expo token to allow sending notifications to this device.
33
-     * This token is unique for each device and won't change.
34
-     * It only needs to be fetched once, then it will be saved in storage.
35
-     *
36
-     * @return {Promise<void>}
37
-     */
38
-    static async initExpoToken() {
39
-        let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
40
-        if (token === '') {
41
-            try {
42
-                await NotificationsManager.askPermissions();
43
-                let expoToken = await Notifications.getExpoPushTokenAsync();
44
-                // Save token for instant use later on
45
-                AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.expoToken.key, expoToken);
46
-            } catch(e) {
47
-                console.log(e);
48
-            }
49
-        }
50
-    }
51
-
52
-    /**
53
-     * Gets the machines watched from the server
54
-     *
55
-     * @param callback Function to execute with the fetched data
56
-     */
57
-    static getMachineNotificationWatchlist(callback: Function) {
58
-        let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
59
-        if (token !== '') {
60
-            let data = {
61
-                function: 'get_machine_watchlist',
62
-                password: passwords.expoNotifications,
63
-                token: token,
64
-            };
65
-            fetch(EXPO_TOKEN_SERVER, {
66
-                method: 'POST',
67
-                headers: new Headers({
68
-                    Accept: 'application/json',
69
-                    'Content-Type': 'application/json',
70
-                }),
71
-                body: JSON.stringify(data) // <-- Post parameters
72
-            }).then((response) => response.json())
73
-                .then((responseJson) => {
74
-                    callback(responseJson);
75
-                });
76
-        }
77
-    }
78
-
79
-    /**
80
-     * Asks the server to enable/disable notifications for the specified machine
81
-     *
82
-     * @param machineID The machine ID
83
-     * @param isEnabled True to enable notifications, false to disable
84
-     */
85
-    static setupMachineNotification(machineID: string, isEnabled: boolean) {
86
-        let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
87
-        if (token !== '') {
88
-            let data = {
89
-                function: 'setup_machine_notification',
90
-                password: passwords.expoNotifications,
91
-                locale: LocaleManager.getCurrentLocale(),
92
-                token: token,
93
-                machine_id: machineID,
94
-                enabled: isEnabled
95
-            };
96
-            fetch(EXPO_TOKEN_SERVER, {
97
-                method: 'POST',
98
-                headers: new Headers({
99
-                    Accept: 'application/json',
100
-                    'Content-Type': 'application/json',
101
-                }),
102
-                body: JSON.stringify(data) // <-- Post parameters
103
-            });
104
-        }
105
-    }
106
-
107
-    /**
108
-     * Sends the selected reminder time for notifications to the server
109
-     *
110
-     * @param time The reminder time to use
111
-     */
112
-    static setMachineReminderNotificationTime(time: number) {
113
-        let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
114
-        if (token !== '') {
115
-            let data = {
116
-                function: 'set_machine_reminder',
117
-                password: passwords.expoNotifications,
118
-                token: token,
119
-                time: time,
120
-            };
121
-            fetch(EXPO_TOKEN_SERVER, {
122
-                method: 'POST',
123
-                headers: new Headers({
124
-                    Accept: 'application/json',
125
-                    'Content-Type': 'application/json',
126
-                }),
127
-                body: JSON.stringify(data) // <-- Post parameters
128
-            });
129
-        }
130
-    }
131
-}

+ 240
- 0
utils/Planning.js View File

@@ -0,0 +1,240 @@
1
+// @flow
2
+
3
+export type eventObject = {
4
+    id: number,
5
+    title: string,
6
+    logo: string,
7
+    date_begin: string,
8
+    date_end: string,
9
+    description: string,
10
+    club: string,
11
+    category_id: number,
12
+    url: string,
13
+};
14
+
15
+// Regex used to check date string validity
16
+const dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
17
+
18
+/**
19
+ * Gets the current day string representation in the format
20
+ * YYYY-MM-DD
21
+ *
22
+ * @return {string} The string representation
23
+ */
24
+export function getCurrentDateString(): string {
25
+    return dateToString(new Date(Date.now()));
26
+}
27
+
28
+/**
29
+ * Checks if the given date is before the other.
30
+ *
31
+ * @param event1Date Event 1 date in format YYYY-MM-DD HH:MM
32
+ * @param event2Date Event 2 date in format YYYY-MM-DD HH:MM
33
+ * @return {boolean}
34
+ */
35
+export function isEventBefore(event1Date: string, event2Date: string): boolean {
36
+    let date1 = stringToDate(event1Date);
37
+    let date2 = stringToDate(event2Date);
38
+    if (date1 !== null && date2 !== null)
39
+        return date1 < date2;
40
+    else
41
+        return false;
42
+}
43
+
44
+/**
45
+ * Gets only the date part of the given event date string in the format
46
+ * YYYY-MM-DD HH:MM
47
+ *
48
+ * @param dateString The string to get the date from
49
+ * @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
50
+ */
51
+export function getDateOnlyString(dateString: string): string | null {
52
+    if (isEventDateStringFormatValid(dateString))
53
+        return dateString.split(" ")[0];
54
+    else
55
+        return null;
56
+}
57
+
58
+/**
59
+ * Checks if the given date string is in the format
60
+ * YYYY-MM-DD HH:MM
61
+ *
62
+ * @param dateString The string to check
63
+ * @return {boolean}
64
+ */
65
+export function isEventDateStringFormatValid(dateString: ?string): boolean {
66
+    return dateString !== undefined
67
+        && dateString !== null
68
+        && dateRegExp.test(dateString);
69
+}
70
+
71
+/**
72
+ * Converts the given date string to a date object.<br>
73
+ * Accepted format: YYYY-MM-DD HH:MM
74
+ *
75
+ * @param dateString The string to convert
76
+ * @return {Date|null} The date object or null if the given string is invalid
77
+ */
78
+export function stringToDate(dateString: string): Date | null {
79
+    let date = new Date();
80
+    if (isEventDateStringFormatValid(dateString)) {
81
+        let stringArray = dateString.split(' ');
82
+        let dateArray = stringArray[0].split('-');
83
+        let timeArray = stringArray[1].split(':');
84
+        date.setFullYear(
85
+            parseInt(dateArray[0]),
86
+            parseInt(dateArray[1]) - 1, // Month range from 0 to 11
87
+            parseInt(dateArray[2])
88
+        );
89
+        date.setHours(
90
+            parseInt(timeArray[0]),
91
+            parseInt(timeArray[1]),
92
+            0,
93
+            0,
94
+        );
95
+    } else
96
+        date = null;
97
+
98
+    return date;
99
+}
100
+
101
+/**
102
+ * Converts a date object to a string in the format
103
+ * YYYY-MM-DD HH-MM-SS
104
+ *
105
+ * @param date The date object to convert
106
+ * @return {string} The converted string
107
+ */
108
+export function dateToString(date: Date): string {
109
+    const day = String(date.getDate()).padStart(2, '0');
110
+    const month = String(date.getMonth() + 1).padStart(2, '0'); //January is 0!
111
+    const year = date.getFullYear();
112
+    const hours = String(date.getHours()).padStart(2, '0');
113
+    const minutes = String(date.getMinutes()).padStart(2, '0');
114
+    return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
115
+}
116
+
117
+/**
118
+ * Returns a string corresponding to the event start and end times in the following format:
119
+ *
120
+ * HH:MM - HH:MM
121
+ *
122
+ * If the end date is not specified or is equal to start time, only start time will be shown.
123
+ *
124
+ * If the end date is not on the same day, 23:59 will be shown as end time
125
+ *
126
+ * @param start Start time in YYYY-MM-DD HH:MM:SS format
127
+ * @param end End time in YYYY-MM-DD HH:MM:SS format
128
+ * @return {string} Formatted string or "/ - /" on error
129
+ */
130
+export function getFormattedEventTime(start: string, end: string): string {
131
+    let formattedStr = '/ - /';
132
+    let startDate = stringToDate(start);
133
+    let endDate = stringToDate(end);
134
+
135
+    if (startDate !== null && endDate !== null && startDate.getTime() !== endDate.getTime()) {
136
+        formattedStr = String(startDate.getHours()).padStart(2, '0') + ':'
137
+            + String(startDate.getMinutes()).padStart(2, '0') + ' - ';
138
+        if (endDate.getFullYear() > startDate.getFullYear()
139
+            || endDate.getMonth() > startDate.getMonth()
140
+            || endDate.getDate() > startDate.getDate())
141
+            formattedStr += '23:59';
142
+        else
143
+            formattedStr += String(endDate.getHours()).padStart(2, '0') + ':'
144
+                + String(endDate.getMinutes()).padStart(2, '0');
145
+    } else if (startDate !== null)
146
+        formattedStr =
147
+            String(startDate.getHours()).padStart(2, '0') + ':'
148
+            + String(startDate.getMinutes()).padStart(2, '0');
149
+
150
+    return formattedStr
151
+}
152
+
153
+/**
154
+ * Checks if the given description can be considered empty.
155
+ * <br>
156
+ * An empty description is composed only of whitespace, <b>br</b> or <b>p</b> tags
157
+ *
158
+ *
159
+ * @param description The text to check
160
+ * @return {boolean}
161
+ */
162
+export function isDescriptionEmpty(description: ?string): boolean {
163
+    if (description !== undefined && description !== null) {
164
+        return description
165
+            .split('<p>').join('') // Equivalent to a replace all
166
+            .split('</p>').join('')
167
+            .split('<br>').join('').trim() === '';
168
+    } else
169
+        return true;
170
+}
171
+
172
+/**
173
+ * Generates an object with an empty array for each key.
174
+ * Each key is a date string in the format
175
+ * YYYY-MM-DD
176
+ *
177
+ * @param numberOfMonths The number of months to create, starting from the current date
178
+ * @return {Object}
179
+ */
180
+export function generateEmptyCalendar(numberOfMonths: number): Object {
181
+    let end = new Date(Date.now());
182
+    end.setMonth(end.getMonth() + numberOfMonths);
183
+    let daysOfYear = {};
184
+    for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
185
+        const dateString = getDateOnlyString(
186
+            dateToString(new Date(d)));
187
+        if (dateString !== null)
188
+            daysOfYear[dateString] = []
189
+    }
190
+    return daysOfYear;
191
+}
192
+
193
+/**
194
+ * Generates an object with an array of eventObject at each key.
195
+ * Each key is a date string in the format
196
+ * YYYY-MM-DD.
197
+ *
198
+ * If no event is available at the given key, the array will be empty
199
+ *
200
+ * @param eventList The list of events to map to the agenda
201
+ * @param numberOfMonths The number of months to create the agenda for
202
+ * @return {Object}
203
+ */
204
+export function generateEventAgenda(eventList: Array<eventObject>, numberOfMonths: number): Object {
205
+    let agendaItems = generateEmptyCalendar(numberOfMonths);
206
+    for (let i = 0; i < eventList.length; i++) {
207
+        const dateString = getDateOnlyString(eventList[i].date_begin);
208
+        if (dateString !== null) {
209
+            const eventArray = agendaItems[dateString];
210
+            if (eventArray !== undefined)
211
+                this.pushEventInOrder(eventArray, eventList[i]);
212
+        }
213
+
214
+    }
215
+    return agendaItems;
216
+}
217
+
218
+/**
219
+ * Adds events to the given array depending on their starting date.
220
+ *
221
+ * Events starting before are added at the front.
222
+ *
223
+ * @param eventArray The array to hold sorted events
224
+ * @param event The event to add to the array
225
+ */
226
+export function pushEventInOrder(eventArray: Array<eventObject>, event: eventObject): Object {
227
+    if (eventArray.length === 0)
228
+        eventArray.push(event);
229
+    else {
230
+        for (let i = 0; i < eventArray.length; i++) {
231
+            if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
232
+                eventArray.splice(i, 0, event);
233
+                break;
234
+            } else if (i === eventArray.length - 1) {
235
+                eventArray.push(event);
236
+                break;
237
+            }
238
+        }
239
+    }
240
+}

+ 0
- 243
utils/PlanningEventManager.js View File

@@ -1,243 +0,0 @@
1
-// @flow
2
-
3
-export type eventObject = {
4
-    id: number,
5
-    title: string,
6
-    logo: string,
7
-    date_begin: string,
8
-    date_end: string,
9
-    description: string,
10
-    club: string,
11
-    category_id: number,
12
-    url: string,
13
-};
14
-
15
-export default class PlanningEventManager {
16
-
17
-    // Regex used to check date string validity
18
-    static dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
19
-
20
-    /**
21
-     * Gets the current day string representation in the format
22
-     * YYYY-MM-DD
23
-     *
24
-     * @return {string} The string representation
25
-     */
26
-    static getCurrentDateString(): string {
27
-        return PlanningEventManager.dateToString(new Date(Date.now()));
28
-    }
29
-
30
-    /**
31
-     * Checks if the given date is before the other.
32
-     *
33
-     * @param event1Date Event 1 date in format YYYY-MM-DD HH:MM
34
-     * @param event2Date Event 2 date in format YYYY-MM-DD HH:MM
35
-     * @return {boolean}
36
-     */
37
-    static isEventBefore(event1Date: string, event2Date: string): boolean {
38
-        let date1 = PlanningEventManager.stringToDate(event1Date);
39
-        let date2 = PlanningEventManager.stringToDate(event2Date);
40
-        if (date1 !== null && date2 !== null)
41
-            return date1 < date2;
42
-        else
43
-            return false;
44
-    }
45
-
46
-    /**
47
-     * Gets only the date part of the given event date string in the format
48
-     * YYYY-MM-DD HH:MM
49
-     *
50
-     * @param dateString The string to get the date from
51
-     * @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
52
-     */
53
-    static getDateOnlyString(dateString: string): string | null {
54
-        if (PlanningEventManager.isEventDateStringFormatValid(dateString))
55
-            return dateString.split(" ")[0];
56
-        else
57
-            return null;
58
-    }
59
-
60
-    /**
61
-     * Checks if the given date string is in the format
62
-     * YYYY-MM-DD HH:MM
63
-     *
64
-     * @param dateString The string to check
65
-     * @return {boolean}
66
-     */
67
-    static isEventDateStringFormatValid(dateString: ?string): boolean {
68
-        return dateString !== undefined
69
-            && dateString !== null
70
-            && PlanningEventManager.dateRegExp.test(dateString);
71
-    }
72
-
73
-    /**
74
-     * Converts the given date string to a date object.<br>
75
-     * Accepted format: YYYY-MM-DD HH:MM
76
-     *
77
-     * @param dateString The string to convert
78
-     * @return {Date|null} The date object or null if the given string is invalid
79
-     */
80
-    static stringToDate(dateString: string): Date | null {
81
-        let date = new Date();
82
-        if (PlanningEventManager.isEventDateStringFormatValid(dateString)) {
83
-            let stringArray = dateString.split(' ');
84
-            let dateArray = stringArray[0].split('-');
85
-            let timeArray = stringArray[1].split(':');
86
-            date.setFullYear(
87
-                parseInt(dateArray[0]),
88
-                parseInt(dateArray[1]) - 1, // Month range from 0 to 11
89
-                parseInt(dateArray[2])
90
-            );
91
-            date.setHours(
92
-                parseInt(timeArray[0]),
93
-                parseInt(timeArray[1]),
94
-                0,
95
-                0,
96
-            );
97
-        } else
98
-            date = null;
99
-
100
-        return date;
101
-    }
102
-
103
-    /**
104
-     * Converts a date object to a string in the format
105
-     * YYYY-MM-DD HH-MM-SS
106
-     *
107
-     * @param date The date object to convert
108
-     * @return {string} The converted string
109
-     */
110
-    static dateToString(date: Date): string {
111
-        const day = String(date.getDate()).padStart(2, '0');
112
-        const month = String(date.getMonth() + 1).padStart(2, '0'); //January is 0!
113
-        const year = date.getFullYear();
114
-        const hours = String(date.getHours()).padStart(2, '0');
115
-        const minutes = String(date.getMinutes()).padStart(2, '0');
116
-        return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
117
-    }
118
-
119
-    /**
120
-     * Returns a string corresponding to the event start and end times in the following format:
121
-     *
122
-     * HH:MM - HH:MM
123
-     *
124
-     * If the end date is not specified or is equal to start time, only start time will be shown.
125
-     *
126
-     * If the end date is not on the same day, 23:59 will be shown as end time
127
-     *
128
-     * @param start Start time in YYYY-MM-DD HH:MM:SS format
129
-     * @param end End time in YYYY-MM-DD HH:MM:SS format
130
-     * @return {string} Formatted string or "/ - /" on error
131
-     */
132
-    static getFormattedEventTime(start: string, end: string): string {
133
-        let formattedStr = '/ - /';
134
-        let startDate = PlanningEventManager.stringToDate(start);
135
-        let endDate = PlanningEventManager.stringToDate(end);
136
-
137
-        if (startDate !== null && endDate !== null && startDate.getTime() !== endDate.getTime()) {
138
-            formattedStr = String(startDate.getHours()).padStart(2, '0') + ':'
139
-                + String(startDate.getMinutes()).padStart(2, '0') + ' - ';
140
-            if (endDate.getFullYear() > startDate.getFullYear()
141
-                || endDate.getMonth() > startDate.getMonth()
142
-                || endDate.getDate() > startDate.getDate())
143
-                formattedStr += '23:59';
144
-            else
145
-                formattedStr += String(endDate.getHours()).padStart(2, '0') + ':'
146
-                    + String(endDate.getMinutes()).padStart(2, '0');
147
-        } else if (startDate !== null)
148
-            formattedStr =
149
-                String(startDate.getHours()).padStart(2, '0') + ':'
150
-                + String(startDate.getMinutes()).padStart(2, '0');
151
-
152
-        return formattedStr
153
-    }
154
-
155
-    /**
156
-     * Checks if the given description can be considered empty.
157
-     * <br>
158
-     * An empty description is composed only of whitespace, <b>br</b> or <b>p</b> tags
159
-     *
160
-     *
161
-     * @param description The text to check
162
-     * @return {boolean}
163
-     */
164
-    static isDescriptionEmpty(description: ?string): boolean {
165
-        if (description !== undefined && description !== null) {
166
-            return description
167
-                .split('<p>').join('') // Equivalent to a replace all
168
-                .split('</p>').join('')
169
-                .split('<br>').join('').trim() === '';
170
-        } else
171
-            return true;
172
-    }
173
-
174
-    /**
175
-     * Generates an object with an empty array for each key.
176
-     * Each key is a date string in the format
177
-     * YYYY-MM-DD
178
-     *
179
-     * @param numberOfMonths The number of months to create, starting from the current date
180
-     * @return {Object}
181
-     */
182
-    static generateEmptyCalendar(numberOfMonths: number): Object {
183
-        let end = new Date(Date.now());
184
-        end.setMonth(end.getMonth() + numberOfMonths);
185
-        let daysOfYear = {};
186
-        for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
187
-            const dateString = PlanningEventManager.getDateOnlyString(
188
-                PlanningEventManager.dateToString(new Date(d)));
189
-            if (dateString !== null)
190
-                daysOfYear[dateString] = []
191
-        }
192
-        return daysOfYear;
193
-    }
194
-
195
-    /**
196
-     * Generates an object with an array of eventObject at each key.
197
-     * Each key is a date string in the format
198
-     * YYYY-MM-DD.
199
-     *
200
-     * If no event is available at the given key, the array will be empty
201
-     *
202
-     * @param eventList The list of events to map to the agenda
203
-     * @param numberOfMonths The number of months to create the agenda for
204
-     * @return {Object}
205
-     */
206
-    static generateEventAgenda(eventList: Array<eventObject>, numberOfMonths: number): Object {
207
-        let agendaItems = PlanningEventManager.generateEmptyCalendar(numberOfMonths);
208
-        for (let i = 0; i < eventList.length; i++) {
209
-            const dateString = PlanningEventManager.getDateOnlyString(eventList[i].date_begin);
210
-            if (dateString !== null) {
211
-                const eventArray = agendaItems[dateString];
212
-                if (eventArray !== undefined)
213
-                    this.pushEventInOrder(eventArray, eventList[i]);
214
-            }
215
-
216
-        }
217
-        return agendaItems;
218
-    }
219
-
220
-    /**
221
-     * Adds events to the given array depending on their starting date.
222
-     *
223
-     * Events starting before are added at the front.
224
-     *
225
-     * @param eventArray The array to hold sorted events
226
-     * @param event The event to add to the array
227
-     */
228
-    static pushEventInOrder(eventArray: Array<eventObject>, event: eventObject): Object {
229
-        if (eventArray.length === 0)
230
-            eventArray.push(event);
231
-        else {
232
-            for (let i = 0; i < eventArray.length; i++) {
233
-                if (PlanningEventManager.isEventBefore(event.date_begin, eventArray[i].date_begin)) {
234
-                    eventArray.splice(i, 0, event);
235
-                    break;
236
-                } else if (i === eventArray.length - 1) {
237
-                    eventArray.push(event);
238
-                    break;
239
-                }
240
-            }
241
-        }
242
-    }
243
-}

+ 19
- 0
utils/WebData.js View File

@@ -0,0 +1,19 @@
1
+// @flow
2
+
3
+/**
4
+ * Read data from FETCH_URL and return it.
5
+ * If no data was found, returns an empty object
6
+ *
7
+ * @param url The urls to fetch data from
8
+ * @return {Promise<Object>}
9
+ */
10
+export async function readData(url: string) {
11
+    let fetchedData: Object = {};
12
+    try {
13
+        let response = await fetch(url);
14
+        fetchedData = await response.json();
15
+    } catch (error) {
16
+        throw new Error('Could not read FetchedData from server');
17
+    }
18
+    return fetchedData;
19
+}

+ 0
- 34
utils/WebDataManager.js View File

@@ -1,34 +0,0 @@
1
-// @flow
2
-
3
-/**
4
- * Class used to get json data from the web
5
- */
6
-export default class WebDataManager {
7
-
8
-    FETCH_URL: string;
9
-    lastDataFetched: Object = {};
10
-
11
-
12
-    constructor(url: string) {
13
-        this.FETCH_URL = url;
14
-    }
15
-
16
-    /**
17
-     * Read data from FETCH_URL and return it.
18
-     * If no data was found, returns an empty object
19
-     *
20
-     * @return {Promise<Object>}
21
-     */
22
-    async readData() {
23
-        let fetchedData: Object = {};
24
-        try {
25
-            let response = await fetch(this.FETCH_URL);
26
-            fetchedData = await response.json();
27
-        } catch (error) {
28
-            throw new Error('Could not read FetchedData from server');
29
-        }
30
-        this.lastDataFetched = fetchedData;
31
-        return fetchedData;
32
-    }
33
-
34
-}

+ 0
- 210
utils/__test__/PlanningEventManager.test.js View File

@@ -1,210 +0,0 @@
1
-import React from 'react';
2
-import PlanningEventManager from "../PlanningEventManager";
3
-
4
-test('isDescriptionEmpty', () => {
5
-    expect(PlanningEventManager.isDescriptionEmpty("")).toBeTrue();
6
-    expect(PlanningEventManager.isDescriptionEmpty("   ")).toBeTrue();
7
-    // noinspection CheckTagEmptyBody
8
-    expect(PlanningEventManager.isDescriptionEmpty("<p></p>")).toBeTrue();
9
-    expect(PlanningEventManager.isDescriptionEmpty("<p>   </p>")).toBeTrue();
10
-    expect(PlanningEventManager.isDescriptionEmpty("<p><br></p>")).toBeTrue();
11
-    expect(PlanningEventManager.isDescriptionEmpty("<p><br></p><p><br></p>")).toBeTrue();
12
-    expect(PlanningEventManager.isDescriptionEmpty("<p><br><br><br></p>")).toBeTrue();
13
-    expect(PlanningEventManager.isDescriptionEmpty("<p><br>")).toBeTrue();
14
-    expect(PlanningEventManager.isDescriptionEmpty(null)).toBeTrue();
15
-    expect(PlanningEventManager.isDescriptionEmpty(undefined)).toBeTrue();
16
-    expect(PlanningEventManager.isDescriptionEmpty("coucou")).toBeFalse();
17
-    expect(PlanningEventManager.isDescriptionEmpty("<p>coucou</p>")).toBeFalse();
18
-});
19
-
20
-test('isEventDateStringFormatValid', () => {
21
-    expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21 09:00")).toBeTrue();
22
-    expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 01:16")).toBeTrue();
23
-
24
-    expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 01:16:00")).toBeFalse();
25
-    expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 1:16")).toBeFalse();
26
-    expect(PlanningEventManager.isEventDateStringFormatValid("3214-f4-12 01:16")).toBeFalse();
27
-    expect(PlanningEventManager.isEventDateStringFormatValid("sqdd 09:00")).toBeFalse();
28
-    expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21")).toBeFalse();
29
-    expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21 truc")).toBeFalse();
30
-    expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 1:16:65")).toBeFalse();
31
-    expect(PlanningEventManager.isEventDateStringFormatValid("garbage")).toBeFalse();
32
-    expect(PlanningEventManager.isEventDateStringFormatValid("")).toBeFalse();
33
-    expect(PlanningEventManager.isEventDateStringFormatValid(undefined)).toBeFalse();
34
-    expect(PlanningEventManager.isEventDateStringFormatValid(null)).toBeFalse();
35
-});
36
-
37
-test('stringToDate', () => {
38
-    let testDate = new Date();
39
-    expect(PlanningEventManager.stringToDate(undefined)).toBeNull();
40
-    expect(PlanningEventManager.stringToDate("")).toBeNull();
41
-    expect(PlanningEventManager.stringToDate("garbage")).toBeNull();
42
-    expect(PlanningEventManager.stringToDate("2020-03-21")).toBeNull();
43
-    expect(PlanningEventManager.stringToDate("09:00:00")).toBeNull();
44
-    expect(PlanningEventManager.stringToDate("2020-03-21 09:g0")).toBeNull();
45
-    expect(PlanningEventManager.stringToDate("2020-03-21 09:g0:")).toBeNull();
46
-    testDate.setFullYear(2020, 2, 21);
47
-    testDate.setHours(9, 0, 0, 0);
48
-    expect(PlanningEventManager.stringToDate("2020-03-21 09:00")).toEqual(testDate);
49
-    testDate.setFullYear(2020, 0, 31);
50
-    testDate.setHours(18, 30, 0, 0);
51
-    expect(PlanningEventManager.stringToDate("2020-01-31 18:30")).toEqual(testDate);
52
-    testDate.setFullYear(2020, 50, 50);
53
-    testDate.setHours(65, 65, 0, 0);
54
-    expect(PlanningEventManager.stringToDate("2020-51-50 65:65")).toEqual(testDate);
55
-});
56
-
57
-test('getFormattedEventTime', () => {
58
-    expect(PlanningEventManager.getFormattedEventTime(null, null))
59
-        .toBe('/ - /');
60
-    expect(PlanningEventManager.getFormattedEventTime(undefined, undefined))
61
-        .toBe('/ - /');
62
-    expect(PlanningEventManager.getFormattedEventTime("20:30", "23:00"))
63
-        .toBe('/ - /');
64
-    expect(PlanningEventManager.getFormattedEventTime("2020-03-30", "2020-03-31"))
65
-        .toBe('/ - /');
66
-
67
-
68
-    expect(PlanningEventManager.getFormattedEventTime("2020-03-21 09:00", "2020-03-21 09:00"))
69
-        .toBe('09:00');
70
-    expect(PlanningEventManager.getFormattedEventTime("2020-03-21 09:00", "2020-03-22 17:00"))
71
-        .toBe('09:00 - 23:59');
72
-    expect(PlanningEventManager.getFormattedEventTime("2020-03-30 20:30", "2020-03-30 23:00"))
73
-        .toBe('20:30 - 23:00');
74
-});
75
-
76
-test('getDateOnlyString', () => {
77
-    expect(PlanningEventManager.getDateOnlyString("2020-03-21 09:00")).toBe("2020-03-21");
78
-    expect(PlanningEventManager.getDateOnlyString("2021-12-15 09:00")).toBe("2021-12-15");
79
-    expect(PlanningEventManager.getDateOnlyString("2021-12-o5 09:00")).toBeNull();
80
-    expect(PlanningEventManager.getDateOnlyString("2021-12-15 09:")).toBeNull();
81
-    expect(PlanningEventManager.getDateOnlyString("2021-12-15")).toBeNull();
82
-    expect(PlanningEventManager.getDateOnlyString("garbage")).toBeNull();
83
-});
84
-
85
-test('isEventBefore', () => {
86
-    expect(PlanningEventManager.isEventBefore(
87
-        "2020-03-21 09:00", "2020-03-21 10:00")).toBeTrue();
88
-    expect(PlanningEventManager.isEventBefore(
89
-        "2020-03-21 10:00", "2020-03-21 10:15")).toBeTrue();
90
-    expect(PlanningEventManager.isEventBefore(
91
-        "2020-03-21 10:15", "2021-03-21 10:15")).toBeTrue();
92
-    expect(PlanningEventManager.isEventBefore(
93
-        "2020-03-21 10:15", "2020-05-21 10:15")).toBeTrue();
94
-    expect(PlanningEventManager.isEventBefore(
95
-        "2020-03-21 10:15", "2020-03-30 10:15")).toBeTrue();
96
-
97
-    expect(PlanningEventManager.isEventBefore(
98
-        "2020-03-21 10:00", "2020-03-21 10:00")).toBeFalse();
99
-    expect(PlanningEventManager.isEventBefore(
100
-        "2020-03-21 10:00", "2020-03-21 09:00")).toBeFalse();
101
-    expect(PlanningEventManager.isEventBefore(
102
-        "2020-03-21 10:15", "2020-03-21 10:00")).toBeFalse();
103
-    expect(PlanningEventManager.isEventBefore(
104
-        "2021-03-21 10:15", "2020-03-21 10:15")).toBeFalse();
105
-    expect(PlanningEventManager.isEventBefore(
106
-        "2020-05-21 10:15", "2020-03-21 10:15")).toBeFalse();
107
-    expect(PlanningEventManager.isEventBefore(
108
-        "2020-03-30 10:15", "2020-03-21 10:15")).toBeFalse();
109
-
110
-    expect(PlanningEventManager.isEventBefore(
111
-        "garbage", "2020-03-21 10:15")).toBeFalse();
112
-    expect(PlanningEventManager.isEventBefore(
113
-        undefined, undefined)).toBeFalse();
114
-});
115
-
116
-test('dateToString', () => {
117
-    let testDate = new Date();
118
-    testDate.setFullYear(2020, 2, 21);
119
-    testDate.setHours(9, 0, 0, 0);
120
-    expect(PlanningEventManager.dateToString(testDate)).toBe("2020-03-21 09:00");
121
-    testDate.setFullYear(2021, 0, 12);
122
-    testDate.setHours(9, 10, 0, 0);
123
-    expect(PlanningEventManager.dateToString(testDate)).toBe("2021-01-12 09:10");
124
-    testDate.setFullYear(2022, 11, 31);
125
-    testDate.setHours(9, 10, 15, 0);
126
-    expect(PlanningEventManager.dateToString(testDate)).toBe("2022-12-31 09:10");
127
-});
128
-
129
-test('generateEmptyCalendar', () => {
130
-    jest.spyOn(Date, 'now')
131
-        .mockImplementation(() =>
132
-            new Date('2020-01-14T00:00:00.000Z').getTime()
133
-        );
134
-    let calendar = PlanningEventManager.generateEmptyCalendar(1);
135
-    expect(calendar).toHaveProperty("2020-01-14");
136
-    expect(calendar).toHaveProperty("2020-01-20");
137
-    expect(calendar).toHaveProperty("2020-02-10");
138
-    expect(Object.keys(calendar).length).toBe(32);
139
-    calendar = PlanningEventManager.generateEmptyCalendar(3);
140
-    expect(calendar).toHaveProperty("2020-01-14");
141
-    expect(calendar).toHaveProperty("2020-01-20");
142
-    expect(calendar).toHaveProperty("2020-02-10");
143
-    expect(calendar).toHaveProperty("2020-02-14");
144
-    expect(calendar).toHaveProperty("2020-03-20");
145
-    expect(calendar).toHaveProperty("2020-04-12");
146
-    expect(Object.keys(calendar).length).toBe(92);
147
-});
148
-
149
-test('pushEventInOrder', () => {
150
-    let eventArray = [];
151
-    let event1 = {date_begin: "2020-01-14 09:15"};
152
-    PlanningEventManager.pushEventInOrder(eventArray, event1);
153
-    expect(eventArray.length).toBe(1);
154
-    expect(eventArray[0]).toBe(event1);
155
-
156
-    let event2 = {date_begin: "2020-01-14 10:15"};
157
-    PlanningEventManager.pushEventInOrder(eventArray, event2);
158
-    expect(eventArray.length).toBe(2);
159
-    expect(eventArray[0]).toBe(event1);
160
-    expect(eventArray[1]).toBe(event2);
161
-
162
-    let event3 = {date_begin: "2020-01-14 10:15", title: "garbage"};
163
-    PlanningEventManager.pushEventInOrder(eventArray, event3);
164
-    expect(eventArray.length).toBe(3);
165
-    expect(eventArray[0]).toBe(event1);
166
-    expect(eventArray[1]).toBe(event2);
167
-    expect(eventArray[2]).toBe(event3);
168
-
169
-    let event4 = {date_begin: "2020-01-13 09:00"};
170
-    PlanningEventManager.pushEventInOrder(eventArray, event4);
171
-    expect(eventArray.length).toBe(4);
172
-    expect(eventArray[0]).toBe(event4);
173
-    expect(eventArray[1]).toBe(event1);
174
-    expect(eventArray[2]).toBe(event2);
175
-    expect(eventArray[3]).toBe(event3);
176
-});
177
-
178
-test('generateEventAgenda', () => {
179
-    jest.spyOn(Date, 'now')
180
-        .mockImplementation(() =>
181
-            new Date('2020-01-14T00:00:00.000Z').getTime()
182
-        );
183
-    let eventList = [
184
-        {date_begin: "2020-01-14 09:15"},
185
-        {date_begin: "2020-02-01 09:15"},
186
-        {date_begin: "2020-01-15 09:15"},
187
-        {date_begin: "2020-02-01 09:30"},
188
-        {date_begin: "2020-02-01 08:30"},
189
-    ];
190
-    const calendar = PlanningEventManager.generateEventAgenda(eventList, 2);
191
-    expect(calendar["2020-01-14"].length).toBe(1);
192
-    expect(calendar["2020-01-14"][0]).toBe(eventList[0]);
193
-    expect(calendar["2020-01-15"].length).toBe(1);
194
-    expect(calendar["2020-01-15"][0]).toBe(eventList[2]);
195
-    expect(calendar["2020-02-01"].length).toBe(3);
196
-    expect(calendar["2020-02-01"][0]).toBe(eventList[4]);
197
-    expect(calendar["2020-02-01"][1]).toBe(eventList[1]);
198
-    expect(calendar["2020-02-01"][2]).toBe(eventList[3]);
199
-});
200
-
201
-test('getCurrentDateString', () => {
202
-    jest.spyOn(Date, 'now')
203
-        .mockImplementation(() => {
204
-            let date = new Date();
205
-            date.setFullYear(2020, 0, 14);
206
-            date.setHours(15, 30, 54, 65);
207
-            return date.getTime();
208
-        });
209
-    expect(PlanningEventManager.getCurrentDateString()).toBe('2020-01-14 15:30');
210
-});

Loading…
Cancel
Save