@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,362 @@
|
|
|
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, Text, FlatList, View, TouchableOpacity
|
|
20
|
+
} from 'react-native';
|
|
21
|
+
import {withTheme} from "react-native-paper";
|
|
22
|
+
import {withTranslation} from "react-i18next";
|
|
23
|
+
import { connect } from 'react-redux'
|
|
24
|
+
|
|
25
|
+
import merge from 'lodash/merge';
|
|
26
|
+
import unescape from 'lodash/unescape';
|
|
27
|
+
import {store} from '@olea-bps/core';
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
import componentStyles from "./styles"
|
|
31
|
+
import IconsOpenasist from "@olea-bps/icons-openasist";
|
|
32
|
+
import { BookDetail as BookDetailComponent } from '@olea-bps/components';
|
|
33
|
+
import { ContactDetail as ContactDetailComponent } from '@olea-bps/components';
|
|
34
|
+
import { RoomDetail as RoomDetailComponent } from '@olea-bps/components';
|
|
35
|
+
import { NewsDetail as NewsDetailComponent } from '@olea-bps/components';
|
|
36
|
+
import {handleHtmlEntities} from "@olea-bps/core/helper/format.helper";
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SearchResultsComponent extends React.Component {
|
|
41
|
+
static propTypes = {
|
|
42
|
+
type: PropTypes.string.isRequired
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Styles of this component
|
|
46
|
+
styles;
|
|
47
|
+
|
|
48
|
+
resultTypes = {
|
|
49
|
+
all: 'all',
|
|
50
|
+
books: 'books',
|
|
51
|
+
contacts: 'contacts',
|
|
52
|
+
rooms: 'rooms',
|
|
53
|
+
news: 'news',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
constructor(props) {
|
|
58
|
+
super(props);
|
|
59
|
+
this.state = {
|
|
60
|
+
inProgress: true
|
|
61
|
+
};
|
|
62
|
+
// ------------------------------------------------------------------------
|
|
63
|
+
// PLUGIN FUNCTIONALITY
|
|
64
|
+
// ------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
const { pluginStyles,theme } = this.props;
|
|
67
|
+
this.styles = componentStyles(theme);
|
|
68
|
+
|
|
69
|
+
if(pluginStyles) {
|
|
70
|
+
this.styles = merge(componentStyles, pluginStyles);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.styles = StyleSheet.create(this.styles);
|
|
74
|
+
|
|
75
|
+
// ------------------------------------------------------------------------
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* User pressed a card
|
|
80
|
+
*
|
|
81
|
+
* @param type
|
|
82
|
+
* @param item
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
_onCardPress = (type, item) => {
|
|
86
|
+
let content = null;
|
|
87
|
+
|
|
88
|
+
// Never provide props directly if you are using translations in this or a parent component
|
|
89
|
+
const props = {navigation: {...this.props.navigation}};
|
|
90
|
+
switch (type) {
|
|
91
|
+
case 'books':
|
|
92
|
+
content = (<BookDetailComponent {...props} book={item}/>);
|
|
93
|
+
break;
|
|
94
|
+
case 'contacts':
|
|
95
|
+
content = (<ContactDetailComponent {...props} contact={item}/>);
|
|
96
|
+
break;
|
|
97
|
+
case 'rooms':
|
|
98
|
+
content = (<RoomDetailComponent {...props} room={item}/>);
|
|
99
|
+
break;
|
|
100
|
+
case 'news':
|
|
101
|
+
content = (<NewsDetailComponent {...props} news={item}/>);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
store.dispatch({
|
|
106
|
+
type: 'UPDATE_MODAL_CONTENT',
|
|
107
|
+
modalContent: (
|
|
108
|
+
<View style={this.styles.modalContainer}>
|
|
109
|
+
{content}
|
|
110
|
+
</View>
|
|
111
|
+
)
|
|
112
|
+
});
|
|
113
|
+
this.props.navigation.navigate('Modal');
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Render a card for a result item
|
|
118
|
+
*
|
|
119
|
+
* @param item
|
|
120
|
+
* @returns {*}
|
|
121
|
+
* @private
|
|
122
|
+
*/
|
|
123
|
+
_renderResult = ({item, index}) => {
|
|
124
|
+
const {colors, themeStyles} = this.props.theme;
|
|
125
|
+
const { t } = this.props;
|
|
126
|
+
|
|
127
|
+
let borderColor = colors.messages.iconDefault;
|
|
128
|
+
let icon = 'book';
|
|
129
|
+
let key = 0;
|
|
130
|
+
let title = '';
|
|
131
|
+
let subtitle = '';
|
|
132
|
+
let type = this.resultTypes.books;
|
|
133
|
+
|
|
134
|
+
if(!item) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Books
|
|
139
|
+
if(item.bookId) {
|
|
140
|
+
borderColor = (item.available) ? colors.messages.successBackground : colors.messages.errorBackground;
|
|
141
|
+
icon = 'book';
|
|
142
|
+
key = item.bookId;
|
|
143
|
+
title = unescape(item.title);
|
|
144
|
+
subtitle = `${item.format || ''}${item.format && item.available ? ' | ' : ''}${item.available ? t('books:available') : t('books:notAvailable')}`;
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
// Contacts
|
|
148
|
+
} else if(item.firstName && item.lastName) {
|
|
149
|
+
borderColor = colors.messages.iconDefault;
|
|
150
|
+
icon = 'profile';
|
|
151
|
+
key = `${item.firstName} ${item.lastName}_${index}`;
|
|
152
|
+
title = unescape(`${item.firstName} ${item.lastName}`);
|
|
153
|
+
subtitle = item.department;
|
|
154
|
+
type = this.resultTypes.contacts
|
|
155
|
+
|
|
156
|
+
// Rooms
|
|
157
|
+
} else if(item.code2017) {
|
|
158
|
+
borderColor = colors.primary;
|
|
159
|
+
icon = 'map-search';
|
|
160
|
+
key = item.code2017;
|
|
161
|
+
//title = unescape(item.code2017);
|
|
162
|
+
title = unescape(item.title);
|
|
163
|
+
subtitle = unescape(`${item.building.postaladdress} ${item.building.name}`);
|
|
164
|
+
type = this.resultTypes.rooms
|
|
165
|
+
|
|
166
|
+
} else if(item.building && item.building.code) {
|
|
167
|
+
borderColor = colors.primary;
|
|
168
|
+
icon = 'map-search';
|
|
169
|
+
key = item.building.code
|
|
170
|
+
title = unescape(item.title);
|
|
171
|
+
subtitle = unescape(`${item.building.postaladdress} ${item.building.name} (Gebäude: ${item.building.code})`);
|
|
172
|
+
type = this.resultTypes.rooms
|
|
173
|
+
|
|
174
|
+
// News
|
|
175
|
+
} else if(item.author) {
|
|
176
|
+
borderColor = colors.black;
|
|
177
|
+
icon = 'news';
|
|
178
|
+
key = item.title;
|
|
179
|
+
title = unescape(item.title);
|
|
180
|
+
subtitle = unescape(item.pubdate);
|
|
181
|
+
type = this.resultTypes.news
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<TouchableOpacity key={key}
|
|
186
|
+
style={[themeStyles.card, {borderLeftWidth: 5, borderLeftColor: borderColor}]}
|
|
187
|
+
onPress={() => this._onCardPress(type, item)}
|
|
188
|
+
>
|
|
189
|
+
<View style={themeStyles.cardLeftIcon}>
|
|
190
|
+
<IconsOpenasist icon={icon} size={35} color={colors.messages.iconDefault} />
|
|
191
|
+
</View>
|
|
192
|
+
<View style={themeStyles.cardContent}>
|
|
193
|
+
<Text style={themeStyles.cardTitle}>{this._getShortTitle(title)}</Text>
|
|
194
|
+
<Text style={themeStyles.cardSubTitle}>{subtitle}</Text>
|
|
195
|
+
</View>
|
|
196
|
+
<View style={themeStyles.cardRightIcon}>
|
|
197
|
+
<IconsOpenasist icon={"forward"} size={25} color={colors.icon} />
|
|
198
|
+
</View>
|
|
199
|
+
</TouchableOpacity>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
_keyExtractor = (item, index) => {
|
|
204
|
+
if(!item) {
|
|
205
|
+
return 'key_' + index;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return ((item.bookId) ? item.bookId : ((item.email) ? item.email + '_' + index : 'key_' + index));
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Prevent titles with more than 3 lines
|
|
214
|
+
*
|
|
215
|
+
* @param title
|
|
216
|
+
* @returns {string|*}
|
|
217
|
+
* @private
|
|
218
|
+
*/
|
|
219
|
+
_getShortTitle = (title) => {
|
|
220
|
+
|
|
221
|
+
// Handle html entities
|
|
222
|
+
title = handleHtmlEntities(title);
|
|
223
|
+
title = title.replace(/<(?:.|\n)*?>/gm, '');
|
|
224
|
+
if(title.length > 60) {
|
|
225
|
+
return title.slice(0, 55) + ' ... ';
|
|
226
|
+
} else {
|
|
227
|
+
return title;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
render() {
|
|
232
|
+
// ------------------------------------------------------------------------
|
|
233
|
+
// PLUGIN FUNCTIONALITY
|
|
234
|
+
// ------------------------------------------------------------------------
|
|
235
|
+
const PluginComponent = this.props.pluginComponent;
|
|
236
|
+
if (PluginComponent) {
|
|
237
|
+
return <PluginComponent />;
|
|
238
|
+
}
|
|
239
|
+
// ------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
const { type, t } = this.props;
|
|
242
|
+
const {paddings, colors} = this.props.theme;
|
|
243
|
+
let output = [];
|
|
244
|
+
let results = [];
|
|
245
|
+
|
|
246
|
+
// Append books
|
|
247
|
+
if(type === this.resultTypes.all || type === this.resultTypes.books) {
|
|
248
|
+
if(results && results.length > 0) {
|
|
249
|
+
results = results.concat(this.props.searchResults.books);
|
|
250
|
+
} else {
|
|
251
|
+
results = this.props.searchResults.books;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Append contacts
|
|
256
|
+
if(type === this.resultTypes.all || type === this.resultTypes.contacts) {
|
|
257
|
+
if(results && results.length > 0) {
|
|
258
|
+
results = results.concat(this.props.searchResults.contacts);
|
|
259
|
+
} else {
|
|
260
|
+
results = this.props.searchResults.contacts;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Append rooms
|
|
265
|
+
if(type === this.resultTypes.all || type === this.resultTypes.rooms) {
|
|
266
|
+
if(results && results.length > 0) {
|
|
267
|
+
results = results.concat(this.props.searchResults.rooms);
|
|
268
|
+
} else {
|
|
269
|
+
results = this.props.searchResults.rooms;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
// Append news
|
|
275
|
+
if(type === this.resultTypes.all || type === this.resultTypes.news) {
|
|
276
|
+
if(results && results.length > 0) {
|
|
277
|
+
results = results.concat(this.props.searchResults.news);
|
|
278
|
+
} else {
|
|
279
|
+
results = this.props.searchResults.news;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
// Sorting results
|
|
285
|
+
if (results && results.length > 0) {
|
|
286
|
+
results.sort((itemA, itemB) => {
|
|
287
|
+
let itemAContainsSearchString = false;
|
|
288
|
+
let itemBContainsSearchString = false;
|
|
289
|
+
if (itemA && (
|
|
290
|
+
itemA.bookId && itemA.title.includes(this.props.searchString) ||
|
|
291
|
+
itemA.firstName && (
|
|
292
|
+
unescape(itemA.title).includes(this.props.searchString) ||
|
|
293
|
+
unescape(itemA.firstName + ' ' + itemA.lastName).includes(this.props.searchString) ||
|
|
294
|
+
itemA.department.includes(this.props.searchString)
|
|
295
|
+
) ||
|
|
296
|
+
itemA.code2017 &&
|
|
297
|
+
(
|
|
298
|
+
unescape(itemA.code2017 + ' - ' + itemA.building.name).includes(this.props.searchString) ||
|
|
299
|
+
(itemA.codeDez1 + ' ' + itemA.codeURZ).includes(this.props.searchString)
|
|
300
|
+
)
|
|
301
|
+
)) {
|
|
302
|
+
itemAContainsSearchString = true;
|
|
303
|
+
}
|
|
304
|
+
if (itemB && (
|
|
305
|
+
itemB.bookId && itemB.title.includes(this.props.searchString) ||
|
|
306
|
+
itemB.firstName && (
|
|
307
|
+
unescape(itemB.title).includes(this.props.searchString) ||
|
|
308
|
+
unescape(itemB.firstName + ' ' + itemB.lastName).includes(this.props.searchString) ||
|
|
309
|
+
itemB.department.includes(this.props.searchString)
|
|
310
|
+
) ||
|
|
311
|
+
itemB.code2017 &&
|
|
312
|
+
(
|
|
313
|
+
unescape(itemB.code2017 + ' - ' + itemB.building.name).includes(this.props.searchString) ||
|
|
314
|
+
(itemB.codeDez1 + ' ' + itemB.codeURZ).includes(this.props.searchString)
|
|
315
|
+
)
|
|
316
|
+
)) {
|
|
317
|
+
itemBContainsSearchString = true;
|
|
318
|
+
}
|
|
319
|
+
return itemBContainsSearchString - itemAContainsSearchString;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
//No search results
|
|
324
|
+
if((type === this.resultTypes.all && (results === 0 || results === null)) ||
|
|
325
|
+
(type === this.resultTypes.books && (this.props.searchResults.books === null || this.props.searchResults.books.length === 0)) ||
|
|
326
|
+
(type === this.resultTypes.contacts &&(this.props.searchResults.contacts === null || this.props.searchResults.contacts.length === 0)) ||
|
|
327
|
+
(type === this.resultTypes.rooms &&(this.props.searchResults.rooms === null || this.props.searchResults.rooms.length === 0))) {
|
|
328
|
+
return (
|
|
329
|
+
<View style={[this.styles.containerInner, this.styles.containerErrorMsg]}>
|
|
330
|
+
<IconsOpenasist icon={"search"} size={48} color={colors.primary}/>
|
|
331
|
+
<Text style={this.styles.title}>{t('search:noResultsTitle')}</Text>
|
|
332
|
+
<Text style={this.styles.subtitle}>{t('search:noResultsSubtitle')}</Text>
|
|
333
|
+
</View>
|
|
334
|
+
);
|
|
335
|
+
} else {
|
|
336
|
+
return (
|
|
337
|
+
<FlatList
|
|
338
|
+
data={results}
|
|
339
|
+
extraData={this.state}
|
|
340
|
+
keyExtractor={this._keyExtractor}
|
|
341
|
+
renderItem={this._renderResult}
|
|
342
|
+
initialNumToRender={8}
|
|
343
|
+
getItemLayout={(data, index) => (
|
|
344
|
+
{length: 50, offset: 50 * index, index}
|
|
345
|
+
)}
|
|
346
|
+
contentContainerStyle={{paddingBottom: paddings.default}}
|
|
347
|
+
/>
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const mapStateToProps = state => {
|
|
354
|
+
return {
|
|
355
|
+
pluginComponent: state.pluginReducer.searchResults.component,
|
|
356
|
+
pluginStyles: state.pluginReducer.searchResults.styles,
|
|
357
|
+
searchResults: state.stateReducer.searchResults,
|
|
358
|
+
searchString: state.stateReducer.searchTopic
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export default connect(mapStateToProps, null)(withTranslation()(withTheme(SearchResultsComponent)))
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export default function(theme) {
|
|
2
|
+
return {
|
|
3
|
+
container: {
|
|
4
|
+
flex: 1
|
|
5
|
+
},
|
|
6
|
+
tabs: {
|
|
7
|
+
backgroundColor: theme.colors.primary
|
|
8
|
+
},
|
|
9
|
+
tab: {
|
|
10
|
+
...theme.fonts.medium
|
|
11
|
+
},
|
|
12
|
+
tabIndicator: {
|
|
13
|
+
backgroundColor: theme.colors.tabs.tabIndicator,
|
|
14
|
+
height: 5
|
|
15
|
+
},
|
|
16
|
+
searchBar: {
|
|
17
|
+
borderRadius: 0,
|
|
18
|
+
height: 55
|
|
19
|
+
},
|
|
20
|
+
resultsContainer: {
|
|
21
|
+
|
|
22
|
+
},
|
|
23
|
+
activity: {
|
|
24
|
+
marginTop: theme.paddings.default
|
|
25
|
+
},
|
|
26
|
+
modalContainer: {
|
|
27
|
+
flex: 1,
|
|
28
|
+
//paddingTop: 50
|
|
29
|
+
},
|
|
30
|
+
modalContainerInner: {
|
|
31
|
+
flex: 1,
|
|
32
|
+
paddingHorizontal: 20,
|
|
33
|
+
paddingVertical: 20
|
|
34
|
+
},
|
|
35
|
+
containerErrorMsg: {
|
|
36
|
+
flex: 1,
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
alignContent: 'center',
|
|
39
|
+
alignItems: 'center',
|
|
40
|
+
margin: theme.paddings.default
|
|
41
|
+
},
|
|
42
|
+
title : {
|
|
43
|
+
fontSize: theme.fontSizes.title,
|
|
44
|
+
color: theme.colors.text,
|
|
45
|
+
textAlign: 'center',
|
|
46
|
+
marginTop: theme.paddings.default,
|
|
47
|
+
marginLeft: theme.paddings.default,
|
|
48
|
+
marginRight: theme.paddings.default
|
|
49
|
+
},
|
|
50
|
+
subtitle : {
|
|
51
|
+
fontSize: theme.fontSizes.subtitle,
|
|
52
|
+
color: theme.colors.subtitle,
|
|
53
|
+
textAlign: 'center',
|
|
54
|
+
marginTop: theme.paddings.default,
|
|
55
|
+
marginLeft: theme.paddings.default,
|
|
56
|
+
marginRight: theme.paddings.default
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
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 } from 'react';
|
|
16
|
+
import { StyleSheet } from 'react-native';
|
|
17
|
+
|
|
18
|
+
import { Button, List, useTheme } from 'react-native-paper';
|
|
19
|
+
import { useTranslation } from 'react-i18next';
|
|
20
|
+
|
|
21
|
+
import componentStyles from './styles';
|
|
22
|
+
|
|
23
|
+
export default function SettingSection({ title, description, onPress }) {
|
|
24
|
+
const { t } = useTranslation();
|
|
25
|
+
const theme = useTheme();
|
|
26
|
+
|
|
27
|
+
const { colors } = theme;
|
|
28
|
+
|
|
29
|
+
const styles = useMemo(
|
|
30
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
31
|
+
[theme, componentStyles]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<List.Section>
|
|
36
|
+
<List.Item
|
|
37
|
+
accessible={false}
|
|
38
|
+
title={title}
|
|
39
|
+
description={description}
|
|
40
|
+
titleNumberOfLines={2}
|
|
41
|
+
titleStyle={styles.listItemTitle}
|
|
42
|
+
descriptionStyle={styles.listItemDescription}
|
|
43
|
+
right={() => (
|
|
44
|
+
<Button
|
|
45
|
+
labelStyle={styles.buttonLabel}
|
|
46
|
+
onPress={onPress}
|
|
47
|
+
color={colors.buttonText}
|
|
48
|
+
>
|
|
49
|
+
{t("common:changeLabel")}
|
|
50
|
+
</Button>
|
|
51
|
+
)}
|
|
52
|
+
/>
|
|
53
|
+
</List.Section>);
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default function (theme) {
|
|
2
|
+
return {
|
|
3
|
+
title: {
|
|
4
|
+
fontSize: theme.fontSizes.l
|
|
5
|
+
},
|
|
6
|
+
description: {
|
|
7
|
+
fontSize: theme.fontSizes.m,
|
|
8
|
+
color: theme.colors.textLighter
|
|
9
|
+
},
|
|
10
|
+
buttonLabel: {
|
|
11
|
+
fontSize: theme.fontSizes.m,
|
|
12
|
+
color: theme.colors.text,
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
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 } from 'react';
|
|
16
|
+
import { StyleSheet } from 'react-native';
|
|
17
|
+
|
|
18
|
+
import { Button, Dialog, Portal, useTheme } from 'react-native-paper';
|
|
19
|
+
import { useTranslation } from 'react-i18next';
|
|
20
|
+
|
|
21
|
+
import componentStyles from './styles';
|
|
22
|
+
|
|
23
|
+
export default function SettingsDialog({ children, title, visible, onDismiss, onOk }) {
|
|
24
|
+
const { t } = useTranslation();
|
|
25
|
+
const theme = useTheme();
|
|
26
|
+
|
|
27
|
+
const styles = useMemo(
|
|
28
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
29
|
+
[theme, componentStyles]
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Portal>
|
|
34
|
+
<Dialog visible={visible} onDismiss={onDismiss}>
|
|
35
|
+
<Dialog.Title style={styles.title}>
|
|
36
|
+
{title}
|
|
37
|
+
</Dialog.Title>
|
|
38
|
+
<Dialog.Content>
|
|
39
|
+
{children}
|
|
40
|
+
</Dialog.Content>
|
|
41
|
+
<Dialog.Actions>
|
|
42
|
+
<Button
|
|
43
|
+
labelStyle={styles.okButton}
|
|
44
|
+
onPress={onOk}
|
|
45
|
+
>
|
|
46
|
+
{t("common:okLabel")}
|
|
47
|
+
</Button>
|
|
48
|
+
</Dialog.Actions>
|
|
49
|
+
</Dialog>
|
|
50
|
+
</Portal>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 } from 'react';
|
|
16
|
+
import { StyleSheet } from 'react-native';
|
|
17
|
+
|
|
18
|
+
import { RadioButton, useTheme } from 'react-native-paper';
|
|
19
|
+
import { useTranslation } from 'react-i18next';
|
|
20
|
+
|
|
21
|
+
import { SettingsDialog } from '@olea-bps/components';
|
|
22
|
+
|
|
23
|
+
import componentStyles from './styles';
|
|
24
|
+
|
|
25
|
+
export default function SettingsDialogRadio({ title, visible, options, selectedOption, onDismiss, onOk, onChange }) {
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
|
|
29
|
+
const styles = useMemo(
|
|
30
|
+
() => StyleSheet.create(componentStyles(theme)),
|
|
31
|
+
[theme, componentStyles]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<SettingsDialog
|
|
36
|
+
title={title}
|
|
37
|
+
visible={visible}
|
|
38
|
+
onDismiss={() => onDismiss(selectedOption)}
|
|
39
|
+
onOk={() => onOk(selectedOption)}
|
|
40
|
+
>
|
|
41
|
+
<RadioButton.Group
|
|
42
|
+
value={selectedOption}
|
|
43
|
+
onValueChange={onChange}
|
|
44
|
+
>
|
|
45
|
+
{
|
|
46
|
+
options.map(
|
|
47
|
+
option => {
|
|
48
|
+
const optionKey = option?.key;
|
|
49
|
+
const colors = theme.colors;
|
|
50
|
+
return (
|
|
51
|
+
<RadioButton.Item
|
|
52
|
+
key={optionKey}
|
|
53
|
+
value={optionKey}
|
|
54
|
+
label={t(option.label)}
|
|
55
|
+
labelStyle={styles.optionLabel}
|
|
56
|
+
color={colors.checkboxChecked}
|
|
57
|
+
mode={'android'}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
</RadioButton.Group>
|
|
64
|
+
</SettingsDialog>
|
|
65
|
+
);
|
|
66
|
+
}
|