@plusscommunities/pluss-maintenance-app 6.0.4-auth.0 → 6.0.4

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.
Files changed (50) hide show
  1. package/dist/module/actions/JobActions.js.map +1 -1
  2. package/dist/module/actions/index.js.map +1 -1
  3. package/dist/module/actions/types.js.map +1 -1
  4. package/dist/module/apis/index.js +1 -1
  5. package/dist/module/apis/index.js.map +1 -1
  6. package/dist/module/apis/{generalActions.js → maintenanceActions.js} +22 -39
  7. package/dist/module/apis/maintenanceActions.js.map +1 -0
  8. package/dist/module/components/FilterPopupMenu.js +48 -12
  9. package/dist/module/components/FilterPopupMenu.js.map +1 -1
  10. package/dist/module/components/MaintenanceList.js +49 -15
  11. package/dist/module/components/MaintenanceList.js.map +1 -1
  12. package/dist/module/components/MaintenanceListItem.js +14 -15
  13. package/dist/module/components/MaintenanceListItem.js.map +1 -1
  14. package/dist/module/components/MaintenanceWidgetItem.js +3 -7
  15. package/dist/module/components/MaintenanceWidgetItem.js.map +1 -1
  16. package/dist/module/components/StatusSelectorPopup.js +2 -1
  17. package/dist/module/components/StatusSelectorPopup.js.map +1 -1
  18. package/dist/module/components/WidgetLarge.js.map +1 -1
  19. package/dist/module/components/WidgetSmall.js +4 -4
  20. package/dist/module/components/WidgetSmall.js.map +1 -1
  21. package/dist/module/core.config.js.map +1 -1
  22. package/dist/module/feature.config.js.map +1 -1
  23. package/dist/module/helper.js +10 -2
  24. package/dist/module/helper.js.map +1 -1
  25. package/dist/module/index.js.map +1 -1
  26. package/dist/module/reducers/JobsReducer.js.map +1 -1
  27. package/dist/module/screens/JobTypePicker.js +2 -2
  28. package/dist/module/screens/JobTypePicker.js.map +1 -1
  29. package/dist/module/screens/MaintenancePage.js +2 -2
  30. package/dist/module/screens/MaintenancePage.js.map +1 -1
  31. package/dist/module/screens/RequestDetail.js +141 -39
  32. package/dist/module/screens/RequestDetail.js.map +1 -1
  33. package/dist/module/screens/RequestNotes.js +6 -6
  34. package/dist/module/screens/RequestNotes.js.map +1 -1
  35. package/dist/module/screens/ServiceRequest.js +6 -6
  36. package/dist/module/screens/ServiceRequest.js.map +1 -1
  37. package/package.json +2 -5
  38. package/src/apis/index.js +1 -1
  39. package/src/apis/{generalActions.js → maintenanceActions.js} +19 -38
  40. package/src/components/FilterPopupMenu.js +39 -7
  41. package/src/components/MaintenanceList.js +56 -16
  42. package/src/components/MaintenanceListItem.js +12 -8
  43. package/src/components/MaintenanceWidgetItem.js +1 -1
  44. package/src/components/StatusSelectorPopup.js +2 -1
  45. package/src/components/WidgetSmall.js +2 -2
  46. package/src/helper.js +11 -2
  47. package/src/screens/RequestDetail.js +131 -14
  48. package/src/screens/RequestNotes.js +4 -4
  49. package/src/screens/ServiceRequest.js +4 -4
  50. package/dist/module/apis/generalActions.js.map +0 -1
@@ -1,10 +1,12 @@
1
1
  import React, { Component } from 'react';
2
- import { View, Text, TouchableOpacity, Modal } from 'react-native';
2
+ import { View, Text, TouchableOpacity, Modal, ScrollView, Dimensions } from 'react-native';
3
3
  import { connect } from 'react-redux';
4
4
  import _ from 'lodash';
5
- import { generalActions } from '../apis';
5
+ import { maintenanceActions } from '../apis';
6
6
  import { Colours, Helper } from '../core.config';
7
7
 
