@plusscommunities/pluss-core-web 1.0.5 → 1.0.6

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 (62) hide show
  1. package/dist/index.cjs.js +7349 -1360
  2. package/dist/index.esm.js +7341 -1358
  3. package/dist/index.umd.js +7346 -1364
  4. package/package.json +5 -3
  5. package/src/actions/AuthActions.js +83 -0
  6. package/src/actions/UsersActions.js +65 -0
  7. package/src/actions/index.js +2 -2
  8. package/src/actions/types.js +9 -9
  9. package/src/analytics.js +73 -0
  10. package/src/apis/analyticsActions.js +49 -0
  11. package/src/apis/authActions.js +58 -0
  12. package/src/apis/fileActions.js +92 -94
  13. package/src/apis/index.js +7 -0
  14. package/src/apis/profileActions.js +133 -0
  15. package/src/apis/stringActions.js +25 -0
  16. package/src/apis/typeActions.js +186 -0
  17. package/src/apis/userActions.js +128 -0
  18. package/src/apis/utilityActions.js +35 -0
  19. package/src/colours.js +16 -16
  20. package/src/components/AnalyticsFilter.js +110 -0
  21. package/src/components/AudienceIncluder.js +174 -0
  22. package/src/components/AudienceSelector.js +549 -0
  23. package/src/components/CheckBox.js +77 -0
  24. package/src/components/DatePicker.js +268 -0
  25. package/src/components/DropdownInput.js +223 -0
  26. package/src/components/FileInput.js +314 -0
  27. package/src/components/ImageInput.js +971 -0
  28. package/src/components/MakerPopup.js +300 -0
  29. package/src/components/OptionsSection.js +64 -0
  30. package/src/components/P60Icon.js +40 -0
  31. package/src/components/ProfilePic.js +35 -0
  32. package/src/components/Reactions.js +77 -0
  33. package/src/components/Tag.js +62 -0
  34. package/src/components/TextFormatPopup.js +54 -0
  35. package/src/components/TimePicker.js +205 -0
  36. package/src/components/UserListing.js +64 -0
  37. package/src/components/index.js +23 -7
  38. package/src/components/svg-icons.json +6 -0
  39. package/src/config.js +10 -0
  40. package/src/helper/HelpDeskWidget.js +52 -0
  41. package/src/helper/api/getUrl.js +15 -0
  42. package/src/helper/api/getUrlParams.js +9 -0
  43. package/src/helper/api/safeReadParams.js +6 -0
  44. package/src/helper/colours.js/getAppColourFromState.js +10 -0
  45. package/src/helper/files/canvasImageUploader.js +159 -0
  46. package/src/helper/files/get1400.js +28 -0
  47. package/src/helper/files/getExtension.js +9 -0
  48. package/src/helper/files/getFileName.js +13 -0
  49. package/src/helper/files/getThumb300.js +32 -0
  50. package/src/helper/files/isVideo.js +8 -0
  51. package/src/{helper.js → helper/helper.js} +19 -130
  52. package/src/helper/index.js +29 -0
  53. package/src/helper/site/getSiteName.js +16 -0
  54. package/src/helper/site/getSiteNameFromRoles.js +12 -0
  55. package/src/helper/storage/readJSONFromStorage.js +9 -0
  56. package/src/helper/storage/setLocalStorage.js +5 -0
  57. package/src/helper/strings/isEmail.js +11 -0
  58. package/src/helper/strings/onlyAlphanumeric.js +8 -0
  59. package/src/helper/strings/randomString.js +10 -0
  60. package/src/helper/strings/toParagraphed.js +17 -0
  61. package/src/index.js +2 -1
  62. package/src/session.js +107 -107
