@olea-bps/base 1.1.5 → 1.1.7
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.
|
@@ -12,30 +12,35 @@
|
|
|
12
12
|
* limitations under the License.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import
|
|
16
|
-
|
|
15
|
+
import {
|
|
16
|
+
useCallback,
|
|
17
|
+
useMemo
|
|
18
|
+
} from 'react';
|
|
17
19
|
|
|
18
20
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
View,
|
|
21
|
+
Linking,
|
|
22
|
+
Platform,
|
|
22
23
|
SafeAreaView,
|
|
24
|
+
ScrollView,
|
|
23
25
|
Share,
|
|
24
|
-
|
|
26
|
+
StyleSheet,
|
|
27
|
+
Text,
|
|
25
28
|
TouchableOpacity,
|
|
26
|
-
|
|
27
|
-
ScrollView
|
|
29
|
+
View,
|
|
28
30
|
} from 'react-native';
|
|
29
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
Headline,
|
|
33
|
+
List,
|
|
34
|
+
useTheme,
|
|
35
|
+
} from 'react-native-paper';
|
|
30
36
|
|
|
31
|
-
import {
|
|
32
|
-
import {withTranslation} from "react-i18next";
|
|
33
|
-
import merge from 'lodash/merge';
|
|
37
|
+
import { useTranslation } from 'react-i18next';
|
|
34
38
|
|
|
35
|
-
import componentStyles from './styles';
|
|
36
39
|
import AppbarComponent from '../AppBar';
|
|
37
40
|
import AppbarAction from '../AppbarAction';
|
|
41
|
+
import IconListItem from '../IconListItem';
|
|
38
42
|
|
|
43
|
+
import componentStyles from './styles';
|
|
39
44
|
|
|
40
45
|
/**
|
|
41
46
|
* Contact Detail Component
|
|
@@ -43,193 +48,168 @@ import AppbarAction from '../AppbarAction';
|
|
|
43
48
|
* Shows the detailed information of a contact with name and contact details.
|
|
44
49
|
* Provides a share functionality.
|
|
45
50
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* Navigation-Parameters:
|
|
50
|
-
* - none
|
|
51
|
+
* @param {object} props
|
|
52
|
+
* @param {object} props.contact - Der anzuzeigende Kontakt
|
|
51
53
|
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
54
|
+
export default function ContactDetailComponent({ contact, ...restProps }) {
|
|
55
|
+
const theme = useTheme();
|
|
56
|
+
const { themeStyles } = theme;
|
|
57
|
+
const { t } = useTranslation();
|
|
58
|
+
|
|
59
|
+
const styles = useMemo(
|
|
60
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
61
|
+
[theme, componentStyles]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const onShare = useCallback(
|
|
65
|
+
async () => {
|
|
66
|
+
try {
|
|
67
|
+
// Telephone-Objekte aus dem Kontakt auslesen. Falls diese nicht vorhanden sind, mit einem leeren Array initialisieren
|
|
68
|
+
const contactTelephones = contact?.telephone ?? [];
|
|
69
|
+
const shareMessageTelephoneNumbers = contactTelephones
|
|
70
|
+
.map(telephone => telephone.number)
|
|
71
|
+
.map(number => `${t('contact:phone')}: ${number}`)
|
|
72
|
+
.join('\n');
|
|
73
|
+
|
|
74
|
+
const shareMessage = `${t('contact:title')} - ${contact.firstName} ${contact.lastName}`
|
|
75
|
+
+
|
|
76
|
+
(
|
|
77
|
+
contact?.building
|
|
78
|
+
? `\n${t('contact:building')}: ${contact.building}`
|
|
79
|
+
: ''
|
|
80
|
+
)
|
|
81
|
+
+
|
|
82
|
+
(
|
|
83
|
+
contact?.department
|
|
84
|
+
? `\n${t('contact:department')}: ${contact.department}`
|
|
85
|
+
: ''
|
|
86
|
+
)
|
|
87
|
+
+
|
|
88
|
+
(
|
|
89
|
+
contact?.room?.title
|
|
90
|
+
? `\n${t('contact:room')}: ${contact.room.title}`
|
|
91
|
+
: ''
|
|
92
|
+
)
|
|
93
|
+
+
|
|
94
|
+
(
|
|
95
|
+
contact?.email
|
|
96
|
+
? `\n${t('contact:email')}: ${contact.email}`
|
|
97
|
+
: ''
|
|
98
|
+
)
|
|
99
|
+
+
|
|
100
|
+
(
|
|
101
|
+
shareMessageTelephoneNumbers
|
|
102
|
+
? '\n' + shareMessageTelephoneNumbers
|
|
103
|
+
: ''
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
await Share.share({
|
|
107
|
+
message: shareMessage,
|
|
96
108
|
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
alert(error.message);
|
|
97
111
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
},
|
|
113
|
+
[contact, t]
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
return contact
|
|
117
|
+
? <SafeAreaView style={[styles.container, themeStyles.safeAreaContainer]}>
|
|
118
|
+
<AppbarComponent
|
|
119
|
+
{...restProps}
|
|
120
|
+
title={t('contact:contactInformation')}
|
|
121
|
+
rightAction={<AppbarAction icon='share' onPress={onShare} />}
|
|
122
|
+
/>
|
|
123
|
+
<ScrollView style={styles.containerInner}>
|
|
124
|
+
<Headline style={styles.name}>{contact.firstName} {contact.lastName}</Headline>
|
|
125
|
+
{
|
|
126
|
+
contact?.building
|
|
127
|
+
? <List.Item
|
|
128
|
+
key="building"
|
|
129
|
+
title={t('contact:building')}
|
|
130
|
+
description={contact.building}
|
|
131
|
+
descriptionStyle={themeStyles.textLighter}
|
|
132
|
+
titleStyle={themeStyles.searchDetailTitle}
|
|
133
|
+
descriptionNumberOfLines={200} />
|
|
134
|
+
: null
|
|
115
135
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Render contact details content
|
|
126
|
-
*
|
|
127
|
-
* @returns {*}
|
|
128
|
-
* @private
|
|
129
|
-
*/
|
|
130
|
-
_renderContent = () => {
|
|
131
|
-
const { contact, t } = this.props;
|
|
132
|
-
const { themeStyles } = this.props.theme;
|
|
133
|
-
|
|
134
|
-
let output = [];
|
|
135
|
-
let index = 1;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if(contact.building)
|
|
141
|
-
output.push(<List.Item key="building" title={t('contact:building')} description={contact.building}
|
|
142
|
-
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
143
|
-
descriptionNumberOfLines={200}/>);
|
|
144
|
-
|
|
145
|
-
if(contact.department)
|
|
146
|
-
output.push(<List.Item key="department" title={t('contact:department')} description={contact.department}
|
|
147
|
-
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
148
|
-
descriptionNumberOfLines={200}/>);
|
|
149
|
-
|
|
150
|
-
if(contact.room && contact.room.title)
|
|
151
|
-
output.push(<List.Item key="room" title={t('contact:room')} description={contact.room.title}
|
|
152
|
-
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
153
|
-
descriptionNumberOfLines={200}/>);
|
|
154
|
-
|
|
155
|
-
if(contact.email)
|
|
156
|
-
output.push(<TouchableOpacity key="email" onPress={() => Linking.openURL('mailto:' + contact.email)}>
|
|
157
|
-
<List.Item title={t('contact:email')} description={contact.email}
|
|
158
|
-
descriptionStyle={themeStyles.textLighter} titleStyle={themeStyles.searchDetailTitle}
|
|
159
|
-
right={props => <List.Icon {...props} icon="email"/>}/>
|
|
160
|
-
</TouchableOpacity>
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
if(contact.telephone.length > 0) {
|
|
164
|
-
contact.telephone.forEach((phoneNumber) => {
|
|
165
|
-
output.push(
|
|
166
|
-
<TouchableOpacity key={'phone_'+ index} onPress={() => {
|
|
167
|
-
const formattedPhoneNumber = phoneNumber.number.replace(/\s/g, '');
|
|
168
|
-
Linking.openURL('tel:' + formattedPhoneNumber).catch(error => console.error(`ContactDetailComponent - Fehler beim öffnen des Telefons ${Platform.OS}`, error));
|
|
169
|
-
}}>
|
|
170
|
-
<List.Item
|
|
171
|
-
title={t('contact:phone') + ' ' + index}
|
|
172
|
-
description={phoneNumber.number}
|
|
136
|
+
{
|
|
137
|
+
contact?.department
|
|
138
|
+
? <List.Item
|
|
139
|
+
key="department"
|
|
140
|
+
title={t('contact:department')}
|
|
141
|
+
description={contact.department}
|
|
173
142
|
descriptionStyle={themeStyles.textLighter}
|
|
174
143
|
titleStyle={themeStyles.searchDetailTitle}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
{
|
|
190
|
-
|
|
144
|
+
descriptionNumberOfLines={200} />
|
|
145
|
+
: null
|
|
146
|
+
}
|
|
147
|
+
{
|
|
148
|
+
contact?.room && contact?.room?.title
|
|
149
|
+
? <List.Item
|
|
150
|
+
key="room"
|
|
151
|
+
title={t('contact:room')}
|
|
152
|
+
description={contact.room.title}
|
|
153
|
+
descriptionStyle={themeStyles.textLighter}
|
|
154
|
+
titleStyle={themeStyles.searchDetailTitle}
|
|
155
|
+
descriptionNumberOfLines={200} />
|
|
156
|
+
: null
|
|
157
|
+
}
|
|
158
|
+
{
|
|
159
|
+
contact?.email
|
|
160
|
+
? <TouchableOpacity
|
|
161
|
+
key="email"
|
|
162
|
+
onPress={() => Linking.openURL('mailto:' + contact.email)}
|
|
163
|
+
>
|
|
164
|
+
<List.Item
|
|
165
|
+
title={t('contact:email')}
|
|
166
|
+
description={contact.email}
|
|
167
|
+
descriptionStyle={themeStyles.textLighter}
|
|
168
|
+
titleStyle={themeStyles.searchDetailTitle}
|
|
169
|
+
right={props => <List.Icon {...props} icon="email" />}
|
|
170
|
+
/>
|
|
171
|
+
</TouchableOpacity>
|
|
172
|
+
: null
|
|
173
|
+
}
|
|
174
|
+
{
|
|
175
|
+
Array.isArray(contact?.telephone)
|
|
176
|
+
? contact.telephone.map(
|
|
177
|
+
(telephone, index, telephones) => {
|
|
178
|
+
|
|
179
|
+
const title = telephones.length == 1
|
|
180
|
+
? t('contact:phone')
|
|
181
|
+
: t('contact:phone') + ' ' + index;
|
|
182
|
+
|
|
183
|
+
const telephoneNumber = telephone.number
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<TouchableOpacity
|
|
187
|
+
key={telephoneNumber}
|
|
188
|
+
onPress={
|
|
189
|
+
() => {
|
|
190
|
+
const formattedPhoneNumber = telephone.number.replace(/\s/g, '');
|
|
191
|
+
Linking.openURL('tel:' + formattedPhoneNumber).catch(error => console.error(`ContactDetailComponent - Fehler beim öffnen des Telefons ${Platform.OS}`, error));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
>
|
|
195
|
+
<IconListItem
|
|
196
|
+
title={title}
|
|
197
|
+
description={telephoneNumber}
|
|
198
|
+
descriptionStyle={themeStyles.textLighter}
|
|
199
|
+
titleStyle={themeStyles.searchDetailTitle}
|
|
200
|
+
icon={'call'}
|
|
201
|
+
/>
|
|
202
|
+
</TouchableOpacity>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
: null
|
|
207
|
+
}
|
|
208
|
+
<View style={styles.space} />
|
|
191
209
|
</ScrollView>
|
|
192
|
-
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
render() {
|
|
196
|
-
// ------------------------------------------------------------------------
|
|
197
|
-
// PLUGIN FUNCTIONALITY
|
|
198
|
-
// ------------------------------------------------------------------------
|
|
199
|
-
const PluginComponent = this.props.pluginComponent;
|
|
200
|
-
if (PluginComponent) {
|
|
201
|
-
return <PluginComponent />;
|
|
202
|
-
}
|
|
203
|
-
// ------------------------------------------------------------------------
|
|
204
|
-
|
|
205
|
-
const {themeStyles} = this.props.theme;
|
|
206
|
-
const { contact, t } = this.props;
|
|
207
|
-
|
|
208
|
-
if(!contact){
|
|
209
|
-
return (<Text>{t('contact:couldNotLoad')}</Text>);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
this.contact = contact;
|
|
213
|
-
|
|
214
|
-
return (
|
|
215
|
-
<SafeAreaView style={[this.styles.container, themeStyles.safeAreaContainer]}>
|
|
216
|
-
<AppbarComponent
|
|
217
|
-
{...this.props}
|
|
218
|
-
title={t('contact:contactInformation')}
|
|
219
|
-
rightAction={<AppbarAction icon='share' onPress={this._onShare.bind(this)} />}
|
|
220
|
-
/>
|
|
221
|
-
{this._renderContent()}
|
|
222
|
-
</SafeAreaView>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const mapStateToProps = state => {
|
|
229
|
-
return {
|
|
230
|
-
pluginComponent: state.pluginReducer.contactDetail.component,
|
|
231
|
-
pluginStyles: state.pluginReducer.contactDetail.styles
|
|
232
|
-
};
|
|
233
|
-
};
|
|
210
|
+
</SafeAreaView>
|
|
234
211
|
|
|
235
|
-
|
|
212
|
+
: <Text>
|
|
213
|
+
{t('contact:couldNotLoad')}
|
|
214
|
+
</Text>;
|
|
215
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useMemo,
|
|
4
|
+
} from 'react';
|
|
5
|
+
import {
|
|
6
|
+
StyleSheet,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
List,
|
|
11
|
+
useTheme,
|
|
12
|
+
} from 'react-native-paper';
|
|
13
|
+
|
|
14
|
+
import { default as Icon } from '../../libraries/icons-openasist';
|
|
15
|
+
|
|
16
|
+
import componentStyles from './styles';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ein Listenelement, welches ein Icon auf der rechten Seite anzeigt.
|
|
20
|
+
* Es können alle Properties der {@link List.Item}-Komponente verwendet werden, außer die `right`-Property.
|
|
21
|
+
* Die `right`-Property wird für das Einbinden des Icons benutzt.
|
|
22
|
+
*
|
|
23
|
+
* @param {object} props
|
|
24
|
+
* @param {string} props.icon Iconname des anzuzeigenen Icons. Für mögliche Werte siehe {@link Icon}
|
|
25
|
+
*/
|
|
26
|
+
export default function IconListItem({ icon, ...listItemProps }) {
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
|
|
29
|
+
const styles = useMemo(
|
|
30
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
31
|
+
[theme, componentStyles]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const listItemIcon = useCallback(
|
|
35
|
+
listIconProps =>
|
|
36
|
+
<List.Icon
|
|
37
|
+
{...listIconProps}
|
|
38
|
+
icon={
|
|
39
|
+
props =>
|
|
40
|
+
<Icon
|
|
41
|
+
{...props}
|
|
42
|
+
icon={icon}
|
|
43
|
+
/>
|
|
44
|
+
}
|
|
45
|
+
/>
|
|
46
|
+
,
|
|
47
|
+
[icon]
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<List.Item
|
|
52
|
+
{...listItemProps}
|
|
53
|
+
right={listItemIcon}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|