@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,65 @@
|
|
|
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, { useMemo, useEffect, useRef } from "react";
|
|
16
|
+
import { useTranslation } from "react-i18next";
|
|
17
|
+
import { View, Text, StyleSheet, Animated } from "react-native";
|
|
18
|
+
import { useTheme } from "react-native-paper";
|
|
19
|
+
|
|
20
|
+
import { useConnectivityContext } from "@olea-bps/context-connectivity";
|
|
21
|
+
|
|
22
|
+
import componentStyles from "./styles";
|
|
23
|
+
|
|
24
|
+
function ConnectivityWarning({ children, bottomNavbarHeight }) {
|
|
25
|
+
const { isConnected } = useConnectivityContext();
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
|
|
29
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
opacity.setValue(0);
|
|
33
|
+
Animated.timing(opacity, {
|
|
34
|
+
toValue: 1,
|
|
35
|
+
duration: 1000,
|
|
36
|
+
useNativeDriver: true,
|
|
37
|
+
}).start();
|
|
38
|
+
}, [isConnected]);
|
|
39
|
+
|
|
40
|
+
const styles = useMemo(() => {
|
|
41
|
+
const baseStyles = componentStyles(theme);
|
|
42
|
+
return StyleSheet.create({
|
|
43
|
+
...baseStyles,
|
|
44
|
+
warningContainer: {
|
|
45
|
+
...baseStyles.warningContainer,
|
|
46
|
+
// -1 to avoid a small gap between the warning and the bottom navbar
|
|
47
|
+
marginBottom: bottomNavbarHeight - 1,
|
|
48
|
+
opacity: opacity,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}, [theme, bottomNavbarHeight, opacity]);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<View style={styles.container}>
|
|
55
|
+
{children}
|
|
56
|
+
{!isConnected && (
|
|
57
|
+
<Animated.View style={[styles.warningContainer]}>
|
|
58
|
+
<Text style={styles.warningText}>{t("warning:noConnection")}</Text>
|
|
59
|
+
</Animated.View>
|
|
60
|
+
)}
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default ConnectivityWarning;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default function (theme) {
|
|
2
|
+
return {
|
|
3
|
+
container: {
|
|
4
|
+
flex: 1,
|
|
5
|
+
},
|
|
6
|
+
warningContainer: {
|
|
7
|
+
position: "absolute",
|
|
8
|
+
bottom: 0,
|
|
9
|
+
width: "100%",
|
|
10
|
+
height: 30,
|
|
11
|
+
justifyContent: "center",
|
|
12
|
+
backgroundColor: theme.colors.error,
|
|
13
|
+
},
|
|
14
|
+
warningText: {
|
|
15
|
+
color: theme.colors.errorText,
|
|
16
|
+
textAlign: "center",
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
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
|
+
StyleSheet,
|
|
20
|
+
Text,
|
|
21
|
+
View,
|
|
22
|
+
SafeAreaView,
|
|
23
|
+
Share,
|
|
24
|
+
Linking,
|
|
25
|
+
TouchableOpacity,
|
|
26
|
+
Platform,
|
|
27
|
+
ScrollView
|
|
28
|
+
} from 'react-native';
|
|
29
|
+
import {Appbar, Headline, List, withTheme} from "react-native-paper";
|
|
30
|
+
|
|
31
|
+
import { connect } from 'react-redux'
|
|
32
|
+
import {withTranslation} from "react-i18next";
|
|
33
|
+
import merge from 'lodash/merge';
|
|
34
|
+
|
|
35
|
+
import componentStyles from "./styles"
|
|
36
|
+
import { AppBar as AppbarComponent } from '@olea-bps/components';
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Contact Detail Component
|
|
41
|
+
*
|
|
42
|
+
* Shows the detailed information of a contact with name and contact details.
|
|
43
|
+
* Provides a share functionality.
|
|
44
|
+
*
|
|
45
|
+
* Parameters:
|
|
46
|
+
* - contact: Contact object with all information about the contact
|
|
47
|
+
*
|
|
48
|
+
* Navigation-Parameters:
|
|
49
|
+
* - none
|
|
50
|
+
*/
|
|
51
|
+
class ContactDetailComponent extends React.Component {
|
|
52
|
+
static propTypes = {
|
|
53
|
+
contact: PropTypes.object.isRequired
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Styles of this component
|
|
57
|
+
styles;
|
|
58
|
+
|
|
59
|
+
contact = null;
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
constructor(props) {
|
|
63
|
+
super(props);
|
|
64
|
+
// ------------------------------------------------------------------------
|
|
65
|
+
// PLUGIN FUNCTIONALITY
|
|
66
|
+
// ------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
const { pluginStyles,theme } = this.props;
|
|
69
|
+
this.styles = componentStyles(theme);
|
|
70
|
+
|
|
71
|
+
if(pluginStyles) {
|
|
72
|
+
this.styles = merge(this.styles, pluginStyles);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.styles = StyleSheet.create(this.styles);
|
|
76
|
+
|
|
77
|
+
// ------------------------------------------------------------------------
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Share function for contact
|
|
82
|
+
*
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
86
|
+
async _onShare() {
|
|
87
|
+
try {
|
|
88
|
+
const { t } = this.props;
|
|
89
|
+
|
|
90
|
+
let phone = "";
|
|
91
|
+
if(this.contact.telephone.length > 0) {
|
|
92
|
+
phone += "\n"+ t('contact:phone') +": ";
|
|
93
|
+
this.contact.telephone.forEach((phoneNumber) => {
|
|
94
|
+
phone += phoneNumber.number + '\n';
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let message = t('contact:title') + ' - ' + this.contact.firstName + ' ' + this.contact.lastName +
|
|
99
|
+
((this.contact.building) ? "\n" + t('contact:building') + ": " + this.contact.building : '') +
|
|
100
|
+
((this.contact.department) ? "\n" + t('contact:department') + ": " + this.contact.department : '') +
|
|
101
|
+
((this.contact.room && this.contact.room.title) ? "\n" + t('contact:room') + ": " + this.contact.room.title : '') +
|
|
102
|
+
((this.contact.email) ? "\n" + t('contact:email') + ": " + this.contact.email : '') +
|
|
103
|
+
phone;
|
|
104
|
+
|
|
105
|
+
const result = await Share.share({
|
|
106
|
+
message: message
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (result.action === Share.sharedAction) {
|
|
110
|
+
if (result.activityType) {
|
|
111
|
+
// shared with activity type of result.activityType
|
|
112
|
+
} else {
|
|
113
|
+
// shared
|
|
114
|
+
}
|
|
115
|
+
} else if (result.action === Share.dismissedAction) {
|
|
116
|
+
// dismissed
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
alert(error.message);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Render contact details content
|
|
125
|
+
*
|
|
126
|
+
* @returns {*}
|
|
127
|
+
* @private
|
|
128
|
+
*/
|
|
129
|
+
_renderContent = () => {
|
|
130
|
+
const { contact, t } = this.props;
|
|
131
|
+
const { themeStyles } = this.props.theme;
|
|
132
|
+
|
|
133
|
+
let output = [];
|
|
134
|
+
let index = 1;
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if(contact.building)
|
|
140
|
+
output.push(<List.Item key="building" title={t('contact:building')} description={contact.building}
|
|
141
|
+
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
142
|
+
descriptionNumberOfLines={200}/>);
|
|
143
|
+
|
|
144
|
+
if(contact.department)
|
|
145
|
+
output.push(<List.Item key="department" title={t('contact:department')} description={contact.department}
|
|
146
|
+
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
147
|
+
descriptionNumberOfLines={200}/>);
|
|
148
|
+
|
|
149
|
+
if(contact.room && contact.room.title)
|
|
150
|
+
output.push(<List.Item key="room" title={t('contact:room')} description={contact.room.title}
|
|
151
|
+
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
152
|
+
descriptionNumberOfLines={200}/>);
|
|
153
|
+
|
|
154
|
+
if(contact.email)
|
|
155
|
+
output.push(<TouchableOpacity key="email" onPress={() => Linking.openURL('mailto:' + contact.email)}>
|
|
156
|
+
<List.Item title={t('contact:email')} description={contact.email}
|
|
157
|
+
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
158
|
+
right={props => <List.Icon {...props} icon="email"/>}/>
|
|
159
|
+
</TouchableOpacity>
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
if(contact.telephone.length > 0) {
|
|
163
|
+
contact.telephone.forEach((phoneNumber) => {
|
|
164
|
+
output.push(
|
|
165
|
+
<TouchableOpacity key={'phone_'+ index} onPress={() => {
|
|
166
|
+
const formattedPhoneNumber = phoneNumber.number.replace(/\s/g, '');
|
|
167
|
+
Linking.openURL('tel:' + formattedPhoneNumber).catch(error => console.error(`ContactDetailComponent - Fehler beim öffnen des Telefons ${Platform.OS}`, error));
|
|
168
|
+
}}>
|
|
169
|
+
<List.Item
|
|
170
|
+
title={t('contact:phone') + ' ' + index}
|
|
171
|
+
description={phoneNumber.number}
|
|
172
|
+
descriptionStyle={themeStyles.textLighter}
|
|
173
|
+
titleStyle={themeStyles.searchDetailTitle}
|
|
174
|
+
right={props =>
|
|
175
|
+
<List.Icon {...props}
|
|
176
|
+
icon="phone"/>}
|
|
177
|
+
/>
|
|
178
|
+
</TouchableOpacity>
|
|
179
|
+
);
|
|
180
|
+
index++;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<ScrollView style={this.styles.containerInner}>
|
|
187
|
+
<Headline style={this.styles.name}>{contact.firstName} {contact.lastName}</Headline>
|
|
188
|
+
{output}
|
|
189
|
+
<View style={this.styles.space}/>
|
|
190
|
+
</ScrollView>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
render() {
|
|
195
|
+
// ------------------------------------------------------------------------
|
|
196
|
+
// PLUGIN FUNCTIONALITY
|
|
197
|
+
// ------------------------------------------------------------------------
|
|
198
|
+
const PluginComponent = this.props.pluginComponent;
|
|
199
|
+
if (PluginComponent) {
|
|
200
|
+
return <PluginComponent />;
|
|
201
|
+
}
|
|
202
|
+
// ------------------------------------------------------------------------
|
|
203
|
+
|
|
204
|
+
const {themeStyles} = this.props.theme;
|
|
205
|
+
const { contact, t } = this.props;
|
|
206
|
+
|
|
207
|
+
if(!contact){
|
|
208
|
+
return (<Text>{t('contact:couldNotLoad')}</Text>);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
this.contact = contact;
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
|
|
215
|
+
<AppbarComponent {...this.props}
|
|
216
|
+
title={t('contact:contactInformation')}
|
|
217
|
+
rightAction={<Appbar.Action icon="share-variant" onPress={this._onShare.bind(this)}/>}/>
|
|
218
|
+
{this._renderContent()}
|
|
219
|
+
</SafeAreaView>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
const mapStateToProps = state => {
|
|
226
|
+
return {
|
|
227
|
+
pluginComponent: state.pluginReducer.contactDetail.component,
|
|
228
|
+
pluginStyles: state.pluginReducer.contactDetail.styles
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export default connect(mapStateToProps, null)(withTranslation()(withTheme(ContactDetailComponent)))
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default function(theme) {
|
|
2
|
+
return {
|
|
3
|
+
container: {
|
|
4
|
+
flex: 1,
|
|
5
|
+
},
|
|
6
|
+
containerInner: {
|
|
7
|
+
flex: 1,
|
|
8
|
+
paddingHorizontal: theme.paddings.default,
|
|
9
|
+
paddingVertical: theme.paddings.default
|
|
10
|
+
},
|
|
11
|
+
activity: {
|
|
12
|
+
marginTop: theme.paddings.default
|
|
13
|
+
},
|
|
14
|
+
badges: {
|
|
15
|
+
flexDirection: 'row',
|
|
16
|
+
flexWrap: 'wrap',
|
|
17
|
+
paddingHorizontal: theme.paddings.small
|
|
18
|
+
},
|
|
19
|
+
badge: {
|
|
20
|
+
marginRight: theme.paddings.xsmall,
|
|
21
|
+
marginBottom: theme.paddings.xsmall
|
|
22
|
+
},
|
|
23
|
+
name: {
|
|
24
|
+
paddingLeft: theme.paddings.xsmall + theme.paddings.small,
|
|
25
|
+
fontSize: theme.fontSizes.title,
|
|
26
|
+
lineHeight: theme.lineHeights.contactName
|
|
27
|
+
},
|
|
28
|
+
space: {
|
|
29
|
+
height: theme.paddings.large
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|