@olea-bps/components 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AppBar/index.js +83 -0
- package/AppBar/styles.js +27 -0
- package/BookDetail/index.js +268 -0
- package/BookDetail/styles.js +124 -0
- package/Component/342/200/216JobsFilter/index.js +188 -0
- package/Component/342/200/216JobsFilter/styles.js +12 -0
- package/ConnectivityWarning/index.js +65 -0
- package/ConnectivityWarning/styles.js +19 -0
- package/ContactDetail/index.js +232 -0
- package/ContactDetail/styles.js +32 -0
- package/CourseDetail/index.js +357 -0
- package/CourseDetail/styles.js +59 -0
- package/CourseDetailDialog/index.js +169 -0
- package/CourseDetailDialog/styles.js +116 -0
- package/CourseInfo/index.js +219 -0
- package/CourseInfo/styles.js +40 -0
- package/DevelopmentDialog/index.js +208 -0
- package/DevelopmentDialog/styles.js +10 -0
- package/EventCodeInput/index.js +146 -0
- package/EventCodeInput/styles.js +108 -0
- package/FlexMenuEntry/index.js +84 -0
- package/FlexMenuEntry/styles.js +27 -0
- package/MainMenuEntry/index.js +88 -0
- package/MainMenuEntry/styles.js +28 -0
- package/MealItem/index.js +87 -0
- package/MealItem/styles.js +73 -0
- package/MensaMenu/index.js +307 -0
- package/MensaMenu/styles.js +94 -0
- package/MensaSlider/index.js +184 -0
- package/MensaSlider/styles.js +53 -0
- package/Modal/index.js +106 -0
- package/Modal/styles.js +8 -0
- package/NewsDetail/index.js +377 -0
- package/NewsDetail/styles.js +77 -0
- package/NewsList/index.js +120 -0
- package/NewsList/styles.js +19 -0
- package/NewsListItem/index.js +89 -0
- package/NewsListItem/styles.js +32 -0
- package/OtherCourses/index.js +152 -0
- package/OtherCourses/styles.js +10 -0
- package/PtsDeparture/index.js +140 -0
- package/PtsDeparture/styles.js +7 -0
- package/PtsStation/index.js +183 -0
- package/PtsStation/styles.js +47 -0
- package/QuickLinks/index.js +127 -0
- package/QuickLinks/styles.js +45 -0
- package/RoomDetail/index.js +281 -0
- package/RoomDetail/styles.js +56 -0
- package/ScaledImage/index.js +92 -0
- package/SearchResults/index.js +362 -0
- package/SearchResults/styles.js +59 -0
- package/SettingSection/index.js +54 -0
- package/SettingSection/styles.js +15 -0
- package/SettingsDialog/index.js +52 -0
- package/SettingsDialog/styles.js +12 -0
- package/SettingsDialogRadio/index.js +66 -0
- package/SettingsDialogRadio/styles.js +7 -0
- package/SettingsDialogSelect/index.js +73 -0
- package/SettingsDialogSelect/styles.js +7 -0
- package/TimetableCodeInput/index.js +201 -0
- package/TimetableCodeInput/styles.js +28 -0
- package/TimetableDay/index.js +266 -0
- package/TimetableDay/styles.js +103 -0
- package/TimetableEvent/index.js +163 -0
- package/TimetableEvent/styles.js +108 -0
- package/TimetableList/index.js +116 -0
- package/TimetableList/styles.js +109 -0
- package/TimetableMonth/index.js +156 -0
- package/TimetableMonth/styles.js +29 -0
- package/TimetableWeek/index.js +245 -0
- package/TimetableWeek/styles.js +58 -0
- package/TopNews/index.js +282 -0
- package/TopNews/styles.js +125 -0
- package/TopNewsHtwk/index.js +279 -0
- package/TopNewsHtwk/styles.js +142 -0
- package/WebView/index.js +108 -0
- package/WebView/styles.js +11 -0
- package/index.js +39 -0
- package/package.json +37 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default function(theme) {
|
|
2
|
+
return {
|
|
3
|
+
container: {
|
|
4
|
+
flex: 1
|
|
5
|
+
},
|
|
6
|
+
innerContainer: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
},
|
|
9
|
+
activity: {
|
|
10
|
+
margin: 40
|
|
11
|
+
},
|
|
12
|
+
listSeperator: {
|
|
13
|
+
height: 1,
|
|
14
|
+
backgroundColor: theme.colors.listSeperator,
|
|
15
|
+
marginLeft: 20,
|
|
16
|
+
marginRight: 20
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { useMemo } from 'react';
|
|
16
|
+
import {
|
|
17
|
+
Text,
|
|
18
|
+
StyleSheet,
|
|
19
|
+
View,
|
|
20
|
+
TouchableOpacity,
|
|
21
|
+
Image,
|
|
22
|
+
} from 'react-native';
|
|
23
|
+
|
|
24
|
+
import { useTheme } from 'react-native-paper';
|
|
25
|
+
import { useTranslation } from 'react-i18next';
|
|
26
|
+
import { useNavigation } from '@react-navigation/native';
|
|
27
|
+
|
|
28
|
+
import { DateTime } from 'luxon';
|
|
29
|
+
|
|
30
|
+
import { useLanguage } from '@olea-bps/core';
|
|
31
|
+
import IconsOpenasist from '@olea-bps/icons-openasist';
|
|
32
|
+
|
|
33
|
+
import componentStyles from './styles';
|
|
34
|
+
|
|
35
|
+
export default function NewsListItem({ news }) {
|
|
36
|
+
const componentName = NewsListItem.name;
|
|
37
|
+
const language = useLanguage();
|
|
38
|
+
const { t } = useTranslation();
|
|
39
|
+
const theme = useTheme()
|
|
40
|
+
const { themeStyles, colors, fontSizes } = theme;
|
|
41
|
+
const navigation = useNavigation();
|
|
42
|
+
|
|
43
|
+
const styles = useMemo(
|
|
44
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
45
|
+
[theme, componentStyles]
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const description = news.shortDesc
|
|
49
|
+
.replace(/<(?:.|\n)*?>/gm, '')
|
|
50
|
+
.replace('Weiterlesen ›', '');
|
|
51
|
+
|
|
52
|
+
console.debug(componentName, ':', `news ${news?.guid} pub date`, ':', news.pubdate);
|
|
53
|
+
const publicationDate = news?.pubdate
|
|
54
|
+
? DateTime.fromISO(news.pubdate, { locale: language }).toLocaleString(DateTime.DATETIME_SHORT)
|
|
55
|
+
: null;
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<TouchableOpacity
|
|
59
|
+
onPress={() => navigation.navigate('NewsDetail', { news: news })}
|
|
60
|
+
accessible={true}
|
|
61
|
+
accessibilityLabel={t('accessibility:feedNewsItem', { news: [news.title, description].join('. '), date: publicationDate })}
|
|
62
|
+
accessibilityHint={t('accessibility:feedNewsItemHint')}
|
|
63
|
+
>
|
|
64
|
+
<View style={themeStyles.flexRow}>
|
|
65
|
+
<View style={[themeStyles.cardContent, styles.contentContainer]}>
|
|
66
|
+
{
|
|
67
|
+
news?.imageUrl
|
|
68
|
+
? <Image
|
|
69
|
+
source={{ uri: news.imageUrl }}
|
|
70
|
+
resizeMode="cover"
|
|
71
|
+
style={styles.image}>
|
|
72
|
+
</Image>
|
|
73
|
+
: null
|
|
74
|
+
}
|
|
75
|
+
<Text style={styles.title}>{news.title}</Text>
|
|
76
|
+
<Text style={styles.description}>{description}</Text>
|
|
77
|
+
{
|
|
78
|
+
publicationDate
|
|
79
|
+
? <View style={[themeStyles.flexRow, { alignItems: 'center', alignContent: 'center' }]}>
|
|
80
|
+
<IconsOpenasist icon={'time'} size={fontSizes.l} color={colors.iconSubtitle} />
|
|
81
|
+
<Text style={[themeStyles.cardSubTitle, styles.publicationDate]}>{publicationDate}</Text>
|
|
82
|
+
</View>
|
|
83
|
+
: null
|
|
84
|
+
}
|
|
85
|
+
</View>
|
|
86
|
+
</View>
|
|
87
|
+
</TouchableOpacity>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default function(theme) {
|
|
2
|
+
return {
|
|
3
|
+
contentContainer: {
|
|
4
|
+
paddingTop: theme.paddings.default,
|
|
5
|
+
paddingLeft: theme.paddings.default,
|
|
6
|
+
paddingRight: theme.paddings.default,
|
|
7
|
+
marginBottom: theme.paddings.default
|
|
8
|
+
},
|
|
9
|
+
publicationDate: {
|
|
10
|
+
...theme.fonts.bold,
|
|
11
|
+
marginTop: 3,
|
|
12
|
+
paddingLeft: theme.paddings.small,
|
|
13
|
+
},
|
|
14
|
+
image: {
|
|
15
|
+
aspectRatio: 16/9,
|
|
16
|
+
paddingBottom: theme.paddings.small,
|
|
17
|
+
},
|
|
18
|
+
title: {
|
|
19
|
+
...theme.fonts.bold,
|
|
20
|
+
fontSize: theme.fontSizes.subtitle,
|
|
21
|
+
lineHeight: theme.lineHeights.titleSmall,
|
|
22
|
+
marginTop: theme.paddings.default,
|
|
23
|
+
marginBottom: theme.paddings.small,
|
|
24
|
+
},
|
|
25
|
+
description: {
|
|
26
|
+
...theme.fonts.regular,
|
|
27
|
+
fontSize: theme.fontSizes.itemText,
|
|
28
|
+
lineHeight: theme.lineHeights.s,
|
|
29
|
+
marginBottom: theme.paddings.small,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import React from 'react';
|
|
16
|
+
import PropTypes from 'prop-types';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
ScrollView,
|
|
20
|
+
StyleSheet,
|
|
21
|
+
Text,
|
|
22
|
+
View,
|
|
23
|
+
SafeAreaView,
|
|
24
|
+
} from 'react-native';
|
|
25
|
+
import { Appbar, withTheme } from 'react-native-paper';
|
|
26
|
+
|
|
27
|
+
import { connect } from 'react-redux'
|
|
28
|
+
import { withTranslation } from 'react-i18next';
|
|
29
|
+
|
|
30
|
+
import merge from 'lodash/merge';
|
|
31
|
+
|
|
32
|
+
import { AppBar as AppbarComponent } from '@olea-bps/components';
|
|
33
|
+
import IconsOpenasist from '@olea-bps/icons-openasist';
|
|
34
|
+
import { TimetableList as TimetableListComponent } from '@olea-bps/components';
|
|
35
|
+
|
|
36
|
+
import componentStyles from './styles'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Course Detail Component
|
|
40
|
+
*
|
|
41
|
+
* Shows the detailed information of a course with room, time, lecturer and so on.
|
|
42
|
+
* Provides a share functionality.
|
|
43
|
+
*
|
|
44
|
+
* Parameters:
|
|
45
|
+
* - course: Course object with all information about the course
|
|
46
|
+
*
|
|
47
|
+
* Navigation-Parameters:
|
|
48
|
+
* - none
|
|
49
|
+
*/
|
|
50
|
+
class OtherCoursesComponent extends React.Component {
|
|
51
|
+
static propTypes = {
|
|
52
|
+
course: PropTypes.array
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Styles of this component
|
|
56
|
+
styles;
|
|
57
|
+
|
|
58
|
+
course = null;
|
|
59
|
+
|
|
60
|
+
constructor(props) {
|
|
61
|
+
super(props);
|
|
62
|
+
|
|
63
|
+
// ------------------------------------------------------------------------
|
|
64
|
+
// PLUGIN FUNCTIONALITY
|
|
65
|
+
// ------------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
const { pluginStyles, theme } = this.props;
|
|
68
|
+
this.styles = componentStyles(theme);
|
|
69
|
+
|
|
70
|
+
if (pluginStyles) {
|
|
71
|
+
this.styles = merge(componentStyles, pluginStyles);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.styles = StyleSheet.create(this.styles);
|
|
75
|
+
|
|
76
|
+
// ------------------------------------------------------------------------
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
_renderList = () => {
|
|
80
|
+
var renderList = this.course?.map((course, courseIndex) =>
|
|
81
|
+
<TimetableListComponent
|
|
82
|
+
{...this.props}
|
|
83
|
+
key={'course_' + courseIndex}
|
|
84
|
+
course={course}
|
|
85
|
+
times={null} />
|
|
86
|
+
) ?? [];
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<View style={this.styles.renderList}>
|
|
90
|
+
{renderList}
|
|
91
|
+
</View>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
_renderContent = () => {
|
|
96
|
+
const { themeStyles } = this.props.theme;
|
|
97
|
+
return (
|
|
98
|
+
<View style={themeStyles.container}>
|
|
99
|
+
<ScrollView>
|
|
100
|
+
{this._renderList()}
|
|
101
|
+
</ScrollView>
|
|
102
|
+
</View>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
render() {
|
|
107
|
+
// ------------------------------------------------------------------------
|
|
108
|
+
// PLUGIN FUNCTIONALITY
|
|
109
|
+
// ------------------------------------------------------------------------
|
|
110
|
+
const PluginComponent = this.props.pluginComponent;
|
|
111
|
+
if (PluginComponent) {
|
|
112
|
+
return <PluginComponent />;
|
|
113
|
+
}
|
|
114
|
+
// ------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
const { themeStyles } = this.props.theme;
|
|
117
|
+
const { course, t } = this.props;
|
|
118
|
+
const { colors } = this.props.theme;
|
|
119
|
+
|
|
120
|
+
if (!course) {
|
|
121
|
+
return (
|
|
122
|
+
<SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
|
|
123
|
+
<AppbarComponent {...this.props}
|
|
124
|
+
title={t('timetable:moreEvents')}
|
|
125
|
+
leftAction={<Appbar.Action
|
|
126
|
+
icon={props => <IconsOpenasist {...props} icon={'down'} color={colors.primaryText} />}
|
|
127
|
+
onPress={() => {
|
|
128
|
+
this.props.navigation.goBack(null);
|
|
129
|
+
}} />} />
|
|
130
|
+
<Text>{t('course:couldNotLoad')}</Text>
|
|
131
|
+
</SafeAreaView>
|
|
132
|
+
);
|
|
133
|
+
} else if (!this.course) {
|
|
134
|
+
this.course = course;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
|
|
139
|
+
<AppbarComponent {...this.props}
|
|
140
|
+
title={t('timetable:moreEvents')}
|
|
141
|
+
leftAction={<Appbar.Action
|
|
142
|
+
icon={props => <IconsOpenasist {...props} icon={'down'} color={colors.primaryText} />}
|
|
143
|
+
onPress={() => {
|
|
144
|
+
this.props.navigation.goBack(null);
|
|
145
|
+
}} />} />
|
|
146
|
+
{this._renderContent()}
|
|
147
|
+
</SafeAreaView>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export default withTranslation()(withTheme(OtherCoursesComponent))
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import React from 'react';
|
|
16
|
+
import PropTypes from 'prop-types';
|
|
17
|
+
|
|
18
|
+
import { StyleSheet, Text } from 'react-native';
|
|
19
|
+
import {List, withTheme} from "react-native-paper";
|
|
20
|
+
import {withTranslation} from "react-i18next";
|
|
21
|
+
import { connect } from 'react-redux'
|
|
22
|
+
import merge from 'lodash/merge';
|
|
23
|
+
|
|
24
|
+
import componentStyles from "./styles"
|
|
25
|
+
import IconsOpenasist from "@olea-bps/icons-openasist";
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PtsDepartureComponent extends React.Component {
|
|
30
|
+
static propTypes = {
|
|
31
|
+
departure: PropTypes.object.isRequired,
|
|
32
|
+
currentTime: PropTypes.object.isRequired
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Styles of this component
|
|
36
|
+
styles;
|
|
37
|
+
|
|
38
|
+
constructor(props) {
|
|
39
|
+
super(props);
|
|
40
|
+
// ------------------------------------------------------------------------
|
|
41
|
+
// PLUGIN FUNCTIONALITY
|
|
42
|
+
// ------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
const { pluginStyles,theme } = this.props;
|
|
45
|
+
this.styles = componentStyles(theme);
|
|
46
|
+
|
|
47
|
+
if(pluginStyles) {
|
|
48
|
+
this.styles = merge(componentStyles, pluginStyles);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.styles = StyleSheet.create(this.styles);
|
|
52
|
+
// ------------------------------------------------------------------------
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Convert the timestamp to a string with the time to departure
|
|
57
|
+
*
|
|
58
|
+
* @param timestamp
|
|
59
|
+
* @returns {string}
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
_getDepartureTime(timestamp, asObject = false) {
|
|
63
|
+
let { currentTime, t } = this.props;
|
|
64
|
+
let departureTime = new Date(timestamp);
|
|
65
|
+
|
|
66
|
+
if(departureTime - currentTime <= 0 && !asObject) {
|
|
67
|
+
return <Text style={this.styles.departureExceeded}>{t('pts:isDeparted')}</Text>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let minutesToDeparture = Math.floor((departureTime - currentTime) / 1000 / 60);
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
let departureHour = departureTime.getHours() > 9 ? departureTime.getHours() : '0' + departureTime.getHours();
|
|
74
|
+
let departureMinutes = departureTime.getMinutes() > 9 ? departureTime.getMinutes() : '0' + departureTime.getMinutes();
|
|
75
|
+
|
|
76
|
+
if(asObject) {
|
|
77
|
+
return {
|
|
78
|
+
time: departureHour + ':' + departureMinutes,
|
|
79
|
+
accessibilityLabelTime: departureHour + ' ' + t('accessibility:pts:speechTime') + departureMinutes,
|
|
80
|
+
minutesUntilDeparture: minutesToDeparture,
|
|
81
|
+
isDeparted: minutesToDeparture <= 0
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return departureHour + ':' + departureMinutes +
|
|
86
|
+
((minutesToDeparture > 0) ? ' ' + t('common:time') + ' - ' : '') +
|
|
87
|
+
((minutesToDeparture > 0) ? minutesToDeparture + t('common:minutes') + ' ' : '');
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
render() {
|
|
93
|
+
// ------------------------------------------------------------------------
|
|
94
|
+
// PLUGIN FUNCTIONALITY
|
|
95
|
+
// ------------------------------------------------------------------------
|
|
96
|
+
const PluginComponent = this.props.pluginComponent;
|
|
97
|
+
if (PluginComponent) {
|
|
98
|
+
return <PluginComponent />;
|
|
99
|
+
}
|
|
100
|
+
// ------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
const { departure, t } = this.props;
|
|
103
|
+
const {colors} = this.props.theme;
|
|
104
|
+
const departureTime = this._getDepartureTime(departure.departureTime, true);
|
|
105
|
+
const departureDetails = {
|
|
106
|
+
time:departureTime.accessibilityLabelTime,
|
|
107
|
+
direction: departure.direction,
|
|
108
|
+
line: departure.number,
|
|
109
|
+
type: departure.type.toUpperCase() === 'TRAM' ? t('pts:tram') : t('pts:bus'),
|
|
110
|
+
minutes:departureTime.minutesUntilDeparture
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<List.Item
|
|
115
|
+
title={this._getDepartureTime(departure.departureTime)}
|
|
116
|
+
description={t('pts:direction') + ": " + departure.direction + "\n" + t('pts:line') + ": " + departure.number}
|
|
117
|
+
left={props => <List.Icon {...props}
|
|
118
|
+
style={{paddingTop: 4, backgroundColor: (departure.type.toUpperCase() === 'TRAM' ? colors.primary : colors.secondary)}}
|
|
119
|
+
color={(departure.type.toUpperCase() === 'TRAM' ? colors.primaryText : colors.secondaryText)}
|
|
120
|
+
icon={ props => <IconsOpenasist icon={(departure.type.toUpperCase() === 'TRAM' ? 'tram': 'bus')} size={30}/>}
|
|
121
|
+
/>}
|
|
122
|
+
accessible={true}
|
|
123
|
+
accessibilityLabel={departureTime.isDeparted ?
|
|
124
|
+
t('accessibility:pts.isDeparted', departureDetails) :
|
|
125
|
+
t('accessibility:pts.departureTime', departureDetails)}
|
|
126
|
+
accessibilityHint={departureTime.isDeparted ? '' : t('accessibility:pts.minutesUntilDeparture', departureDetails)}
|
|
127
|
+
/>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
const mapStateToProps = state => {
|
|
134
|
+
return {
|
|
135
|
+
pluginComponent: state.pluginReducer.ptsDeparture.component,
|
|
136
|
+
pluginStyles: state.pluginReducer.ptsDeparture.styles
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export default connect(mapStateToProps, null)(withTranslation()(withTheme(PtsDepartureComponent)))
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
* you may not use this file except in compliance with the License.
|
|
4
|
+
* You may obtain a copy of the License at
|
|
5
|
+
*
|
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
*
|
|
8
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
* See the License for the specific language governing permissions and
|
|
12
|
+
* limitations under the License.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import React from 'react';
|
|
16
|
+
import PropTypes from 'prop-types';
|
|
17
|
+
|
|
18
|
+
import {StyleSheet, TouchableOpacity} from 'react-native';
|
|
19
|
+
import {Card, IconButton, withTheme} from "react-native-paper";
|
|
20
|
+
import {withTranslation} from "react-i18next";
|
|
21
|
+
import {connect} from 'react-redux'
|
|
22
|
+
import concat from "lodash/concat";
|
|
23
|
+
import merge from 'lodash/merge';
|
|
24
|
+
|
|
25
|
+
import {onSettingPtsStationOverride, store} from "@olea-bps/core";
|
|
26
|
+
import { PtsDeparture as PtsDepartureComponent } from '@olea-bps/components';
|
|
27
|
+
import IconsOpenasist from "@olea-bps/icons-openasist";
|
|
28
|
+
|
|
29
|
+
import componentStyles from "./styles"
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* PTS Station Component
|
|
33
|
+
*
|
|
34
|
+
* Shows a single station with a list of its departure times and directions
|
|
35
|
+
*
|
|
36
|
+
* Parameters:
|
|
37
|
+
* - station: Station object with all information about it
|
|
38
|
+
* - currentTime: Date object of the current time (to prevent different times across all components)
|
|
39
|
+
*
|
|
40
|
+
* Navigation-Parameters:
|
|
41
|
+
* - none
|
|
42
|
+
*/
|
|
43
|
+
class PtsStationComponent extends React.Component {
|
|
44
|
+
static propTypes = {
|
|
45
|
+
station: PropTypes.object.isRequired,
|
|
46
|
+
currentTime: PropTypes.object.isRequired
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Styles of this component
|
|
50
|
+
styles;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
constructor(props) {
|
|
55
|
+
super(props);
|
|
56
|
+
this.state = {
|
|
57
|
+
inProgress: true
|
|
58
|
+
};
|
|
59
|
+
// ------------------------------------------------------------------------
|
|
60
|
+
// PLUGIN FUNCTIONALITY
|
|
61
|
+
// ------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
const { pluginStyles,theme } = this.props;
|
|
64
|
+
this.styles = componentStyles(theme);
|
|
65
|
+
|
|
66
|
+
if(pluginStyles) {
|
|
67
|
+
this.styles = merge(componentStyles, pluginStyles);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.styles = StyleSheet.create(this.styles);
|
|
71
|
+
|
|
72
|
+
// ------------------------------------------------------------------------
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* update the favorite station for given station id
|
|
77
|
+
*
|
|
78
|
+
* @param selectedItemId
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
_updateFavoriteState = (selectedItemId) => {
|
|
82
|
+
const favorites = this.props.settings.favoritesPtsStation;
|
|
83
|
+
|
|
84
|
+
if (favorites && favorites.includes && favorites.includes(selectedItemId)) {
|
|
85
|
+
const newFavoriteArray = favorites.filter(function (itemId) {
|
|
86
|
+
return selectedItemId !== itemId;
|
|
87
|
+
});
|
|
88
|
+
store.dispatch(onSettingPtsStationOverride('favorites', newFavoriteArray));
|
|
89
|
+
} else {
|
|
90
|
+
store.dispatch(onSettingPtsStationOverride('favorites', concat(favorites, [selectedItemId])));
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Render each departure
|
|
96
|
+
*
|
|
97
|
+
* @param departures
|
|
98
|
+
* @returns {*}
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
101
|
+
_renderDepartures(departures) {
|
|
102
|
+
if(departures.length === 0)
|
|
103
|
+
return;
|
|
104
|
+
|
|
105
|
+
let output = [];
|
|
106
|
+
departures.forEach((departure, index) => {
|
|
107
|
+
if(departure) {
|
|
108
|
+
output.push(<PtsDepartureComponent key={index + '_' + departure.number + ' ' + departure.departureTime + ' ' + departure.direction}
|
|
109
|
+
departure={departure} currentTime={this.props.currentTime} />);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return output;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
render() {
|
|
117
|
+
// ------------------------------------------------------------------------
|
|
118
|
+
// PLUGIN FUNCTIONALITY
|
|
119
|
+
// ------------------------------------------------------------------------
|
|
120
|
+
const PluginComponent = this.props.pluginComponent;
|
|
121
|
+
if (PluginComponent) {
|
|
122
|
+
return <PluginComponent />;
|
|
123
|
+
}
|
|
124
|
+
// ------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
const { station, t, editMode } = this.props;
|
|
127
|
+
const {colors} = this.props.theme;
|
|
128
|
+
const {favoritesPtsStation} = this.props.settings;
|
|
129
|
+
|
|
130
|
+
const isFavorite = favoritesPtsStation && favoritesPtsStation.includes && favoritesPtsStation.includes(station.id);
|
|
131
|
+
const accessibilityHint = isFavorite ?
|
|
132
|
+
t('accessibility:pts.isFavorite') :
|
|
133
|
+
t('accessibility:pts.isNotFavorite');
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<Card>
|
|
137
|
+
<Card.Title title={station.name}
|
|
138
|
+
subtitle={t('pts:distance') + ": " + (Math.round(station.distance * 100) / 100) + ' ' + t('pts:meter')}
|
|
139
|
+
right={(props) =>
|
|
140
|
+
editMode ?
|
|
141
|
+
<TouchableOpacity
|
|
142
|
+
style={this.styles.starIcon}
|
|
143
|
+
onPress={() => {this._updateFavoriteState(station.id); setTimeout(() => {this.props.refresh()}, 200);}}
|
|
144
|
+
accessibilityLabel={station.name}
|
|
145
|
+
accessibilityHint={editMode ? accessibilityHint : ''}
|
|
146
|
+
accessibilityRole={'button'}
|
|
147
|
+
accessibilityState={editMode ? {selected: isFavorite} : null}
|
|
148
|
+
>
|
|
149
|
+
<IconsOpenasist
|
|
150
|
+
icon={isFavorite ? "star-selected" : "star"}
|
|
151
|
+
size={25}
|
|
152
|
+
color={colors.icon}
|
|
153
|
+
/>
|
|
154
|
+
</TouchableOpacity> :
|
|
155
|
+
<IconButton
|
|
156
|
+
{...props}
|
|
157
|
+
icon="crosshairs-gps"
|
|
158
|
+
onPress={() => {
|
|
159
|
+
if(this.props.routeButtonPressed) {
|
|
160
|
+
this.props.routeButtonPressed(station.latitude, station.longitude);
|
|
161
|
+
}
|
|
162
|
+
}}
|
|
163
|
+
accessibilityLabel={',' + t('accessibility:pts.centerLocation')}
|
|
164
|
+
/>
|
|
165
|
+
}/>
|
|
166
|
+
<Card.Content>
|
|
167
|
+
{this._renderDepartures(station.departures)}
|
|
168
|
+
</Card.Content>
|
|
169
|
+
</Card>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
const mapStateToProps = state => {
|
|
176
|
+
return {
|
|
177
|
+
pluginComponent: state.pluginReducer.ptsStation.component,
|
|
178
|
+
pluginStyles: state.pluginReducer.ptsStation.styles,
|
|
179
|
+
settings: state.settingReducer
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export default connect(mapStateToProps, null)(withTranslation()(withTheme(PtsStationComponent)))
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export default function(theme) {
|
|
2
|
+
return {
|
|
3
|
+
container: {
|
|
4
|
+
flex: 1,
|
|
5
|
+
},
|
|
6
|
+
containerInner: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
paddingHorizontal: 20,
|
|
9
|
+
paddingVertical: 20
|
|
10
|
+
},
|
|
11
|
+
activity: {
|
|
12
|
+
marginTop: 20
|
|
13
|
+
},
|
|
14
|
+
badges: {
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
flexWrap: 'wrap',
|
|
17
|
+
paddingHorizontal: 10
|
|
18
|
+
},
|
|
19
|
+
badge: {
|
|
20
|
+
marginRight: 5,
|
|
21
|
+
marginBottom: 5
|
|
22
|
+
},
|
|
23
|
+
bookHeader: {
|
|
24
|
+
flex: 0,
|
|
25
|
+
flexDirection: 'row',
|
|
26
|
+
marginBottom: 20
|
|
27
|
+
},
|
|
28
|
+
bookImage: {
|
|
29
|
+
flex: 0.4,
|
|
30
|
+
maxHeight: 300
|
|
31
|
+
},
|
|
32
|
+
bookTitle: {
|
|
33
|
+
flex: 0.6,
|
|
34
|
+
paddingLeft: 15
|
|
35
|
+
},
|
|
36
|
+
bookDetails: {
|
|
37
|
+
flex: 1,
|
|
38
|
+
flexDirection: 'column'
|
|
39
|
+
},
|
|
40
|
+
holdingBranch: {
|
|
41
|
+
flexWrap: 'wrap'
|
|
42
|
+
},
|
|
43
|
+
starIcon: {
|
|
44
|
+
marginRight: theme.paddings.default
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|