8
+ const SCREEN_HEIGHT = Dimensions.get('window').height;
9
+
8
10
  class FilterPopupMenu extends Component {
9
11
  constructor(props) {
10
12
  super(props);
@@ -13,6 +15,8 @@ class FilterPopupMenu extends Component {
13
15
  types: props.types || [],
14
16
  selectedStatus: props.status || '',
15
17
  selectedType: props.type || '',
18
+ selectedAssignee: props.assignee || '',
19
+ assignees: [],
16
20
  };
17
21
  this.statusOptions = [
18
22
  {
@@ -24,7 +28,7 @@ class FilterPopupMenu extends Component {
24
28
  value: 'Unassigned|In Progress',
25
29
  },
26
30
  {
27
- label: 'Unassigned',
31
+ label: 'Open',
28
32
  value: 'Unassigned',
29
33
  },
30
34
  {
@@ -39,6 +43,7 @@ class FilterPopupMenu extends Component {
39
43
  }
40
44
 
41
45
  componentDidMount() {
46
+ this.getAssignees();
42
47
  if (_.isEmpty(this.state.types)) this.refreshTypes();
43
48
  }
44
49
 
@@ -48,8 +53,30 @@ class FilterPopupMenu extends Component {
48
53
  }
49
54
  }
50
55
 
56
+ getAssignees = async () => {
57
+ try {
58
+ const res = await maintenanceActions.getAssignees(this.props.site);
59
+ let assignees = res.data.Users.map(t => {
60
+ return { label: t.displayName, value: t.id };
61
+ });
62
+ assignees = _.orderBy(assignees, 'label');
63
+
64
+ assignees.splice(0, 0, { label: 'All', value: '' });
65
+
66
+ const newState = { assignees };
67
+
68
+ if (!assignees.some(a => a.value === this.state.selectedAssignee)) {
69
+ newState.selectedAssignee = '';
70
+ }
71
+ // console.log('refreshassignees', assignees);
72
+ this.setState(newState);
73
+ } catch (error) {
74
+ console.error('getAssignees', error);
75
+ }
76
+ };
77
+
51
78
  refreshTypes = async () => {
52
- const { data } = await generalActions.getJobTypes(Helper.getSite(this.props.site));
79
+ const { data } = await maintenanceActions.getJobTypes(Helper.getSite(this.props.site));
53
80
  const types = data.map(t => {
54
81
  return { label: t.typeName, value: t.typeName };
55
82
  });
@@ -66,11 +93,14 @@ class FilterPopupMenu extends Component {
66
93
 
67
94
  onDone = () => {
68
95
  const { onClose } = this.props;
69
- const { selectedStatus, selectedType } = this.state;
96
+ const { selectedStatus, selectedType, selectedAssignee } = this.state;
70
97
  if (onClose)
71
98
  onClose({
72
99
  status: selectedStatus,
100
+ statusText: this.statusOptions.find(o => o.value === selectedStatus)?.label,
73
101
  type: selectedType,
102
+ assignee: selectedAssignee,
103
+ assigneeName: this.state.assignees.find(a => a.value === selectedAssignee)?.label,
74
104
  });
75
105
  };
76
106
 
@@ -123,10 +153,11 @@ class FilterPopupMenu extends Component {
123
153
  <View style={styles.container}>
124
154
  <View style={styles.menu}>
125
155
  {this.renderTitle()}
126
- <View style={styles.optionContent}>
156
+ <ScrollView style={styles.optionContent}>
127
157
  {this.renderOptions('Status', this.statusOptions, 'selectedStatus')}
128
158
  {this.renderOptions('Type', this.state.types, 'selectedType')}
129
- </View>
159
+ {this.renderOptions('Assigned To', this.state.assignees, 'selectedAssignee')}
160
+ </ScrollView>
130
161
  {this.renderCancel()}
131
162
  </View>
132
163
  </View>
@@ -153,6 +184,7 @@ const styles = {
153
184
  backgroundColor: '#fff',
154
185
  borderTopLeftRadius: 12,
155
186
  borderTopRightRadius: 12,
187
+ maxHeight: SCREEN_HEIGHT * 0.8,
156
188
  },
157
189
  cancelContainer: {
158
190
  paddingVertical: 16,
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2
2
  import { View, StyleSheet, FlatList, TouchableOpacity, Text } from 'react-native';
3
3
  import _ from 'lodash';
4
4
  import { connect } from 'react-redux';
5
- import { generalActions } from '../apis';
5
+ import { maintenanceActions } from '../apis';
6
6
  import { jobsLoaded, jobAdded, jobsAdded } from '../actions';
7
7
  import MaintenanceListItem from '../components/MaintenanceListItem';
8
8
  import FilterPopupMenu from './FilterPopupMenu';
@@ -13,6 +13,7 @@ class MaintenanceList extends Component {
13
13
  super(props);
14
14
 
15
15
  this.initialStatus = props.hasPermission ? 'Unassigned|In Progress' : '';
16
+ this.initialStatusText = props.hasPermission ? 'Incomplete' : '';
16
17
 
17
18
  this.state = {
18
19
  types: [],
@@ -21,7 +22,10 @@ class MaintenanceList extends Component {
21
22
  searchText: '',
22
23
  showFilterPopup: false,
23
24
  selectedStatus: this.initialStatus,
25
+ selectedStatusText: this.initialStatusText,
24
26
  selectedType: '',
27
+ selectedAssignee: '',
28
+ selectedAssigneeName: '',
25
29
  };
26
30
  }
27
31
 
@@ -42,7 +46,7 @@ class MaintenanceList extends Component {
42
46
  try {
43
47
  const { selectedStatus, selectedType } = this.state;
44
48
  // console.log('filters', { selectedStatus, selectedType });
45
- const res = await generalActions.getJobsRecursive(this.props.site, selectedStatus, selectedType);
49
+ const res = await maintenanceActions.getJobsRecursive(this.props.site, selectedStatus, selectedType);
46
50
  // console.log('refresh', res?.data);
47
51
  if (selectedStatus !== this.initialStatus || !_.isEmpty(selectedType)) {
48
52
  this.props.jobsAdded(res);
@@ -58,7 +62,7 @@ class MaintenanceList extends Component {
58
62
  };
59
63
 
60
64
  refreshTypes = async () => {
61
- const { data } = await generalActions.getJobTypes(Helper.getSite(this.props.site));
65
+ const { data } = await maintenanceActions.getJobTypes(Helper.getSite(this.props.site));
62
66
  const types = data.map(t => {
63
67
  return { label: t.typeName, value: t.typeName };
64
68
  });
@@ -72,7 +76,7 @@ class MaintenanceList extends Component {
72
76
 
73
77
  this.onLoadingChanged(true, async () => {
74
78
  try {
75
- const job = await generalActions.getJobByJobId(this.props.site, jobId);
79
+ const job = await maintenanceActions.getJobByJobId(this.props.site, jobId);
76
80
  // console.log('fetchJob', job?.data);
77
81
  this.props.jobAdded(job.data);
78
82
  } catch (error) {
@@ -91,7 +95,7 @@ class MaintenanceList extends Component {
91
95
  }
92
96
 
93
97
  resetDataSource = (source = '') => {
94
- const { searchText, selectedStatus, selectedType } = this.state;
98
+ const { searchText, selectedStatus, selectedType, selectedAssignee } = this.state;
95
99
  const { jobs } = this.props;
96
100
 
97
101
  let filteredList = jobs;
@@ -108,6 +112,7 @@ class MaintenanceList extends Component {
108
112
  }
109
113
  if (selectedStatus) filteredList = filteredList.filter(j => selectedStatus.includes(j.status));
110
114
  if (selectedType) filteredList = filteredList.filter(j => selectedType.includes(j.type));
115
+ if (selectedAssignee) filteredList = filteredList.filter(j => selectedAssignee.includes(j.AssigneeId));
111
116
  if (jobIdMatch) {
112
117
  const jobIndex = filteredList.indexOf(jobIdMatch);
113
118
  if (jobIndex > -1) {
@@ -142,10 +147,38 @@ class MaintenanceList extends Component {
142
147
  };
143
148
 
144
149
  onSelectFilter = selected => {
145
- this.setState({ selectedStatus: selected.status, selectedType: selected.type }, () => {
146
- this.resetDataSource();
147
- this.onToggleFilter();
148
- });
150
+ this.setState(
151
+ {
152
+ selectedStatus: selected.status,
153
+ selectedStatusText: selected.statusText,
154
+ selectedType: selected.type,
155
+ selectedAssignee: selected.assignee,
156
+ selectedAssigneeName: selected.assigneeName,
157
+ },
158
+ () => {
159
+ this.resetDataSource();
160
+ this.onToggleFilter();
161
+ },
162
+ );
163
+ };
164
+
165
+ getFilterButtonText = () => {
166
+ const { selectedStatus, selectedStatusText, selectedType, selectedAssignee, selectedAssigneeName } = this.state;
167
+ const filterTexts = [];
168
+ if (!_.isEmpty(selectedStatus)) {
169
+ filterTexts.push(selectedStatusText);
170
+ }
171
+
172
+ if (!_.isEmpty(selectedType)) {
173
+ filterTexts.push(selectedType);
174
+ }
175
+ if (!_.isEmpty(selectedAssignee)) {
176
+ filterTexts.push(selectedAssigneeName);
177
+ }
178
+ if (_.isEmpty(filterTexts)) {
179
+ return 'Filter';
180
+ }
181
+ return `Filtering by ${filterTexts.join(', ')}`;
149
182
  };
150
183
 
151
184
  renderEmptyList() {
@@ -156,7 +189,7 @@ class MaintenanceList extends Component {
156
189
  return (
157
190
  <TouchableOpacity onPress={this.onToggleFilter}>
158
191
  <View style={styles.filterButton}>
159
- <Text style={[styles.filterButtonText, { color: this.props.colourBrandingMain }]}>Filter</Text>
192
+ <Text style={[styles.filterButtonText, { color: this.props.colourBrandingMain }]}>{this.getFilterButtonText()}</Text>
160
193
  </View>
161
194
  </TouchableOpacity>
162
195
  );
@@ -185,7 +218,7 @@ class MaintenanceList extends Component {
185
218
  const { ListHeaderComponent } = this.props;
186
219
  return (
187
220
  <View>
188
- {ListHeaderComponent ? ListHeaderComponent : <View style={{ height: 32 }} />}
221
+ {ListHeaderComponent ? ListHeaderComponent : <View style={{ height: 8 }} />}
189
222
  {this.renderFilterButton()}
190
223
  {this.renderSearch()}
191
224
  </View>
@@ -210,11 +243,18 @@ class MaintenanceList extends Component {
210
243
  }
211
244
 
212
245
  renderFilterPopup() {
213
- const { showFilterPopup, types, selectedStatus, selectedType } = this.state;
246
+ const { showFilterPopup, types, selectedStatus, selectedType, selectedAssignee } = this.state;
214
247
  if (!showFilterPopup) return null;
215
248
 
216
249
  return (
217
- <FilterPopupMenu site={this.props.site} types={types} status={selectedStatus} type={selectedType} onClose={this.onSelectFilter} />
250
+ <FilterPopupMenu
251
+ site={this.props.site}
252
+ types={types}
253
+ status={selectedStatus}
254
+ assignee={selectedAssignee}
255
+ type={selectedType}
256
+ onClose={this.onSelectFilter}
257
+ />
218
258
  );
219
259
  }
220
260
 
@@ -265,9 +305,9 @@ const styles = StyleSheet.create({
265
305
  paddingHorizontal: 16,
266
306
  },
267
307
  filterButton: {
268
- position: 'absolute',
269
- right: 20,
270
- top: -32,
308
+ paddingBottom: 8,
309
+ paddingHorizontal: 16,
310
+ flexDirection: 'row-reverse',
271
311
  },
272
312
  filterButtonText: {
273
313
  fontFamily: 'sf-semibold',
@@ -63,7 +63,7 @@ class MaintenanceListItem extends Component {
63
63
  const { job } = this.props;
64
64
  const createdTime = moment(job.createdUnix);
65
65
  const createdTimeText = `${createdTime.format('ddd, D MMMM')} • ${createdTime.format('h:mma')}`;
66
- const activityTimeText = job.expectedDate ? moment(job.expectedDate).format('D MMMM') : '--';
66
+ const assigneeText = job.Assignee ? `Assigned to\n${job.Assignee.displayName}` : '';
67
67
  const { statusText, statusColor } = getJobStatusProps(job.status);
68
68
 
69
69
  return (
@@ -77,7 +77,9 @@ class MaintenanceListItem extends Component {
77
77
  {job.room ? <Text style={styles.jobLocationText}>{job.room}</Text> : null}
78
78
  <View style={styles.jobTypeSeenContainer}>
79
79
  <View style={[styles.jobTypeContainer, { backgroundColor: Colours.hexToRGBAstring(this.props.colourBrandingMain, 0.2) }]}>
80
- <Text style={[styles.jobTypeText, { color: this.props.colourBrandingMain }]}>{job.type}</Text>
80
+ <Text style={[styles.jobTypeText, { color: this.props.colourBrandingMain }]} numberOfLines={2}>
81
+ {job.type}
82
+ </Text>
81
83
  </View>
82
84
  {this.renderSeen()}
83
85
  </View>
@@ -92,14 +94,14 @@ class MaintenanceListItem extends Component {
92
94
  <Text style={styles.jobCreatedText}>{createdTimeText}</Text>
93
95
  <View style={styles.jobActivityContainer}>
94
96
  <View style={[styles.jobStatusContainer, { backgroundColor: statusColor }]}>
95
- <Icon name="wrench" type="font-awesome" iconStyle={styles.jobStatusIcon} />
97
+ {/* <Icon name="wrench" type="font-awesome" iconStyle={styles.jobStatusIcon} /> */}
96
98
  <Text style={styles.jobStatusText}>{statusText}</Text>
97
99
  </View>
98
100
  <View style={[styles.jobStatusLine, { borderColor: statusColor }]}>
99
101
  <View style={styles.jobStatusLineMask} />
100
102
  </View>
101
103
  <View style={[styles.jobStatusCircle, { backgroundColor: statusColor }]} />
102
- <Text style={styles.jobStatusDateText}>{activityTimeText}</Text>
104
+ <Text style={styles.jobStatusDateText}>{assigneeText}</Text>
103
105
  </View>
104
106
  </View>
105
107
  </View>
@@ -151,8 +153,9 @@ const styles = StyleSheet.create({
151
153
  alignItems: 'center',
152
154
  },
153
155
  jobTypeContainer: {
154
- height: 20,
155
- width: 80,
156
+ padding: 4,
157
+ minWidth: 80,
158
+ maxWidth: 140,
156
159
  borderRadius: 4,
157
160
  justifyContent: 'center',
158
161
  },
@@ -160,6 +163,7 @@ const styles = StyleSheet.create({
160
163
  fontFamily: 'sf-semibold',
161
164
  fontSize: 12,
162
165
  textAlign: 'center',
166
+ maxWidth: '100%',
163
167
  },
164
168
  jobSeenContainer: {
165
169
  flexDirection: 'row',
@@ -227,7 +231,7 @@ const styles = StyleSheet.create({
227
231
  jobStatusContainer: {
228
232
  flexDirection: 'row',
229
233
  alignItems: 'center',
230
- justifyContent: 'space-between',
234
+ justifyContent: 'center',
231
235
  width: 105,
232
236
  height: 30,
233
237
  paddingHorizontal: 8,
@@ -265,7 +269,7 @@ const styles = StyleSheet.create({
265
269
  jobStatusDateText: {
266
270
  flex: 1,
267
271
  textAlign: 'right',
268
- fontFamily: 'sf-bold',
272
+ fontFamily: 'sf-medium',
269
273
  fontSize: 14,
270
274
  color: Colours.TEXT_DARK,
271
275
  },
@@ -43,7 +43,7 @@ class MaintenanceWidgetItem extends Component {
43
43
  </View>
44
44
  <View style={styles.jobBottomSection}>
45
45
  <View style={[styles.jobStatusContainer, { backgroundColor: statusColor }]}>
46
- <Icon name="wrench" type="font-awesome" iconStyle={styles.jobStatusIcon} />
46
+ {/* <Icon name="wrench" type="font-awesome" iconStyle={styles.jobStatusIcon} /> */}
47
47
  <Text style={styles.jobStatusText}>{statusText}</Text>
48
48
  </View>
49
49
  </View>
@@ -11,6 +11,7 @@ class StatusSelectorPopup extends PureComponent {
11
11
  ? filter.map(status => {
12
12
  return {
13
13
  name: status,
14
+ label: getJobStatusLabel(status),
14
15
  color: getJobStatusColour(status),
15
16
  };
16
17
  })
@@ -32,7 +33,7 @@ class StatusSelectorPopup extends PureComponent {
32
33
  return (
33
34
  <TouchableOpacity key={status.name} onPress={() => onSelect(status.name)}>
34
35
  <View style={[styles.jobStatusContainer, { backgroundColor: status.color }]}>
35
- <Text style={styles.jobStatusText}>{status.name}</Text>
36
+ <Text style={styles.jobStatusText}>{status.label}</Text>
36
37
  </View>
37
38
  </TouchableOpacity>
38
39
  );
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
2
2
  import { Text, View, ScrollView, StyleSheet } from 'react-native';
3
3
  import { connect } from 'react-redux';
4
4
  import _ from 'lodash';
5
- import { generalActions } from '../apis';
5
+ import { maintenanceActions } from '../apis';
6
6
  import { jobsLoaded } from '../actions';
7
7
  import MaintenanceWidgetItem from './MaintenanceWidgetItem';
8
8
  import { Services } from '../feature.config';
@@ -39,7 +39,7 @@ class WidgetSmall extends Component {
39
39
  refresh = () => {
40
40
  this.onLoadingChanged(true, async () => {
41
41
  try {
42
- const res = await generalActions.getJobsRecursive(this.props.site);
42
+ const res = await maintenanceActions.getJobsRecursive(this.props.site);
43
43
  // console.log('WidgetSmall - refresh', res.data);
44
44
  this.props.jobsLoaded(res);
45
45
  } catch (error) {
package/src/helper.js CHANGED
@@ -1,16 +1,20 @@
1
+ import { label } from 'aws-amplify';
1
2
  import { Colours } from './core.config';
2
3
 
3
4
  const jobStatusOptions = [
4
5
  {
5
6
  name: 'Unassigned',
7
+ label: 'Open',
6
8
  color: Colours.LINEGREY,
7
9
  },
8
10
  {
9
11
  name: 'In Progress',
12
+ label: 'In Progress',
10
13
  color: Colours.COLOUR_TEAL,
11
14
  },
12
15
  {
13
16
  name: 'Completed',
17
+ label: 'Completed',
14
18
  color: Colours.COLOUR_GREEN_LIGHT,
15
19
  },
16
20
  ];
@@ -20,11 +24,16 @@ const getJobStatusColour = status => {
20
24
  return option ? option.color : jobStatusOptions[0].color;
21
25
  };
22
26
 
27
+ const getJobStatusLabel = status => {
28
+ const option = jobStatusOptions.find(item => item.name === status);
29
+ return option ? option.label : jobStatusOptions[0].label;
30
+ };
31
+
23
32
  const getJobStatusProps = status => {
24
- const statusText = status || jobStatusOptions[0].name;
33
+ const statusText = getJobStatusLabel(status) || jobStatusOptions[0].label;
25
34
  const statusColor = getJobStatusColour(statusText);
26
35
 
27
36
  return { statusText, statusColor };
28
37
  };
29
38
 
30
- export { jobStatusOptions, getJobStatusColour, getJobStatusProps };
39
+ export { jobStatusOptions, getJobStatusColour, getJobStatusProps, getJobStatusLabel };