@@ -0,0 +1,77 @@
1
+ import React, { PureComponent } from 'react';
2
+ import FontAwesome from 'react-fontawesome';
3
+ import _ from 'lodash';
4
+
5
+ class CheckBox extends PureComponent {
6
+ generateClassNames() {
7
+ let result = 'checkBox';
8
+ if (this.props.isActive) {
9
+ result = result + ' checkBox--active';
10
+ }
11
+ if (this.props.disabled) {
12
+ result = result + ' checkBox--disabled';
13
+ }
14
+ if (this.props.noHoverHighlight) {
15
+ result = result + ' checkBox--noHoverHighlight';
16
+ }
17
+ return result;
18
+ }
19
+
20
+ getLabelClasses() {
21
+ let result = 'actionText pointer';
22
+ if (this.props.disabled) {
23
+ result = result + ' actionText--disabled';
24
+ }
25
+ return result;
26
+ }
27
+
28
+ getBoxStyle() {
29
+ const result = {};
30
+ if (this.props.highlightColour && this.props.isActive) {
31
+ result.borderColor = this.props.highlightColour;
32
+ result.backgroundColor = this.props.highlightColour;
33
+ }
34
+ return result;
35
+ }
36
+
37
+ onChange = (e) => {
38
+ if (this.props.disabled) {
39
+ return;
40
+ }
41
+ return this.props.onChange(e);
42
+ };
43
+
44
+ render() {
45
+ return (
46
+ <div className={this.props.className}>
47
+ <div className={this.props.showWarning ? 'checkBox--error' : null} style={{ ...styles.row, ...this.props.style }}>
48
+ <div className={this.generateClassNames()} onClick={this.onChange} style={this.getBoxStyle()}>
49
+ <div className="checkBoxTick">
50
+ <FontAwesome className="checkBoxTick-font" name={'check'} />
51
+ </div>
52
+ </div>
53
+ {!_.isEmpty(this.props.label) && (
54
+ <div
55
+ className={this.getLabelClasses()}
56
+ style={{ marginLeft: 8, fontSize: 14, lineHeight: '20px', ...this.props.labelStyle }}
57
+ onClick={this.onChange}
58
+ >
59
+ {this.props.label}
60
+ </div>
61
+ )}
62
+ </div>
63
+ {this.props.children}
64
+ </div>
65
+ );
66
+ }
67
+ }
68
+
69
+ const styles = {
70
+ row: {
71
+ display: 'flex',
72
+ flexDirection: 'row',
73
+ marginBottom: 8,
74
+ },
75
+ };
76
+
77
+ export { CheckBox };
@@ -0,0 +1,268 @@
1
+ import React, { Component } from 'react';
2
+ import moment from 'moment';
3
+ import _ from 'lodash';
4
+ import { P60Icon } from './';
5
+
6
+ class DatePicker extends Component {
7
+ state = {
8
+ shownMonth: new Date(),
9
+ grid: [],
10
+ };
11
+
12
+ UNSAFE_componentWillMount() {
13
+ this.onNewProps(this.props, true);
14
+ }
15
+
16
+ UNSAFE_componentWillReceiveProps(nextProps) {
17
+ this.onNewProps(nextProps);
18
+ }
19
+
20
+ onNewProps(nextProps, forceUpdate) {
21
+ if (this.props.multiple && nextProps.selectedDates !== this.props.selectedDates) {
22
+ this.generateGrid(this.state.shownMonth, nextProps.selectedDates);
23
+ } else if (forceUpdate || nextProps.selectedDate !== this.props.selectedDate) {
24
+ let dateToUse = nextProps.selectedDate;
25
+ if (!(dateToUse instanceof Date)) {
26
+ dateToUse = new Date(dateToUse);
27
+ }
28
+ if (isNaN(dateToUse)) {
29
+ dateToUse = new Date();
30
+ }
31
+ this.setState({
32
+ shownMonth: dateToUse,
33
+ selectedDate: dateToUse,
34
+ });
35
+ this.generateGrid(dateToUse, dateToUse);
36
+ }
37
+ }
38
+
39
+ getDate() {
40
+ if (!this.props.selectedDate) {
41
+ return 'Select day';
42
+ }
43
+ return moment(this.props.selectedDate).format('dddd, Do MMMM');
44
+ }
45
+
46
+ getShortDate() {
47
+ if (!this.props.selectedDate) {
48
+ return '';
49
+ }
50
+ return moment(this.props.selectedDate).format('DD/MM/YYYY');
51
+ }
52
+
53
+ getMonth() {
54
+ return moment(this.state.shownMonth).format('MMMM YYYY');
55
+ }
56
+
57
+ isDateSelected(date, selectedDate) {
58
+ if (this.props.multiple) {
59
+ return _.includes(selectedDate, date.format('DD-MM-YYYY'));
60
+ }
61
+ return date.isSame(selectedDate, 'date');
62
+ }
63
+
64
+ changeMonth(change) {
65
+ const newShownDate = new Date(this.state.shownMonth.getFullYear(), this.state.shownMonth.getMonth() + 1 + change, 0);
66
+ this.setState({
67
+ shownMonth: newShownDate,
68
+ });
69
+ this.generateGrid(newShownDate);
70
+ }
71
+
72
+ selectRange(date) {
73
+ const d1 = moment(this.state.lastSelected, 'DD-MM-YYYY');
74
+ const d2 = moment(date, 'DD-MM-YYYY');
75
+
76
+ let startDate, endDate;
77
+
78
+ if (d1.valueOf() > d2.valueOf()) {
79
+ // clicked an earlier day
80
+ startDate = moment(d2);
81
+ endDate = moment(d1);
82
+ } else {
83
+ // clicked a later day
84
+ startDate = moment(d1);
85
+ endDate = moment(d2);
86
+ }
87
+
88
+ const dateRange = [startDate.format('DD-MM-YYYY')];
89
+ while (startDate.format('DD-MM-YYYY') !== endDate.format('DD-MM-YYYY')) {
90
+ startDate.add(1, 'd');
91
+ dateRange.push(startDate.format('DD-MM-YYYY'));
92
+ }
93
+
94
+ if (
95
+ (_.includes(this.props.selectedDates, d2.format('DD-MM-YYYY')) && !_.includes(this.props.selectedDates, d1.format('DD-MM-YYYY'))) ||
96
+ !_.some(dateRange, (d) => {
97
+ return !_.includes(this.props.selectedDates, d);
98
+ })
99
+ ) {
100
+ // the first clicked date was just de-selected and then clicked on a selected date
101
+ // or every date in the range is already selected, then
102
+ // de-select the range
103
+ this.props.selectDate(
104
+ _.filter(this.props.selectedDates, (d) => {
105
+ return !_.includes(dateRange, d);
106
+ }),
107
+ );
108
+ } else {
109
+ // select the range
110
+ const newSelection = [...this.props.selectedDates, ...dateRange];
111
+ this.props.selectDate(_.uniq(newSelection));
112
+ }
113
+ }
114
+
115
+ selectDate(date, e) {
116
+ console.log('selected a date');
117
+ if (this.props.multiple) {
118
+ const dateKey = moment(date).format('DD-MM-YYYY');
119
+
120
+ if (e.shiftKey && this.state.lastSelected && this.state.lastSelected !== dateKey) {
121
+ // shift-click to select range
122
+ this.selectRange(dateKey);
123
+ } else {
124
+ // toggle single date
125
+ const index = this.props.selectedDates.indexOf(dateKey);
126
+ const newSelection = [...this.props.selectedDates];
127
+ if (index > -1) {
128
+ newSelection.splice(index, 1);
129
+ } else {
130
+ newSelection.push(dateKey);
131
+ }
132
+ this.props.selectDate(newSelection);
133
+ }
134
+ this.setState({
135
+ lastSelected: dateKey,
136
+ });
137
+ } else {
138
+ this.props.selectDate(moment(date).format('YYYY-MM-DD'));
139
+ }
140
+ }
141
+
142
+ generateGrid(date, selectedDate) {
143
+ const month = moment(date);
144
+ let dateToTarget = moment(date).endOf('month');
145
+ let dateToModify = moment(date).startOf('month');
146
+ const selectedDateToUse = this.props.multiple
147
+ ? selectedDate || this.props.selectedDates || []
148
+ : moment(selectedDate || this.state.selectedDate);
149
+
150
+ // set dateToModify to be Sunday of that week
151
+ while (dateToModify.day() !== 0) {
152
+ dateToModify = dateToModify.add(-1, 'day');
153
+ }
154
+
155
+ const rows = [[]];
156
+
157
+ while (dateToTarget.day() !== 6) {
158
+ dateToTarget = dateToTarget.add(1, 'day');
159
+ }
160
+ dateToTarget = dateToTarget.add(1, 'day'); // add an extra day to complete the week
161
+
162
+ while (!dateToModify.isSame(dateToTarget, 'day')) {
163
+ if (rows[rows.length - 1].length === 7) {
164
+ // week has filled - add new row
165
+ rows.push([]);
166
+ }
167
+ const thisDate = moment(dateToModify);
168
+
169
+ rows[rows.length - 1].push({
170
+ date: thisDate,
171
+ dateKey: thisDate.format('DD-MM-YYYY'),
172
+ display: thisDate.date(),
173
+ isFaded: !thisDate.isSame(month, 'month'),
174
+ isToday: thisDate.isSame(moment(), 'date'),
175
+ isSelected: this.isDateSelected(thisDate, selectedDateToUse),
176
+ });
177
+
178
+ dateToModify = dateToModify.add(1, 'day');
179
+ }
180
+
181
+ this.setState({
182
+ grid: rows,
183
+ });
184
+ }
185
+
186
+ renderGrid() {
187
+ return this.state.grid.map((row, index) => {
188
+ return (
189
+ <div className="datepicker__row marginTop-8" key={index}>
190
+ {row.map((date) => {
191
+ let classes = 'datepicker__date';
192
+ if (date.isFaded) {
193
+ classes += ' datepicker__date--faded';
194
+ }
195
+ if (date.isToday) {
196
+ classes += ' datepicker__date--today';
197
+ }
198
+ if (date.isSelected) {
199
+ classes += ' datepicker__date--selected';
200
+ }
201
+ return (
202
+ <div className={classes} key={date.dateKey}>
203
+ <div
204
+ className="datepicker__date__inner"
205
+ onClick={(e) => {
206
+ this.selectDate(date.date, e);
207
+ }}
208
+ >
209
+ {date.display}
210
+ </div>
211
+ </div>
212
+ );
213
+ })}
214
+ </div>
215
+ );
216
+ });
217
+ }
218
+
219
+ renderTop() {
220
+ if (this.props.hideTop) {
221
+ return null;
222
+ }
223
+ if (this.props.multiple) {
224
+ return (
225
+ <div className="datepicker__multitop">
226
+ <p className="datepicker__multitop__text">Shift + Click to select a range of dates</p>
227
+ </div>
228
+ );
229
+ }
230
+ return (
231
+ <div className="datepicker__top">
232
+ <p className="datepicker__title truncate">{this.getDate()}</p>
233
+ </div>
234
+ );
235
+ }
236
+
237
+ render() {
238
+ return (
239
+ <div className="datepicker noselect" style={this.props.style}>
240
+ {this.renderTop()}
241
+ <div className="datepicker__bottom">
242
+ <div className="datepicker__bottomHeader">
243
+ {/* <div className='datepicker__selectedDate'>
244
+ <p className='datepicker__selectedDateText'>{this.getShortDate()}</p>
245
+ </div> */}
246
+ <div className="datepicker__monthSelector">
247
+ <P60Icon className="datepicker__monthChevron" icon="chevron_left" onClick={this.changeMonth.bind(this, -1)} />
248
+ <p className="datepicker__selectedMonth">{this.getMonth()}</p>
249
+ <P60Icon className="datepicker__monthChevron" icon="chevron_right" onClick={this.changeMonth.bind(this, 1)} />
250
+ </div>
251
+ </div>
252
+ <div className="datepicker__row marginTop-16">
253
+ <p className="datepicker__colHeader">SUN</p>
254
+ <p className="datepicker__colHeader">MON</p>
255
+ <p className="datepicker__colHeader">TUE</p>
256
+ <p className="datepicker__colHeader">WED</p>
257
+ <p className="datepicker__colHeader">THU</p>
258
+ <p className="datepicker__colHeader">FRI</p>
259
+ <p className="datepicker__colHeader">SAT</p>
260
+ </div>
261
+ {this.renderGrid()}
262
+ </div>
263
+ </div>
264
+ );
265
+ }
266
+ }
267
+
268
+ export { DatePicker };
@@ -0,0 +1,223 @@
1
+ import React, { Component } from 'react';
2
+ import _ from 'lodash';
3
+ import FontAwesome from 'react-fontawesome';
4
+ import { INACTIVE_TEXT } from '../colours';
5
+
6
+ class DropdownInput extends Component {
7
+ constructor(props) {
8
+ super(props);
9
+ this.state = {
10
+ width: 0,
11
+ height: 0,
12
+ open: false,
13
+ };
14
+
15
+ this.setWrapperRef = this.setWrapperRef.bind(this);
16
+ this.handleClickOutside = this.handleClickOutside.bind(this);
17
+ }
18
+
19
+ componentDidMount() {
20
+ document.addEventListener('mousedown', this.handleClickOutside);
21
+ }
22
+
23
+ componentWillUnmount() {
24
+ document.removeEventListener('mousedown', this.handleClickOutside);
25
+ }
26
+
27
+ setWrapperRef(node) {
28
+ this.wrapperRef = node;
29
+ }
30
+
31
+ handleClickOutside(event) {
32
+ if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
33
+ this.setState({ open: false });
34
+ }
35
+ }
36
+
37
+ getAutoComplete() {
38
+ if (!_.isUndefined(this.props.autoComplete)) {
39
+ return this.props.autoComplete ? 'on' : 'off';
40
+ }
41
+ return 'off';
42
+ }
43
+
44
+ getClassNames() {
45
+ let string = '';
46
+ if (this.props.className) {
47
+ string += `${this.props.className} `;
48
+ }
49
+ if (!_.isUndefined(this.props.disabled) && this.props.disabled) {
50
+ string = 'genericInput-disabled ';
51
+ }
52
+ if (this.props.large) {
53
+ string += 'genericInput-large ';
54
+ }
55
+ if (!_.isUndefined(this.props.showError) && this.props.showError()) {
56
+ return string + 'genericInput-error';
57
+ }
58
+ if (!_.isUndefined(this.props.isValid) && this.props.isValid()) {
59
+ return string + 'genericInput-valid';
60
+ }
61
+ return string;
62
+ }
63
+
64
+ getLabelStyle() {
65
+ const style = {};
66
+ if (_.isEmpty(this.props.value) && !this.props.alwaysShowLabel) {
67
+ style.opacity = 0;
68
+ }
69
+ if (!_.isUndefined(this.props.ignoreValue) && this.props.value === this.props.ignoreValue && !this.props.alwaysShowLabel) {
70
+ style.opacity = 0;
71
+ }
72
+ // if (this.props.isRequired) {
73
+ // style.marginLeft = 12;
74
+ // }
75
+ return style;
76
+ }
77
+
78
+ renderError() {
79
+ if (!_.isUndefined(this.props.showError) && this.props.showError()) {
80
+ return <div className={'fieldLabel fieldLabel-warning'}>{this.props.errorMessage ? this.props.errorMessage : 'Required'}</div>;
81
+ }
82
+ return null;
83
+ }
84
+
85
+ renderHelp() {
86
+ if (!_.isUndefined(this.props.help)) {
87
+ return <div className="genericInput-help">{this.props.help}</div>;
88
+ }
89
+ return null;
90
+ }
91
+
92
+ open() {
93
+ if (this.props.disabled) {
94
+ return;
95
+ }
96
+ this.setState({ open: !this.state.open });
97
+ }
98
+
99
+ renderOption() {
100
+ if (!this.state.open) {
101
+ return null;
102
+ }
103
+ return (
104
+ <div style={styles.dropdownItemsWrapper}>
105
+ {_.values(this.props.options).map((cat) => {
106
+ return (
107
+ <div
108
+ key={cat.Key}
109
+ className="subtleHover fontRegular fontSize-16 text-dark"
110
+ style={styles.dropDownOption}
111
+ onClick={() => {
112
+ this.props.onSelect(cat.Key);
113
+ }}
114
+ >
115
+ {cat.Title}
116
+ </div>
117
+ );
118
+ })}
119
+ </div>
120
+ );
121
+ }
122
+
123
+ getBottomBorder() {
124
+ if (!_.isUndefined(this.props.disabled) && this.props.disabled) {
125
+ return 'dropdownInput-bottomBorder--disabled';
126
+ }
127
+ if (!_.isUndefined(this.props.showError) && this.props.showError()) {
128
+ return 'dropdownInput-bottomBorder--error';
129
+ }
130
+ return '';
131
+ }
132
+
133
+ renderInput() {
134
+ return (
135
+ <div style={styles.row}>
136
+ {this.props.isRequired && <div className="inputRequired " />}
137
+ <div
138
+ onClick={this.open.bind(this)}
139
+ className={`dropdownInput-bottomBorder ${this.getBottomBorder()} ${!this.props.disabled ? 'pointer' : ''}`}
140
+ >
141
+ <input
142
+ id={this.props.id}
143
+ placeholder={!_.isUndefined(this.props.placeholder) ? this.props.placeholder : this.props.label}
144
+ type={!_.isUndefined(this.props.type) ? this.props.type : 'text'}
145
+ className={`genericInput ${!this.props.disabled ? 'pointer' : ''}`}
146
+ value={this.props.value}
147
+ onChange={this.props.onChange}
148
+ onKeyPress={this.props.onEnter}
149
+ style={{ ...this.props.inputStyle }}
150
+ disabled
151
+ autoComplete="false"
152
+ />
153
+ <div style={styles.chevronWrapper}>
154
+ <FontAwesome
155
+ style={{
156
+ ...styles.chevron,
157
+ color: !_.isUndefined(this.props.disabled) && this.props.disabled ? 'transparent' : INACTIVE_TEXT,
158
+ }}
159
+ name={this.state.open ? 'chevron-up' : 'chevron-down'}
160
+ />
161
+ </div>
162
+ {this.renderOption()}
163
+ </div>
164
+ </div>
165
+ );
166
+ }
167
+
168
+ render() {
169
+ return (
170
+ <div
171
+ ref={this.setWrapperRef}
172
+ className={`dropdownInput ${this.getClassNames()}`}
173
+ style={{ marginBottom: 16, position: 'relative', ...this.props.style }}
174
+ >
175
+ <div style={{ ...styles.row, marginBottom: 0, justifyContent: 'space-between' }}>
176
+ {!_.isUndefined(this.props.label) && (
177
+ <div className="fieldLabel" style={this.getLabelStyle()}>
178
+ {this.props.label}
179
+ </div>
180
+ )}
181
+ {this.renderError()}
182
+ </div>
183
+ {/* Render either generic input or large text area */}
184
+ {this.renderInput()}
185
+ {/* Render bottom help info */}
186
+ {this.renderHelp()}
187
+ </div>
188
+ );
189
+ }
190
+ }
191
+
192
+ const styles = {
193
+ row: {
194
+ display: 'flex',
195
+ flexDirection: 'row',
196
+ alignItems: 'center',
197
+ },
198
+ chevronWrapper: {
199
+ display: 'flex',
200
+ flexDirection: 'column',
201
+ justifyContent: 'center',
202
+ },
203
+ chevron: {
204
+ fontSize: 12,
205
+ paddingBottom: 4,
206
+ },
207
+ dropdownItemsWrapper: {
208
+ backgroundColor: '#fff',
209
+ position: 'absolute',
210
+ width: '100%',
211
+ top: 35,
212
+ boxShadow: '2px 2px 10px rgba(106, 163, 216, 0.7)',
213
+ zIndex: 90,
214
+ borderRadius: 4,
215
+ paddingTop: 4,
216
+ paddingBottom: 4,
217
+ },
218
+ dropDownOption: {
219
+ padding: '4px 16px',
220
+ },
221
+ };
222
+
223
+ export { DropdownInput };