forked from vergnet/application-amicale
Improved project structure
This commit is contained in:
parent
fac9d8208e
commit
7e90b80ca2
30 changed files with 672 additions and 698 deletions
12
App.js
12
App.js
|
@ -2,17 +2,17 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import {Platform, StatusBar} from 'react-native';
|
||||
import LocaleManager from './utils/LocaleManager';
|
||||
import AsyncStorageManager from "./utils/AsyncStorageManager";
|
||||
import LocaleManager from './managers/LocaleManager';
|
||||
import AsyncStorageManager from "./managers/AsyncStorageManager";
|
||||
import CustomIntroSlider from "./components/CustomIntroSlider";
|
||||
import {SplashScreen} from 'expo';
|
||||
import ThemeManager from './utils/ThemeManager';
|
||||
import ThemeManager from './managers/ThemeManager';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import {createStackNavigator} from '@react-navigation/stack';
|
||||
import DrawerNavigator from './navigation/DrawerNavigator';
|
||||
import NotificationsManager from "./utils/NotificationsManager";
|
||||
import {initExpoToken} from "./utils/Notifications";
|
||||
import {Provider as PaperProvider} from 'react-native-paper';
|
||||
import AprilFoolsManager from "./utils/AprilFoolsManager";
|
||||
import AprilFoolsManager from "./managers/AprilFoolsManager";
|
||||
import Update from "./constants/Update";
|
||||
|
||||
type Props = {};
|
||||
|
@ -90,7 +90,7 @@ export default class App extends React.Component<Props, State> {
|
|||
// Wait for custom fonts to be loaded before showing the app
|
||||
await AsyncStorageManager.getInstance().loadPreferences();
|
||||
ThemeManager.getInstance().setUpdateThemeCallback(this.onUpdateTheme);
|
||||
await NotificationsManager.initExpoToken();
|
||||
await initExpoToken();
|
||||
this.onLoadFinished();
|
||||
}
|
||||
|
||||
|
|
210
__tests__/utils/PlanningEventManager.test.js
Normal file
210
__tests__/utils/PlanningEventManager.test.js
Normal file
|
@ -0,0 +1,210 @@
|
|||
import React from 'react';
|
||||
import * as Planning from "../../utils/Planning";
|
||||
|
||||
test('isDescriptionEmpty', () => {
|
||||
expect(Planning.isDescriptionEmpty("")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty(" ")).toBeTrue();
|
||||
// noinspection CheckTagEmptyBody
|
||||
expect(Planning.isDescriptionEmpty("<p></p>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("<p> </p>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("<p><br></p>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("<p><br></p><p><br></p>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("<p><br><br><br></p>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("<p><br>")).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty(null)).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty(undefined)).toBeTrue();
|
||||
expect(Planning.isDescriptionEmpty("coucou")).toBeFalse();
|
||||
expect(Planning.isDescriptionEmpty("<p>coucou</p>")).toBeFalse();
|
||||
});
|
||||
|
||||
test('isEventDateStringFormatValid', () => {
|
||||
expect(Planning.isEventDateStringFormatValid("2020-03-21 09:00")).toBeTrue();
|
||||
expect(Planning.isEventDateStringFormatValid("3214-64-12 01:16")).toBeTrue();
|
||||
|
||||
expect(Planning.isEventDateStringFormatValid("3214-64-12 01:16:00")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("3214-64-12 1:16")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("3214-f4-12 01:16")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("sqdd 09:00")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("2020-03-21")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("2020-03-21 truc")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("3214-64-12 1:16:65")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("garbage")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid("")).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid(undefined)).toBeFalse();
|
||||
expect(Planning.isEventDateStringFormatValid(null)).toBeFalse();
|
||||
});
|
||||
|
||||
test('stringToDate', () => {
|
||||
let testDate = new Date();
|
||||
expect(Planning.stringToDate(undefined)).toBeNull();
|
||||
expect(Planning.stringToDate("")).toBeNull();
|
||||
expect(Planning.stringToDate("garbage")).toBeNull();
|
||||
expect(Planning.stringToDate("2020-03-21")).toBeNull();
|
||||
expect(Planning.stringToDate("09:00:00")).toBeNull();
|
||||
expect(Planning.stringToDate("2020-03-21 09:g0")).toBeNull();
|
||||
expect(Planning.stringToDate("2020-03-21 09:g0:")).toBeNull();
|
||||
testDate.setFullYear(2020, 2, 21);
|
||||
testDate.setHours(9, 0, 0, 0);
|
||||
expect(Planning.stringToDate("2020-03-21 09:00")).toEqual(testDate);
|
||||
testDate.setFullYear(2020, 0, 31);
|
||||
testDate.setHours(18, 30, 0, 0);
|
||||
expect(Planning.stringToDate("2020-01-31 18:30")).toEqual(testDate);
|
||||
testDate.setFullYear(2020, 50, 50);
|
||||
testDate.setHours(65, 65, 0, 0);
|
||||
expect(Planning.stringToDate("2020-51-50 65:65")).toEqual(testDate);
|
||||
});
|
||||
|
||||
test('getFormattedEventTime', () => {
|
||||
expect(Planning.getFormattedEventTime(null, null))
|
||||
.toBe('/ - /');
|
||||
expect(Planning.getFormattedEventTime(undefined, undefined))
|
||||
.toBe('/ - /');
|
||||
expect(Planning.getFormattedEventTime("20:30", "23:00"))
|
||||
.toBe('/ - /');
|
||||
expect(Planning.getFormattedEventTime("2020-03-30", "2020-03-31"))
|
||||
.toBe('/ - /');
|
||||
|
||||
|
||||
expect(Planning.getFormattedEventTime("2020-03-21 09:00", "2020-03-21 09:00"))
|
||||
.toBe('09:00');
|
||||
expect(Planning.getFormattedEventTime("2020-03-21 09:00", "2020-03-22 17:00"))
|
||||
.toBe('09:00 - 23:59');
|
||||
expect(Planning.getFormattedEventTime("2020-03-30 20:30", "2020-03-30 23:00"))
|
||||
.toBe('20:30 - 23:00');
|
||||
});
|
||||
|
||||
test('getDateOnlyString', () => {
|
||||
expect(Planning.getDateOnlyString("2020-03-21 09:00")).toBe("2020-03-21");
|
||||
expect(Planning.getDateOnlyString("2021-12-15 09:00")).toBe("2021-12-15");
|
||||
expect(Planning.getDateOnlyString("2021-12-o5 09:00")).toBeNull();
|
||||
expect(Planning.getDateOnlyString("2021-12-15 09:")).toBeNull();
|
||||
expect(Planning.getDateOnlyString("2021-12-15")).toBeNull();
|
||||
expect(Planning.getDateOnlyString("garbage")).toBeNull();
|
||||
});
|
||||
|
||||
test('isEventBefore', () => {
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 09:00", "2020-03-21 10:00")).toBeTrue();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 10:15")).toBeTrue();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:15", "2021-03-21 10:15")).toBeTrue();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-05-21 10:15")).toBeTrue();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-03-30 10:15")).toBeTrue();
|
||||
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 10:00")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 09:00")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-03-21 10:00")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
"2021-03-21 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-05-21 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
"2020-03-30 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
|
||||
expect(Planning.isEventBefore(
|
||||
"garbage", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(Planning.isEventBefore(
|
||||
undefined, undefined)).toBeFalse();
|
||||
});
|
||||
|
||||
test('dateToString', () => {
|
||||
let testDate = new Date();
|
||||
testDate.setFullYear(2020, 2, 21);
|
||||
testDate.setHours(9, 0, 0, 0);
|
||||
expect(Planning.dateToString(testDate)).toBe("2020-03-21 09:00");
|
||||
testDate.setFullYear(2021, 0, 12);
|
||||
testDate.setHours(9, 10, 0, 0);
|
||||
expect(Planning.dateToString(testDate)).toBe("2021-01-12 09:10");
|
||||
testDate.setFullYear(2022, 11, 31);
|
||||
testDate.setHours(9, 10, 15, 0);
|
||||
expect(Planning.dateToString(testDate)).toBe("2022-12-31 09:10");
|
||||
});
|
||||
|
||||
test('generateEmptyCalendar', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() =>
|
||||
new Date('2020-01-14T00:00:00.000Z').getTime()
|
||||
);
|
||||
let calendar = Planning.generateEmptyCalendar(1);
|
||||
expect(calendar).toHaveProperty("2020-01-14");
|
||||
expect(calendar).toHaveProperty("2020-01-20");
|
||||
expect(calendar).toHaveProperty("2020-02-10");
|
||||
expect(Object.keys(calendar).length).toBe(32);
|
||||
calendar = Planning.generateEmptyCalendar(3);
|
||||
expect(calendar).toHaveProperty("2020-01-14");
|
||||
expect(calendar).toHaveProperty("2020-01-20");
|
||||
expect(calendar).toHaveProperty("2020-02-10");
|
||||
expect(calendar).toHaveProperty("2020-02-14");
|
||||
expect(calendar).toHaveProperty("2020-03-20");
|
||||
expect(calendar).toHaveProperty("2020-04-12");
|
||||
expect(Object.keys(calendar).length).toBe(92);
|
||||
});
|
||||
|
||||
test('pushEventInOrder', () => {
|
||||
let eventArray = [];
|
||||
let event1 = {date_begin: "2020-01-14 09:15"};
|
||||
Planning.pushEventInOrder(eventArray, event1);
|
||||
expect(eventArray.length).toBe(1);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
|
||||
let event2 = {date_begin: "2020-01-14 10:15"};
|
||||
Planning.pushEventInOrder(eventArray, event2);
|
||||
expect(eventArray.length).toBe(2);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
expect(eventArray[1]).toBe(event2);
|
||||
|
||||
let event3 = {date_begin: "2020-01-14 10:15", title: "garbage"};
|
||||
Planning.pushEventInOrder(eventArray, event3);
|
||||
expect(eventArray.length).toBe(3);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
expect(eventArray[1]).toBe(event2);
|
||||
expect(eventArray[2]).toBe(event3);
|
||||
|
||||
let event4 = {date_begin: "2020-01-13 09:00"};
|
||||
Planning.pushEventInOrder(eventArray, event4);
|
||||
expect(eventArray.length).toBe(4);
|
||||
expect(eventArray[0]).toBe(event4);
|
||||
expect(eventArray[1]).toBe(event1);
|
||||
expect(eventArray[2]).toBe(event2);
|
||||
expect(eventArray[3]).toBe(event3);
|
||||
});
|
||||
|
||||
test('generateEventAgenda', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() =>
|
||||
new Date('2020-01-14T00:00:00.000Z').getTime()
|
||||
);
|
||||
let eventList = [
|
||||
{date_begin: "2020-01-14 09:15"},
|
||||
{date_begin: "2020-02-01 09:15"},
|
||||
{date_begin: "2020-01-15 09:15"},
|
||||
{date_begin: "2020-02-01 09:30"},
|
||||
{date_begin: "2020-02-01 08:30"},
|
||||
];
|
||||
const calendar = Planning.generateEventAgenda(eventList, 2);
|
||||
expect(calendar["2020-01-14"].length).toBe(1);
|
||||
expect(calendar["2020-01-14"][0]).toBe(eventList[0]);
|
||||
expect(calendar["2020-01-15"].length).toBe(1);
|
||||
expect(calendar["2020-01-15"][0]).toBe(eventList[2]);
|
||||
expect(calendar["2020-02-01"].length).toBe(3);
|
||||
expect(calendar["2020-02-01"][0]).toBe(eventList[4]);
|
||||
expect(calendar["2020-02-01"][1]).toBe(eventList[1]);
|
||||
expect(calendar["2020-02-01"][2]).toBe(eventList[3]);
|
||||
});
|
||||
|
||||
test('getCurrentDateString', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() => {
|
||||
let date = new Date();
|
||||
date.setFullYear(2020, 0, 14);
|
||||
date.setHours(15, 30, 54, 65);
|
||||
return date.getTime();
|
||||
});
|
||||
expect(Planning.getCurrentDateString()).toBe('2020-01-14 15:30');
|
||||
});
|
|
@ -5,7 +5,7 @@ import {StyleSheet, View} from "react-native";
|
|||
import HTML from "react-native-render-html";
|
||||
import i18n from "i18n-js";
|
||||
import {Avatar, Button, Card, withTheme} from 'react-native-paper';
|
||||
import PlanningEventManager from "../utils/PlanningEventManager";
|
||||
import {getFormattedEventTime, isDescriptionEmpty} from "../utils/Planning";
|
||||
|
||||
/**
|
||||
* Component used to display an event preview if an event is available
|
||||
|
@ -17,7 +17,7 @@ function PreviewEventDashboardItem(props) {
|
|||
const {colors} = props.theme;
|
||||
const isEmpty = props.event === undefined
|
||||
? true
|
||||
: PlanningEventManager.isDescriptionEmpty(props.event['description']);
|
||||
: isDescriptionEmpty(props.event['description']);
|
||||
|
||||
if (props.event !== undefined && props.event !== null) {
|
||||
const hasImage = props.event['logo'] !== '' && props.event['logo'] !== null;
|
||||
|
@ -34,12 +34,12 @@ function PreviewEventDashboardItem(props) {
|
|||
{hasImage ?
|
||||
<Card.Title
|
||||
title={props.event['title']}
|
||||
subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
||||
subtitle={getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
||||
left={getImage}
|
||||
/> :
|
||||
<Card.Title
|
||||
title={props.event['title']}
|
||||
subtitle={PlanningEventManager.getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
||||
subtitle={getFormattedEventTime(props.event['date_begin'], props.event['date_end'])}
|
||||
/>}
|
||||
{!isEmpty ?
|
||||
<Card.Content style={styles.content}>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import WebDataManager from "../utils/WebDataManager";
|
||||
import {readData} from "../utils/WebData";
|
||||
import i18n from "i18n-js";
|
||||
import {Snackbar} from 'react-native-paper';
|
||||
import {RefreshControl, SectionList, View} from "react-native";
|
||||
|
@ -42,8 +42,6 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
updateData: 0,
|
||||
};
|
||||
|
||||
webDataManager: WebDataManager;
|
||||
|
||||
refreshInterval: IntervalID;
|
||||
lastRefresh: Date;
|
||||
|
||||
|
@ -79,7 +77,6 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
* Allows to detect when the screen is focused
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.webDataManager = new WebDataManager(this.props.fetchUrl);
|
||||
const onScreenFocus = this.onScreenFocus.bind(this);
|
||||
const onScreenBlur = this.onScreenBlur.bind(this);
|
||||
this.props.navigation.addListener('focus', onScreenFocus);
|
||||
|
@ -144,7 +141,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
|
|||
canRefresh = true;
|
||||
if (canRefresh) {
|
||||
this.setState({refreshing: true});
|
||||
this.webDataManager.readData()
|
||||
readData(this.props.fetchUrl)
|
||||
.then(this.onFetchSuccess)
|
||||
.catch(this.onFetchError);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<coverage generated="1584889501493" clover="3.2.0">
|
||||
<project timestamp="1584889501493" name="All files">
|
||||
<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"/>
|
||||
<file name="PlanningEventManager.js" path="/home/keplyx/expo-projects/application-amicale/utils/PlanningEventManager.js">
|
||||
<file name="Planning.js" path="/home/keplyx/expo-projects/application-amicale/utils/Planning.js">
|
||||
<metrics statements="65" coveredstatements="65" conditionals="39" coveredconditionals="36" methods="11" coveredmethods="11"/>
|
||||
<line num="18" count="1" type="stmt"/>
|
||||
<line num="27" count="1" type="stmt"/>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for PlanningEventManager.js</title>
|
||||
<title>Code coverage report for Planning.js</title>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="prettify.css" />
|
||||
<link rel="stylesheet" href="base.css" />
|
||||
|
@ -19,7 +19,7 @@
|
|||
<body>
|
||||
<div class='wrapper'>
|
||||
<div class='pad1'>
|
||||
<h1><a href="index.html">All files</a> PlanningEventManager.js</h1>
|
||||
<h1><a href="index.html">All files</a> Planning.js</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
|
@ -806,4 +806,3 @@ export default class PlanningEventManager {
|
|||
<script src="block-navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file high" data-value="PlanningEventManager.js"><a href="PlanningEventManager.js.html">PlanningEventManager.js</a></td>
|
||||
<td class="file high" data-value="Planning.js"><a href="PlanningEventManager.js.html">Planning.js</a></td>
|
||||
<td data-value="100" class="pic high">
|
||||
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
||||
</td>
|
||||
|
@ -108,4 +108,3 @@
|
|||
<script src="block-navigation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
TN:
|
||||
SF:utils/PlanningEventManager.js
|
||||
SF:utils/Planning.js
|
||||
FN:26,(anonymous_0)
|
||||
FN:37,(anonymous_1)
|
||||
FN:53,(anonymous_2)
|
||||
|
|
|
@ -12,7 +12,7 @@ import ProximoListScreen from "../screens/Proximo/ProximoListScreen";
|
|||
import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
|
||||
import PlanexScreen from '../screens/Websites/PlanexScreen';
|
||||
import {MaterialCommunityIcons} from "@expo/vector-icons";
|
||||
import AsyncStorageManager from "../utils/AsyncStorageManager";
|
||||
import AsyncStorageManager from "../managers/AsyncStorageManager";
|
||||
import HeaderButton from "../components/HeaderButton";
|
||||
import {withTheme} from 'react-native-paper';
|
||||
import i18n from "i18n-js";
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as React from 'react';
|
|||
import {FlatList, Linking, Platform, View} from 'react-native';
|
||||
import i18n from "i18n-js";
|
||||
import appJson from '../../app';
|
||||
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||
import CustomModal from "../../components/CustomModal";
|
||||
import {Avatar, Button, Card, List, Text, Title, withTheme} from 'react-native-paper';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import {ScrollView, View} from "react-native";
|
||||
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||
import CustomModal from "../../components/CustomModal";
|
||||
import {Button, Card, List, Subheading, TextInput, Title, withTheme} from 'react-native-paper';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {Text, withTheme} from 'react-native-paper';
|
|||
import FeedItem from "../components/FeedItem";
|
||||
import SquareDashboardItem from "../components/SquareDashboardItem";
|
||||
import PreviewEventDashboardItem from "../components/PreviewEventDashboardItem";
|
||||
import PlanningEventManager from "../utils/PlanningEventManager";
|
||||
import {stringToDate} from "../utils/Planning";
|
||||
// import DATA from "../dashboard_data.json";
|
||||
|
||||
|
||||
|
@ -201,8 +201,8 @@ class HomeScreen extends React.Component<Props> {
|
|||
* @return {number} The number of milliseconds
|
||||
*/
|
||||
getEventDuration(event: Object): number {
|
||||
let start = PlanningEventManager.stringToDate(event['date_begin']);
|
||||
let end = PlanningEventManager.stringToDate(event['date_end']);
|
||||
let start = stringToDate(event['date_begin']);
|
||||
let end = stringToDate(event['date_end']);
|
||||
let duration = 0;
|
||||
if (start !== undefined && start !== null && end !== undefined && end !== null)
|
||||
duration = end - start;
|
||||
|
@ -219,7 +219,7 @@ class HomeScreen extends React.Component<Props> {
|
|||
getEventsAfterLimit(events: Object, limit: Date): Array<Object> {
|
||||
let validEvents = [];
|
||||
for (let event of events) {
|
||||
let startDate = PlanningEventManager.stringToDate(event['date_begin']);
|
||||
let startDate = stringToDate(event['date_begin']);
|
||||
if (startDate !== undefined && startDate !== null && startDate >= limit) {
|
||||
validEvents.push(event);
|
||||
}
|
||||
|
@ -255,8 +255,8 @@ class HomeScreen extends React.Component<Props> {
|
|||
let validEvents = [];
|
||||
let now = new Date();
|
||||
for (let event of events) {
|
||||
let startDate = PlanningEventManager.stringToDate(event['date_begin']);
|
||||
let endDate = PlanningEventManager.stringToDate(event['date_end']);
|
||||
let startDate = stringToDate(event['date_begin']);
|
||||
let endDate = stringToDate(event['date_end']);
|
||||
if (startDate !== undefined && startDate !== null) {
|
||||
if (startDate > now)
|
||||
validEvents.push(event);
|
||||
|
|
|
@ -4,9 +4,9 @@ import * as React from 'react';
|
|||
import {Image, ScrollView, View} from 'react-native';
|
||||
import HTML from "react-native-render-html";
|
||||
import {Linking} from "expo";
|
||||
import PlanningEventManager from '../../utils/PlanningEventManager';
|
||||
import {getDateOnlyString, getFormattedEventTime} from '../../utils/Planning';
|
||||
import {Card, withTheme} from 'react-native-paper';
|
||||
import DateManager from "../../utils/DateManager";
|
||||
import DateManager from "../../managers/DateManager";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
|
@ -33,9 +33,9 @@ class PlanningDisplayScreen extends React.Component<Props> {
|
|||
|
||||
render() {
|
||||
// console.log("rendering planningDisplayScreen");
|
||||
let subtitle = PlanningEventManager.getFormattedEventTime(
|
||||
let subtitle = getFormattedEventTime(
|
||||
this.displayData["date_begin"], this.displayData["date_end"]);
|
||||
let dateString = PlanningEventManager.getDateOnlyString(this.displayData["date_begin"]);
|
||||
let dateString = getDateOnlyString(this.displayData["date_begin"]);
|
||||
if (dateString !== null)
|
||||
subtitle += ' | ' + DateManager.getInstance().getTranslatedDate(dateString);
|
||||
return (
|
||||
|
|
|
@ -4,9 +4,14 @@ import * as React from 'react';
|
|||
import {BackHandler, View} from 'react-native';
|
||||
import i18n from "i18n-js";
|
||||
import {LocaleConfig} from 'react-native-calendars';
|
||||
import WebDataManager from "../../utils/WebDataManager";
|
||||
import type {eventObject} from "../../utils/PlanningEventManager";
|
||||
import PlanningEventManager from '../../utils/PlanningEventManager';
|
||||
import {readData} from "../../utils/WebData";
|
||||
import type {eventObject} from "../../utils/Planning";
|
||||
import {
|
||||
generateEventAgenda,
|
||||
getCurrentDateString,
|
||||
getDateOnlyString,
|
||||
getFormattedEventTime,
|
||||
} from '../../utils/Planning';
|
||||
import {Avatar, Divider, List} from 'react-native-paper';
|
||||
import CustomAgenda from "../../components/CustomAgenda";
|
||||
|
||||
|
@ -38,7 +43,6 @@ const AGENDA_MONTH_SPAN = 3;
|
|||
export default class PlanningScreen extends React.Component<Props, State> {
|
||||
|
||||
agendaRef: Object;
|
||||
webDataManager: WebDataManager;
|
||||
|
||||
lastRefresh: Date;
|
||||
minTimeBetweenRefresh = 60;
|
||||
|
@ -59,11 +63,10 @@ export default class PlanningScreen extends React.Component<Props, State> {
|
|||
onAgendaRef: Function;
|
||||
onCalendarToggled: Function;
|
||||
onBackButtonPressAndroid: Function;
|
||||
currentDate = PlanningEventManager.getDateOnlyString(PlanningEventManager.getCurrentDateString());
|
||||
currentDate = getDateOnlyString(getCurrentDateString());
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.webDataManager = new WebDataManager(FETCH_URL);
|
||||
if (i18n.currentLocale().startsWith("fr")) {
|
||||
LocaleConfig.defaultLocale = 'fr';
|
||||
}
|
||||
|
@ -141,11 +144,11 @@ export default class PlanningScreen extends React.Component<Props, State> {
|
|||
|
||||
if (canRefresh) {
|
||||
this.setState({refreshing: true});
|
||||
this.webDataManager.readData()
|
||||
readData(FETCH_URL)
|
||||
.then((fetchedData) => {
|
||||
this.setState({
|
||||
refreshing: false,
|
||||
agendaItems: PlanningEventManager.generateEventAgenda(fetchedData, AGENDA_MONTH_SPAN)
|
||||
agendaItems: generateEventAgenda(fetchedData, AGENDA_MONTH_SPAN)
|
||||
});
|
||||
this.lastRefresh = new Date();
|
||||
})
|
||||
|
@ -189,7 +192,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
|
|||
<Divider/>
|
||||
<List.Item
|
||||
title={item.title}
|
||||
description={PlanningEventManager.getFormattedEventTime(item["date_begin"], item["date_end"])}
|
||||
description={getFormattedEventTime(item["date_begin"], item["date_end"])}
|
||||
left={() => <Avatar.Image
|
||||
source={{uri: item.logo}}
|
||||
style={{backgroundColor: 'transparent'}}
|
||||
|
@ -204,7 +207,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
|
|||
<Divider/>
|
||||
<List.Item
|
||||
title={item.title}
|
||||
description={PlanningEventManager.getFormattedEventTime(item["date_begin"], item["date_end"])}
|
||||
description={getFormattedEventTime(item["date_begin"], item["date_end"])}
|
||||
onPress={onPress}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
@ -4,15 +4,15 @@ import * as React from 'react';
|
|||
import {Alert, Platform, View} from 'react-native';
|
||||
import i18n from "i18n-js";
|
||||
import WebSectionList from "../../components/WebSectionList";
|
||||
import NotificationsManager from "../../utils/NotificationsManager";
|
||||
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||
import * as Notifications from "../../utils/Notifications";
|
||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||
import * as Expo from "expo";
|
||||
import {Avatar, Banner, Button, Card, Text, withTheme} from 'react-native-paper';
|
||||
import HeaderButton from "../../components/HeaderButton";
|
||||
import ProxiwashListItem from "../../components/ProxiwashListItem";
|
||||
import ProxiwashConstants from "../../constants/ProxiwashConstants";
|
||||
import CustomModal from "../../components/CustomModal";
|
||||
import AprilFoolsManager from "../../utils/AprilFoolsManager";
|
||||
import AprilFoolsManager from "../../managers/AprilFoolsManager";
|
||||
|
||||
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json";
|
||||
|
||||
|
@ -118,12 +118,12 @@ class ProxiwashScreen extends React.Component<Props, State> {
|
|||
});
|
||||
if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') {
|
||||
// Get latest watchlist from server
|
||||
NotificationsManager.getMachineNotificationWatchlist((fetchedList) => {
|
||||
Notifications.getMachineNotificationWatchlist((fetchedList) => {
|
||||
this.setState({machinesWatched: fetchedList})
|
||||
});
|
||||
// Get updated watchlist after received notification
|
||||
Expo.Notifications.addListener(() => {
|
||||
NotificationsManager.getMachineNotificationWatchlist((fetchedList) => {
|
||||
Notifications.getMachineNotificationWatchlist((fetchedList) => {
|
||||
this.setState({machinesWatched: fetchedList})
|
||||
});
|
||||
});
|
||||
|
@ -175,7 +175,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
|
|||
setupNotifications(machineId: string) {
|
||||
if (AsyncStorageManager.getInstance().preferences.expoToken.current !== '') {
|
||||
if (!this.isMachineWatched(machineId)) {
|
||||
NotificationsManager.setupMachineNotification(machineId, true);
|
||||
Notifications.setupMachineNotification(machineId, true);
|
||||
this.saveNotificationToState(machineId);
|
||||
} else
|
||||
this.disableNotification(machineId);
|
||||
|
@ -205,7 +205,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
|
|||
if (data.length > 0) {
|
||||
let arrayIndex = data.indexOf(machineId);
|
||||
if (arrayIndex !== -1) {
|
||||
NotificationsManager.setupMachineNotification(machineId, false);
|
||||
Notifications.setupMachineNotification(machineId, false);
|
||||
this.removeNotificationFroState(arrayIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import DateManager from "../utils/DateManager";
|
||||
import DateManager from "../managers/DateManager";
|
||||
import WebSectionList from "../components/WebSectionList";
|
||||
import {Card, Text, withTheme} from 'react-native-paper';
|
||||
import AprilFoolsManager from "../utils/AprilFoolsManager";
|
||||
import AprilFoolsManager from "../managers/AprilFoolsManager";
|
||||
|
||||
const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/menu/menu_data.json";
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import {ScrollView} from "react-native";
|
||||
import ThemeManager from '../utils/ThemeManager';
|
||||
import ThemeManager from '../managers/ThemeManager';
|
||||
import i18n from "i18n-js";
|
||||
import AsyncStorageManager from "../utils/AsyncStorageManager";
|
||||
import NotificationsManager from "../utils/NotificationsManager";
|
||||
import AsyncStorageManager from "../managers/AsyncStorageManager";
|
||||
import {setMachineReminderNotificationTime} from "../utils/Notifications";
|
||||
import {Card, List, Switch, ToggleButton} from 'react-native-paper';
|
||||
import {Appearance} from "react-native-appearance";
|
||||
|
||||
|
@ -60,7 +60,7 @@ export default class SettingsScreen extends React.Component<Props, State> {
|
|||
let intVal = 0;
|
||||
if (value !== 'never')
|
||||
intVal = parseInt(value);
|
||||
NotificationsManager.setMachineReminderNotificationTime(intVal);
|
||||
setMachineReminderNotificationTime(intVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import ThemeManager from "../../utils/ThemeManager";
|
||||
import ThemeManager from "../../managers/ThemeManager";
|
||||
import WebViewScreen from "../../components/WebViewScreen";
|
||||
import {Avatar, Banner} from "react-native-paper";
|
||||
import i18n from "i18n-js";
|
||||
import {View} from "react-native";
|
||||
import AsyncStorageManager from "../../utils/AsyncStorageManager";
|
||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
|
|
125
utils/Notifications.js
Normal file
125
utils/Notifications.js
Normal file
|
@ -0,0 +1,125 @@
|
|||
// @flow
|
||||
|
||||
import * as Permissions from 'expo-permissions';
|
||||
import {Notifications} from 'expo';
|
||||
import AsyncStorageManager from "../managers/AsyncStorageManager";
|
||||
import LocaleManager from "../managers/LocaleManager";
|
||||
import passwords from "../passwords";
|
||||
|
||||
const EXPO_TOKEN_SERVER = 'https://etud.insa-toulouse.fr/~amicale_app/expo_notifications/save_token.php';
|
||||
|
||||
/**
|
||||
* Async function asking permission to send notifications to the user
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export async function askPermissions() {
|
||||
const {status: existingStatus} = await Permissions.getAsync(Permissions.NOTIFICATIONS);
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
|
||||
finalStatus = status;
|
||||
}
|
||||
return finalStatus === 'granted';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save expo token to allow sending notifications to this device.
|
||||
* This token is unique for each device and won't change.
|
||||
* It only needs to be fetched once, then it will be saved in storage.
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export async function initExpoToken() {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token === '') {
|
||||
try {
|
||||
await askPermissions();
|
||||
let expoToken = await Notifications.getExpoPushTokenAsync();
|
||||
// Save token for instant use later on
|
||||
AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.expoToken.key, expoToken);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the machines watched from the server
|
||||
*
|
||||
* @param callback Function to execute with the fetched data
|
||||
*/
|
||||
export function getMachineNotificationWatchlist(callback: Function) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'get_machine_watchlist',
|
||||
password: passwords.expoNotifications,
|
||||
token: token,
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
}).then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
callback(responseJson);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the server to enable/disable notifications for the specified machine
|
||||
*
|
||||
* @param machineID The machine ID
|
||||
* @param isEnabled True to enable notifications, false to disable
|
||||
*/
|
||||
export function setupMachineNotification(machineID: string, isEnabled: boolean) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'setup_machine_notification',
|
||||
password: passwords.expoNotifications,
|
||||
locale: LocaleManager.getCurrentLocale(),
|
||||
token: token,
|
||||
machine_id: machineID,
|
||||
enabled: isEnabled
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the selected reminder time for notifications to the server
|
||||
*
|
||||
* @param time The reminder time to use
|
||||
*/
|
||||
export function setMachineReminderNotificationTime(time: number) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'set_machine_reminder',
|
||||
password: passwords.expoNotifications,
|
||||
token: token,
|
||||
time: time,
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as Permissions from 'expo-permissions';
|
||||
import {Notifications} from 'expo';
|
||||
import AsyncStorageManager from "./AsyncStorageManager";
|
||||
import LocaleManager from "./LocaleManager";
|
||||
import passwords from "../passwords";
|
||||
|
||||
const EXPO_TOKEN_SERVER = 'https://etud.insa-toulouse.fr/~amicale_app/expo_notifications/save_token.php';
|
||||
|
||||
/**
|
||||
* Static class used to manage notifications sent to the user
|
||||
*/
|
||||
export default class NotificationsManager {
|
||||
|
||||
/**
|
||||
* Async function asking permission to send notifications to the user
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
static async askPermissions() {
|
||||
const {status: existingStatus} = await Permissions.getAsync(Permissions.NOTIFICATIONS);
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
|
||||
finalStatus = status;
|
||||
}
|
||||
return finalStatus === 'granted';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save expo token to allow sending notifications to this device.
|
||||
* This token is unique for each device and won't change.
|
||||
* It only needs to be fetched once, then it will be saved in storage.
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
static async initExpoToken() {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token === '') {
|
||||
try {
|
||||
await NotificationsManager.askPermissions();
|
||||
let expoToken = await Notifications.getExpoPushTokenAsync();
|
||||
// Save token for instant use later on
|
||||
AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.expoToken.key, expoToken);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the machines watched from the server
|
||||
*
|
||||
* @param callback Function to execute with the fetched data
|
||||
*/
|
||||
static getMachineNotificationWatchlist(callback: Function) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'get_machine_watchlist',
|
||||
password: passwords.expoNotifications,
|
||||
token: token,
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
}).then((response) => response.json())
|
||||
.then((responseJson) => {
|
||||
callback(responseJson);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the server to enable/disable notifications for the specified machine
|
||||
*
|
||||
* @param machineID The machine ID
|
||||
* @param isEnabled True to enable notifications, false to disable
|
||||
*/
|
||||
static setupMachineNotification(machineID: string, isEnabled: boolean) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'setup_machine_notification',
|
||||
password: passwords.expoNotifications,
|
||||
locale: LocaleManager.getCurrentLocale(),
|
||||
token: token,
|
||||
machine_id: machineID,
|
||||
enabled: isEnabled
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the selected reminder time for notifications to the server
|
||||
*
|
||||
* @param time The reminder time to use
|
||||
*/
|
||||
static setMachineReminderNotificationTime(time: number) {
|
||||
let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
|
||||
if (token !== '') {
|
||||
let data = {
|
||||
function: 'set_machine_reminder',
|
||||
password: passwords.expoNotifications,
|
||||
token: token,
|
||||
time: time,
|
||||
};
|
||||
fetch(EXPO_TOKEN_SERVER, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify(data) // <-- Post parameters
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
240
utils/Planning.js
Normal file
240
utils/Planning.js
Normal file
|
@ -0,0 +1,240 @@
|
|||
// @flow
|
||||
|
||||
export type eventObject = {
|
||||
id: number,
|
||||
title: string,
|
||||
logo: string,
|
||||
date_begin: string,
|
||||
date_end: string,
|
||||
description: string,
|
||||
club: string,
|
||||
category_id: number,
|
||||
url: string,
|
||||
};
|
||||
|
||||
// Regex used to check date string validity
|
||||
const dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
|
||||
|
||||
/**
|
||||
* Gets the current day string representation in the format
|
||||
* YYYY-MM-DD
|
||||
*
|
||||
* @return {string} The string representation
|
||||
*/
|
||||
export function getCurrentDateString(): string {
|
||||
return dateToString(new Date(Date.now()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given date is before the other.
|
||||
*
|
||||
* @param event1Date Event 1 date in format YYYY-MM-DD HH:MM
|
||||
* @param event2Date Event 2 date in format YYYY-MM-DD HH:MM
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isEventBefore(event1Date: string, event2Date: string): boolean {
|
||||
let date1 = stringToDate(event1Date);
|
||||
let date2 = stringToDate(event2Date);
|
||||
if (date1 !== null && date2 !== null)
|
||||
return date1 < date2;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets only the date part of the given event date string in the format
|
||||
* YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to get the date from
|
||||
* @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
|
||||
*/
|
||||
export function getDateOnlyString(dateString: string): string | null {
|
||||
if (isEventDateStringFormatValid(dateString))
|
||||
return dateString.split(" ")[0];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given date string is in the format
|
||||
* YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to check
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isEventDateStringFormatValid(dateString: ?string): boolean {
|
||||
return dateString !== undefined
|
||||
&& dateString !== null
|
||||
&& dateRegExp.test(dateString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given date string to a date object.<br>
|
||||
* Accepted format: YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to convert
|
||||
* @return {Date|null} The date object or null if the given string is invalid
|
||||
*/
|
||||
export function stringToDate(dateString: string): Date | null {
|
||||
let date = new Date();
|
||||
if (isEventDateStringFormatValid(dateString)) {
|
||||
let stringArray = dateString.split(' ');
|
||||
let dateArray = stringArray[0].split('-');
|
||||
let timeArray = stringArray[1].split(':');
|
||||
date.setFullYear(
|
||||
parseInt(dateArray[0]),
|
||||
parseInt(dateArray[1]) - 1, // Month range from 0 to 11
|
||||
parseInt(dateArray[2])
|
||||
);
|
||||
date.setHours(
|
||||
parseInt(timeArray[0]),
|
||||
parseInt(timeArray[1]),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
} else
|
||||
date = null;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a date object to a string in the format
|
||||
* YYYY-MM-DD HH-MM-SS
|
||||
*
|
||||
* @param date The date object to convert
|
||||
* @return {string} The converted string
|
||||
*/
|
||||
export function dateToString(date: Date): string {
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); //January is 0!
|
||||
const year = date.getFullYear();
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string corresponding to the event start and end times in the following format:
|
||||
*
|
||||
* HH:MM - HH:MM
|
||||
*
|
||||
* If the end date is not specified or is equal to start time, only start time will be shown.
|
||||
*
|
||||
* If the end date is not on the same day, 23:59 will be shown as end time
|
||||
*
|
||||
* @param start Start time in YYYY-MM-DD HH:MM:SS format
|
||||
* @param end End time in YYYY-MM-DD HH:MM:SS format
|
||||
* @return {string} Formatted string or "/ - /" on error
|
||||
*/
|
||||
export function getFormattedEventTime(start: string, end: string): string {
|
||||
let formattedStr = '/ - /';
|
||||
let startDate = stringToDate(start);
|
||||
let endDate = stringToDate(end);
|
||||
|
||||
if (startDate !== null && endDate !== null && startDate.getTime() !== endDate.getTime()) {
|
||||
formattedStr = String(startDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(startDate.getMinutes()).padStart(2, '0') + ' - ';
|
||||
if (endDate.getFullYear() > startDate.getFullYear()
|
||||
|| endDate.getMonth() > startDate.getMonth()
|
||||
|| endDate.getDate() > startDate.getDate())
|
||||
formattedStr += '23:59';
|
||||
else
|
||||
formattedStr += String(endDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(endDate.getMinutes()).padStart(2, '0');
|
||||
} else if (startDate !== null)
|
||||
formattedStr =
|
||||
String(startDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(startDate.getMinutes()).padStart(2, '0');
|
||||
|
||||
return formattedStr
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given description can be considered empty.
|
||||
* <br>
|
||||
* An empty description is composed only of whitespace, <b>br</b> or <b>p</b> tags
|
||||
*
|
||||
*
|
||||
* @param description The text to check
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function isDescriptionEmpty(description: ?string): boolean {
|
||||
if (description !== undefined && description !== null) {
|
||||
return description
|
||||
.split('<p>').join('') // Equivalent to a replace all
|
||||
.split('</p>').join('')
|
||||
.split('<br>').join('').trim() === '';
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an object with an empty array for each key.
|
||||
* Each key is a date string in the format
|
||||
* YYYY-MM-DD
|
||||
*
|
||||
* @param numberOfMonths The number of months to create, starting from the current date
|
||||
* @return {Object}
|
||||
*/
|
||||
export function generateEmptyCalendar(numberOfMonths: number): Object {
|
||||
let end = new Date(Date.now());
|
||||
end.setMonth(end.getMonth() + numberOfMonths);
|
||||
let daysOfYear = {};
|
||||
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
||||
const dateString = getDateOnlyString(
|
||||
dateToString(new Date(d)));
|
||||
if (dateString !== null)
|
||||
daysOfYear[dateString] = []
|
||||
}
|
||||
return daysOfYear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an object with an array of eventObject at each key.
|
||||
* Each key is a date string in the format
|
||||
* YYYY-MM-DD.
|
||||
*
|
||||
* If no event is available at the given key, the array will be empty
|
||||
*
|
||||
* @param eventList The list of events to map to the agenda
|
||||
* @param numberOfMonths The number of months to create the agenda for
|
||||
* @return {Object}
|
||||
*/
|
||||
export function generateEventAgenda(eventList: Array<eventObject>, numberOfMonths: number): Object {
|
||||
let agendaItems = generateEmptyCalendar(numberOfMonths);
|
||||
for (let i = 0; i < eventList.length; i++) {
|
||||
const dateString = getDateOnlyString(eventList[i].date_begin);
|
||||
if (dateString !== null) {
|
||||
const eventArray = agendaItems[dateString];
|
||||
if (eventArray !== undefined)
|
||||
this.pushEventInOrder(eventArray, eventList[i]);
|
||||
}
|
||||
|
||||
}
|
||||
return agendaItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds events to the given array depending on their starting date.
|
||||
*
|
||||
* Events starting before are added at the front.
|
||||
*
|
||||
* @param eventArray The array to hold sorted events
|
||||
* @param event The event to add to the array
|
||||
*/
|
||||
export function pushEventInOrder(eventArray: Array<eventObject>, event: eventObject): Object {
|
||||
if (eventArray.length === 0)
|
||||
eventArray.push(event);
|
||||
else {
|
||||
for (let i = 0; i < eventArray.length; i++) {
|
||||
if (isEventBefore(event.date_begin, eventArray[i].date_begin)) {
|
||||
eventArray.splice(i, 0, event);
|
||||
break;
|
||||
} else if (i === eventArray.length - 1) {
|
||||
eventArray.push(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,243 +0,0 @@
|
|||
// @flow
|
||||
|
||||
export type eventObject = {
|
||||
id: number,
|
||||
title: string,
|
||||
logo: string,
|
||||
date_begin: string,
|
||||
date_end: string,
|
||||
description: string,
|
||||
club: string,
|
||||
category_id: number,
|
||||
url: string,
|
||||
};
|
||||
|
||||
export default class PlanningEventManager {
|
||||
|
||||
// Regex used to check date string validity
|
||||
static dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
|
||||
|
||||
/**
|
||||
* Gets the current day string representation in the format
|
||||
* YYYY-MM-DD
|
||||
*
|
||||
* @return {string} The string representation
|
||||
*/
|
||||
static getCurrentDateString(): string {
|
||||
return PlanningEventManager.dateToString(new Date(Date.now()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given date is before the other.
|
||||
*
|
||||
* @param event1Date Event 1 date in format YYYY-MM-DD HH:MM
|
||||
* @param event2Date Event 2 date in format YYYY-MM-DD HH:MM
|
||||
* @return {boolean}
|
||||
*/
|
||||
static isEventBefore(event1Date: string, event2Date: string): boolean {
|
||||
let date1 = PlanningEventManager.stringToDate(event1Date);
|
||||
let date2 = PlanningEventManager.stringToDate(event2Date);
|
||||
if (date1 !== null && date2 !== null)
|
||||
return date1 < date2;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets only the date part of the given event date string in the format
|
||||
* YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to get the date from
|
||||
* @return {string|null} Date in format YYYY:MM:DD or null if given string is invalid
|
||||
*/
|
||||
static getDateOnlyString(dateString: string): string | null {
|
||||
if (PlanningEventManager.isEventDateStringFormatValid(dateString))
|
||||
return dateString.split(" ")[0];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given date string is in the format
|
||||
* YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to check
|
||||
* @return {boolean}
|
||||
*/
|
||||
static isEventDateStringFormatValid(dateString: ?string): boolean {
|
||||
return dateString !== undefined
|
||||
&& dateString !== null
|
||||
&& PlanningEventManager.dateRegExp.test(dateString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given date string to a date object.<br>
|
||||
* Accepted format: YYYY-MM-DD HH:MM
|
||||
*
|
||||
* @param dateString The string to convert
|
||||
* @return {Date|null} The date object or null if the given string is invalid
|
||||
*/
|
||||
static stringToDate(dateString: string): Date | null {
|
||||
let date = new Date();
|
||||
if (PlanningEventManager.isEventDateStringFormatValid(dateString)) {
|
||||
let stringArray = dateString.split(' ');
|
||||
let dateArray = stringArray[0].split('-');
|
||||
let timeArray = stringArray[1].split(':');
|
||||
date.setFullYear(
|
||||
parseInt(dateArray[0]),
|
||||
parseInt(dateArray[1]) - 1, // Month range from 0 to 11
|
||||
parseInt(dateArray[2])
|
||||
);
|
||||
date.setHours(
|
||||
parseInt(timeArray[0]),
|
||||
parseInt(timeArray[1]),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
} else
|
||||
date = null;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a date object to a string in the format
|
||||
* YYYY-MM-DD HH-MM-SS
|
||||
*
|
||||
* @param date The date object to convert
|
||||
* @return {string} The converted string
|
||||
*/
|
||||
static dateToString(date: Date): string {
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); //January is 0!
|
||||
const year = date.getFullYear();
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string corresponding to the event start and end times in the following format:
|
||||
*
|
||||
* HH:MM - HH:MM
|
||||
*
|
||||
* If the end date is not specified or is equal to start time, only start time will be shown.
|
||||
*
|
||||
* If the end date is not on the same day, 23:59 will be shown as end time
|
||||
*
|
||||
* @param start Start time in YYYY-MM-DD HH:MM:SS format
|
||||
* @param end End time in YYYY-MM-DD HH:MM:SS format
|
||||
* @return {string} Formatted string or "/ - /" on error
|
||||
*/
|
||||
static getFormattedEventTime(start: string, end: string): string {
|
||||
let formattedStr = '/ - /';
|
||||
let startDate = PlanningEventManager.stringToDate(start);
|
||||
let endDate = PlanningEventManager.stringToDate(end);
|
||||
|
||||
if (startDate !== null && endDate !== null && startDate.getTime() !== endDate.getTime()) {
|
||||
formattedStr = String(startDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(startDate.getMinutes()).padStart(2, '0') + ' - ';
|
||||
if (endDate.getFullYear() > startDate.getFullYear()
|
||||
|| endDate.getMonth() > startDate.getMonth()
|
||||
|| endDate.getDate() > startDate.getDate())
|
||||
formattedStr += '23:59';
|
||||
else
|
||||
formattedStr += String(endDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(endDate.getMinutes()).padStart(2, '0');
|
||||
} else if (startDate !== null)
|
||||
formattedStr =
|
||||
String(startDate.getHours()).padStart(2, '0') + ':'
|
||||
+ String(startDate.getMinutes()).padStart(2, '0');
|
||||
|
||||
return formattedStr
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given description can be considered empty.
|
||||
* <br>
|
||||
* An empty description is composed only of whitespace, <b>br</b> or <b>p</b> tags
|
||||
*
|
||||
*
|
||||
* @param description The text to check
|
||||
* @return {boolean}
|
||||
*/
|
||||
static isDescriptionEmpty(description: ?string): boolean {
|
||||
if (description !== undefined && description !== null) {
|
||||
return description
|
||||
.split('<p>').join('') // Equivalent to a replace all
|
||||
.split('</p>').join('')
|
||||
.split('<br>').join('').trim() === '';
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an object with an empty array for each key.
|
||||
* Each key is a date string in the format
|
||||
* YYYY-MM-DD
|
||||
*
|
||||
* @param numberOfMonths The number of months to create, starting from the current date
|
||||
* @return {Object}
|
||||
*/
|
||||
static generateEmptyCalendar(numberOfMonths: number): Object {
|
||||
let end = new Date(Date.now());
|
||||
end.setMonth(end.getMonth() + numberOfMonths);
|
||||
let daysOfYear = {};
|
||||
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
||||
const dateString = PlanningEventManager.getDateOnlyString(
|
||||
PlanningEventManager.dateToString(new Date(d)));
|
||||
if (dateString !== null)
|
||||
daysOfYear[dateString] = []
|
||||
}
|
||||
return daysOfYear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an object with an array of eventObject at each key.
|
||||
* Each key is a date string in the format
|
||||
* YYYY-MM-DD.
|
||||
*
|
||||
* If no event is available at the given key, the array will be empty
|
||||
*
|
||||
* @param eventList The list of events to map to the agenda
|
||||
* @param numberOfMonths The number of months to create the agenda for
|
||||
* @return {Object}
|
||||
*/
|
||||
static generateEventAgenda(eventList: Array<eventObject>, numberOfMonths: number): Object {
|
||||
let agendaItems = PlanningEventManager.generateEmptyCalendar(numberOfMonths);
|
||||
for (let i = 0; i < eventList.length; i++) {
|
||||
const dateString = PlanningEventManager.getDateOnlyString(eventList[i].date_begin);
|
||||
if (dateString !== null) {
|
||||
const eventArray = agendaItems[dateString];
|
||||
if (eventArray !== undefined)
|
||||
this.pushEventInOrder(eventArray, eventList[i]);
|
||||
}
|
||||
|
||||
}
|
||||
return agendaItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds events to the given array depending on their starting date.
|
||||
*
|
||||
* Events starting before are added at the front.
|
||||
*
|
||||
* @param eventArray The array to hold sorted events
|
||||
* @param event The event to add to the array
|
||||
*/
|
||||
static pushEventInOrder(eventArray: Array<eventObject>, event: eventObject): Object {
|
||||
if (eventArray.length === 0)
|
||||
eventArray.push(event);
|
||||
else {
|
||||
for (let i = 0; i < eventArray.length; i++) {
|
||||
if (PlanningEventManager.isEventBefore(event.date_begin, eventArray[i].date_begin)) {
|
||||
eventArray.splice(i, 0, event);
|
||||
break;
|
||||
} else if (i === eventArray.length - 1) {
|
||||
eventArray.push(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
utils/WebData.js
Normal file
19
utils/WebData.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* Read data from FETCH_URL and return it.
|
||||
* If no data was found, returns an empty object
|
||||
*
|
||||
* @param url The urls to fetch data from
|
||||
* @return {Promise<Object>}
|
||||
*/
|
||||
export async function readData(url: string) {
|
||||
let fetchedData: Object = {};
|
||||
try {
|
||||
let response = await fetch(url);
|
||||
fetchedData = await response.json();
|
||||
} catch (error) {
|
||||
throw new Error('Could not read FetchedData from server');
|
||||
}
|
||||
return fetchedData;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* Class used to get json data from the web
|
||||
*/
|
||||
export default class WebDataManager {
|
||||
|
||||
FETCH_URL: string;
|
||||
lastDataFetched: Object = {};
|
||||
|
||||
|
||||
constructor(url: string) {
|
||||
this.FETCH_URL = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from FETCH_URL and return it.
|
||||
* If no data was found, returns an empty object
|
||||
*
|
||||
* @return {Promise<Object>}
|
||||
*/
|
||||
async readData() {
|
||||
let fetchedData: Object = {};
|
||||
try {
|
||||
let response = await fetch(this.FETCH_URL);
|
||||
fetchedData = await response.json();
|
||||
} catch (error) {
|
||||
throw new Error('Could not read FetchedData from server');
|
||||
}
|
||||
this.lastDataFetched = fetchedData;
|
||||
return fetchedData;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
import React from 'react';
|
||||
import PlanningEventManager from "../PlanningEventManager";
|
||||
|
||||
test('isDescriptionEmpty', () => {
|
||||
expect(PlanningEventManager.isDescriptionEmpty("")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty(" ")).toBeTrue();
|
||||
// noinspection CheckTagEmptyBody
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p></p>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p> </p>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p><br></p>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p><br></p><p><br></p>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p><br><br><br></p>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p><br>")).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty(null)).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty(undefined)).toBeTrue();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("coucou")).toBeFalse();
|
||||
expect(PlanningEventManager.isDescriptionEmpty("<p>coucou</p>")).toBeFalse();
|
||||
});
|
||||
|
||||
test('isEventDateStringFormatValid', () => {
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21 09:00")).toBeTrue();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 01:16")).toBeTrue();
|
||||
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 01:16:00")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 1:16")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("3214-f4-12 01:16")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("sqdd 09:00")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("2020-03-21 truc")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("3214-64-12 1:16:65")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("garbage")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid("")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid(undefined)).toBeFalse();
|
||||
expect(PlanningEventManager.isEventDateStringFormatValid(null)).toBeFalse();
|
||||
});
|
||||
|
||||
test('stringToDate', () => {
|
||||
let testDate = new Date();
|
||||
expect(PlanningEventManager.stringToDate(undefined)).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("")).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("garbage")).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("2020-03-21")).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("09:00:00")).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("2020-03-21 09:g0")).toBeNull();
|
||||
expect(PlanningEventManager.stringToDate("2020-03-21 09:g0:")).toBeNull();
|
||||
testDate.setFullYear(2020, 2, 21);
|
||||
testDate.setHours(9, 0, 0, 0);
|
||||
expect(PlanningEventManager.stringToDate("2020-03-21 09:00")).toEqual(testDate);
|
||||
testDate.setFullYear(2020, 0, 31);
|
||||
testDate.setHours(18, 30, 0, 0);
|
||||
expect(PlanningEventManager.stringToDate("2020-01-31 18:30")).toEqual(testDate);
|
||||
testDate.setFullYear(2020, 50, 50);
|
||||
testDate.setHours(65, 65, 0, 0);
|
||||
expect(PlanningEventManager.stringToDate("2020-51-50 65:65")).toEqual(testDate);
|
||||
});
|
||||
|
||||
test('getFormattedEventTime', () => {
|
||||
expect(PlanningEventManager.getFormattedEventTime(null, null))
|
||||
.toBe('/ - /');
|
||||
expect(PlanningEventManager.getFormattedEventTime(undefined, undefined))
|
||||
.toBe('/ - /');
|
||||
expect(PlanningEventManager.getFormattedEventTime("20:30", "23:00"))
|
||||
.toBe('/ - /');
|
||||
expect(PlanningEventManager.getFormattedEventTime("2020-03-30", "2020-03-31"))
|
||||
.toBe('/ - /');
|
||||
|
||||
|
||||
expect(PlanningEventManager.getFormattedEventTime("2020-03-21 09:00", "2020-03-21 09:00"))
|
||||
.toBe('09:00');
|
||||
expect(PlanningEventManager.getFormattedEventTime("2020-03-21 09:00", "2020-03-22 17:00"))
|
||||
.toBe('09:00 - 23:59');
|
||||
expect(PlanningEventManager.getFormattedEventTime("2020-03-30 20:30", "2020-03-30 23:00"))
|
||||
.toBe('20:30 - 23:00');
|
||||
});
|
||||
|
||||
test('getDateOnlyString', () => {
|
||||
expect(PlanningEventManager.getDateOnlyString("2020-03-21 09:00")).toBe("2020-03-21");
|
||||
expect(PlanningEventManager.getDateOnlyString("2021-12-15 09:00")).toBe("2021-12-15");
|
||||
expect(PlanningEventManager.getDateOnlyString("2021-12-o5 09:00")).toBeNull();
|
||||
expect(PlanningEventManager.getDateOnlyString("2021-12-15 09:")).toBeNull();
|
||||
expect(PlanningEventManager.getDateOnlyString("2021-12-15")).toBeNull();
|
||||
expect(PlanningEventManager.getDateOnlyString("garbage")).toBeNull();
|
||||
});
|
||||
|
||||
test('isEventBefore', () => {
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 09:00", "2020-03-21 10:00")).toBeTrue();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 10:15")).toBeTrue();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:15", "2021-03-21 10:15")).toBeTrue();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-05-21 10:15")).toBeTrue();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-03-30 10:15")).toBeTrue();
|
||||
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 10:00")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:00", "2020-03-21 09:00")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-21 10:15", "2020-03-21 10:00")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2021-03-21 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-05-21 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"2020-03-30 10:15", "2020-03-21 10:15")).toBeFalse();
|
||||
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
"garbage", "2020-03-21 10:15")).toBeFalse();
|
||||
expect(PlanningEventManager.isEventBefore(
|
||||
undefined, undefined)).toBeFalse();
|
||||
});
|
||||
|
||||
test('dateToString', () => {
|
||||
let testDate = new Date();
|
||||
testDate.setFullYear(2020, 2, 21);
|
||||
testDate.setHours(9, 0, 0, 0);
|
||||
expect(PlanningEventManager.dateToString(testDate)).toBe("2020-03-21 09:00");
|
||||
testDate.setFullYear(2021, 0, 12);
|
||||
testDate.setHours(9, 10, 0, 0);
|
||||
expect(PlanningEventManager.dateToString(testDate)).toBe("2021-01-12 09:10");
|
||||
testDate.setFullYear(2022, 11, 31);
|
||||
testDate.setHours(9, 10, 15, 0);
|
||||
expect(PlanningEventManager.dateToString(testDate)).toBe("2022-12-31 09:10");
|
||||
});
|
||||
|
||||
test('generateEmptyCalendar', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() =>
|
||||
new Date('2020-01-14T00:00:00.000Z').getTime()
|
||||
);
|
||||
let calendar = PlanningEventManager.generateEmptyCalendar(1);
|
||||
expect(calendar).toHaveProperty("2020-01-14");
|
||||
expect(calendar).toHaveProperty("2020-01-20");
|
||||
expect(calendar).toHaveProperty("2020-02-10");
|
||||
expect(Object.keys(calendar).length).toBe(32);
|
||||
calendar = PlanningEventManager.generateEmptyCalendar(3);
|
||||
expect(calendar).toHaveProperty("2020-01-14");
|
||||
expect(calendar).toHaveProperty("2020-01-20");
|
||||
expect(calendar).toHaveProperty("2020-02-10");
|
||||
expect(calendar).toHaveProperty("2020-02-14");
|
||||
expect(calendar).toHaveProperty("2020-03-20");
|
||||
expect(calendar).toHaveProperty("2020-04-12");
|
||||
expect(Object.keys(calendar).length).toBe(92);
|
||||
});
|
||||
|
||||
test('pushEventInOrder', () => {
|
||||
let eventArray = [];
|
||||
let event1 = {date_begin: "2020-01-14 09:15"};
|
||||
PlanningEventManager.pushEventInOrder(eventArray, event1);
|
||||
expect(eventArray.length).toBe(1);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
|
||||
let event2 = {date_begin: "2020-01-14 10:15"};
|
||||
PlanningEventManager.pushEventInOrder(eventArray, event2);
|
||||
expect(eventArray.length).toBe(2);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
expect(eventArray[1]).toBe(event2);
|
||||
|
||||
let event3 = {date_begin: "2020-01-14 10:15", title: "garbage"};
|
||||
PlanningEventManager.pushEventInOrder(eventArray, event3);
|
||||
expect(eventArray.length).toBe(3);
|
||||
expect(eventArray[0]).toBe(event1);
|
||||
expect(eventArray[1]).toBe(event2);
|
||||
expect(eventArray[2]).toBe(event3);
|
||||
|
||||
let event4 = {date_begin: "2020-01-13 09:00"};
|
||||
PlanningEventManager.pushEventInOrder(eventArray, event4);
|
||||
expect(eventArray.length).toBe(4);
|
||||
expect(eventArray[0]).toBe(event4);
|
||||
expect(eventArray[1]).toBe(event1);
|
||||
expect(eventArray[2]).toBe(event2);
|
||||
expect(eventArray[3]).toBe(event3);
|
||||
});
|
||||
|
||||
test('generateEventAgenda', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() =>
|
||||
new Date('2020-01-14T00:00:00.000Z').getTime()
|
||||
);
|
||||
let eventList = [
|
||||
{date_begin: "2020-01-14 09:15"},
|
||||
{date_begin: "2020-02-01 09:15"},
|
||||
{date_begin: "2020-01-15 09:15"},
|
||||
{date_begin: "2020-02-01 09:30"},
|
||||
{date_begin: "2020-02-01 08:30"},
|
||||
];
|
||||
const calendar = PlanningEventManager.generateEventAgenda(eventList, 2);
|
||||
expect(calendar["2020-01-14"].length).toBe(1);
|
||||
expect(calendar["2020-01-14"][0]).toBe(eventList[0]);
|
||||
expect(calendar["2020-01-15"].length).toBe(1);
|
||||
expect(calendar["2020-01-15"][0]).toBe(eventList[2]);
|
||||
expect(calendar["2020-02-01"].length).toBe(3);
|
||||
expect(calendar["2020-02-01"][0]).toBe(eventList[4]);
|
||||
expect(calendar["2020-02-01"][1]).toBe(eventList[1]);
|
||||
expect(calendar["2020-02-01"][2]).toBe(eventList[3]);
|
||||
});
|
||||
|
||||
test('getCurrentDateString', () => {
|
||||
jest.spyOn(Date, 'now')
|
||||
.mockImplementation(() => {
|
||||
let date = new Date();
|
||||
date.setFullYear(2020, 0, 14);
|
||||
date.setHours(15, 30, 54, 65);
|
||||
return date.getTime();
|
||||
});
|
||||
expect(PlanningEventManager.getCurrentDateString()).toBe('2020-01-14 15:30');
|
||||
});
|
Loading…
Reference in a new issue