@plusscommunities/pluss-circles-web-groups 1.5.6 → 1.5.7-beta.1

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.
@@ -1,387 +1,527 @@
1
- import React, { Component } from 'react';
2
- import { connect } from 'react-redux';
3
- import _ from 'lodash';
4
- import moment from 'moment';
5
- import { Link } from 'react-router-dom';
6
- import { PlussCore } from '../feature.config';
7
- import { circlesLoaded, circleRemoved } from '../actions';
8
- import { circleActions } from '../apis';
9
- import { Table } from 'react-bootstrap';
10
- import FontAwesome from 'react-fontawesome';
11
- import { values } from '../values.config';
1
+ import React, { Component } from "react";
2
+ import { connect } from "react-redux";
3
+ import _ from "lodash";
4
+ import moment from "moment";
5
+ import { Link } from "react-router-dom";
6
+ import { PlussCore } from "../feature.config";
7
+ import { circlesLoaded, circleRemoved } from "../actions";
8
+ import { circleActions } from "../apis";
9
+ import { Table } from "react-bootstrap";
10
+ import FontAwesome from "react-fontawesome";
11
+ import { values } from "../values.config";
12
12
 
13
13
  const { Components, Session, Helper } = PlussCore;
14
14
 
15
15
  class Circles extends Component {
16
- constructor(props) {
17
- super(props);
18
- this.state = {
19
- userSearch: '',
20
- };
21
- }
22
-
23
- componentDidMount() {
24
- this.getData();
25
- }
26
-
27
- getData = () => {
28
- const { auth } = this.props;
29
- this.setState({ loadingAll: true }, async () => {
30
- try {
31
- const res = await circleActions.getAll(auth.site);
32
- console.log('getData', res.data);
33
- this.props.circlesLoaded(res.data);
34
- this.setState({ loadingAll: false });
35
- } catch (error) {
36
- console.error('getData', error);
37
- this.setState({ loadingAll: false });
38
- }
39
- });
40
- };
41
-
42
- getCircles() {
43
- let result = this.props.circles;
44
- if (this.state.selectedTypeFilter) {
45
- result = _.filter(result, (circle) => {
46
- return this.state.selectedTypeFilter === 'circle' ? !circle.IsPrivate : circle.IsPrivate;
47
- });
48
- }
49
- if (this.state.selectedUserFilter) {
50
- result = _.filter(result, (circle) => {
51
- return _.some(circle.Audience, (user) => {
52
- return user.userId === this.state.selectedUserFilter.userId;
53
- });
54
- });
55
- }
56
- return result;
57
- }
58
-
59
- getUsers() {
60
- let users = [];
61
- this.props.circles.forEach((circle) => {
62
- circle.Audience.forEach((user) => {
63
- users.push(user);
64
- });
65
- });
66
- users = _.sortBy(
67
- _.uniqBy(users, (user) => {
68
- return user.userId;
69
- }),
70
- 'displayName',
71
- );
72
- return _.filter(users, (u) => {
73
- if (!_.isEmpty(this.state.userSearch)) {
74
- return (u.displayName || '').toLowerCase().indexOf(this.state.userSearch.toLowerCase()) > -1;
75
- }
76
- return true;
77
- });
78
- }
79
-
80
- validateCircleAdmin(circle, onlyCreator) {
81
- if (Session.validateAccess(this.props.auth.site, values.permission, this.props.auth)) {
82
- return true;
83
- }
84
- if (onlyCreator) {
85
- return (circle.Creator && circle.Creator.userId === this.props.user.Id) || circle.CreatorId === this.props.user.Id;
86
- }
87
- return _.some(circle.Audience, (user) => {
88
- return user.userId === this.props.user.Id && user.isAdmin;
89
- });
90
- }
91
-
92
- canAddNew = () => {
93
- const { auth } = this.props;
94
- return Session.validateAccess(auth.site, values.permission, auth);
95
- };
96
-
97
- onAddNew = () => {
98
- const { auth } = this.props;
99
- if (Session.validateAccess(auth.site, values.permission, auth)) {
100
- this.props.history.push(`/${values.featureKey}/add`);
101
- }
102
- };
103
-
104
- openUserFilter = () => {
105
- this.setState({
106
- userFilterOpen: true,
107
- });
108
- };
109
-
110
- closeUserFilter = () => {
111
- this.setState({
112
- userFilterOpen: false,
113
- });
114
- };
115
-
116
- selectUserFilter = (user) => {
117
- this.setState({
118
- selectedUserFilter: user,
119
- userFilterOpen: false,
120
- });
121
- };
122
-
123
- removeUserFilter = (event) => {
124
- event.stopPropagation();
125
- this.setState({
126
- selectedUserFilter: null,
127
- });
128
- };
129
-
130
- openTypeFilter = () => {
131
- this.setState({
132
- typeFilterOpen: true,
133
- });
134
- };
135
-
136
- closeTypeFilter = () => {
137
- this.setState({
138
- typeFilterOpen: false,
139
- });
140
- };
141
-
142
- selectTypeFilter = (type) => {
143
- this.setState({
144
- selectedTypeFilter: type,
145
- typeFilterOpen: false,
146
- });
147
- };
148
-
149
- removeTypeFilter = (event) => {
150
- event.stopPropagation();
151
- this.setState({
152
- selectedTypeFilter: null,
153
- });
154
- };
155
-
156
- onHandleChange = (event) => {
157
- var stateChange = {};
158
- stateChange[event.target.getAttribute('id')] = event.target.value;
159
- this.setState(stateChange);
160
- };
161
-
162
- removeCircle = (circle) => {
163
- if (
164
- window.confirm(
165
- `Are you sure you want to delete that ${values.entityName}? You will no longer be able to access the messages in the ${values.entityName}.`,
166
- )
167
- ) {
168
- this.props.circleRemoved(circle.Id);
169
- circleActions
170
- .delete(circle.Id)
171
- .then((res) => {
172
- this.getData();
173
- })
174
- .catch((res) => {
175
- alert('Something went wrong with the request. Please try again.');
176
- });
177
- }
178
- };
179
-
180
- getTypeFilterText = (type) => {
181
- if (type === 'private') {
182
- return 'Private Message';
183
- }
184
- return _.capitalize(values.entityName);
185
- };
186
-
187
- getTitle = (circle) => {
188
- if (circle.IsPrivate) {
189
- return `PM: ${circle.Audience.map((user) => {
190
- return user.displayName;
191
- }).join(', ')}`;
192
- }
193
- return circle.Title;
194
- };
195
-
196
- renderRow(circle) {
197
- return (
198
- <tr key={circle.Id}>
199
- <td className="table-TitleColumn">
200
- <Link to={`/${values.featureKey}/${values.entityKey}/${circle.Id}`}>{this.getTitle(circle)}</Link>
201
- </td>
202
- <td>{moment(circle.Changed).local().format('D MMM YYYY')}</td>
203
- <td>
204
- {circle.Audience.map((user) => {
205
- return (
206
- <Components.ProfilePic
207
- size={30}
208
- image={user.profilePic}
209
- hoverText={user.displayName}
210
- containerClass="circleTableProfilePic"
211
- />
212
- );
213
- })}
214
- </td>
215
- <td className="table-options">
216
- <div style={{ display: 'flex', alignItems: 'center' }}>
217
- {this.validateCircleAdmin(circle) && !circle.IsPrivate && (
218
- <Link to={`/${values.featureKey}/edit/${circle.Id}`}>
219
- <FontAwesome
220
- style={{
221
- fontSize: 20,
222
- padding: 5,
223
- marginLeft: 12,
224
- cursor: 'pointer',
225
- }}
226
- name="pencil"
227
- />
228
- </Link>
229
- )}
230
- {this.validateCircleAdmin(circle, true) && !circle.IsPrivate && (
231
- <a
232
- onClick={() => {
233
- this.removeCircle(circle);
234
- }}
235
- >
236
- <FontAwesome
237
- style={{
238
- fontSize: 20,
239
- padding: 5,
240
- marginLeft: 12,
241
- cursor: 'pointer',
242
- }}
243
- name="minus-circle"
244
- />
245
- </a>
246
- )}
247
- </div>
248
- </td>
249
- </tr>
250
- );
251
- }
252
-
253
- renderFilters() {
254
- let userFilter = <Components.Tag className="marginRight-10" onClick={this.openUserFilter} text="User" />;
255
- let typeFilter = <Components.Tag className="marginRight-10" onClick={this.openTypeFilter} text="Type" />;
256
-
257
- if (this.state.selectedUserFilter) {
258
- userFilter = (
259
- <Components.Tag className="marginRight-10" onClick={this.openUserFilter} rightIcon="close" rightClick={this.removeUserFilter}>
260
- <Components.UserListing size={15} user={this.state.selectedUserFilter} textClass="tag_text" />
261
- </Components.Tag>
262
- );
263
- }
264
- if (this.state.selectedTypeFilter) {
265
- typeFilter = (
266
- <Components.Tag
267
- className="marginRight-10"
268
- onClick={this.openTypeFilter}
269
- rightIcon="close"
270
- rightClick={this.removeTypeFilter}
271
- text={this.getTypeFilterText(this.state.selectedTypeFilter)}
272
- />
273
- );
274
- }
275
- return (
276
- <div className="flex flex-center marginTop-20">
277
- <Components.Text type="h5" className="marginRight-20">
278
- Filter by
279
- </Components.Text>
280
- {userFilter}
281
- {typeFilter}
282
- </div>
283
- );
284
- }
285
-
286
- renderUserFilterPopup() {
287
- if (!this.state.userFilterOpen) {
288
- return null;
289
- }
290
- return (
291
- <Components.Popup title="Select User" maxWidth={600} minWidth={400} minHeight={400} hasPadding onClose={this.closeUserFilter}>
292
- <Components.GenericInput
293
- id="userSearch"
294
- type="text"
295
- label="Search"
296
- placeholder="Enter name"
297
- value={this.state.userSearch}
298
- onChange={(e) => this.onHandleChange(e)}
299
- alwaysShowLabel
300
- />
301
- {this.getUsers().map((user) => {
302
- return (
303
- <Components.UserListing
304
- key={user.userId}
305
- user={user}
306
- onClick={() => {
307
- this.selectUserFilter(user);
308
- }}
309
- />
310
- );
311
- })}
312
- </Components.Popup>
313
- );
314
- }
315
-
316
- renderTypeFilterPopup() {
317
- if (!this.state.typeFilterOpen) {
318
- return null;
319
- }
320
- return (
321
- <Components.Popup title="Select Type" maxWidth={600} minWidth={400} hasPadding onClose={this.closeTypeFilter}>
322
- <Components.Tag
323
- onClick={() => {
324
- this.selectTypeFilter('circle');
325
- }}
326
- text={_.capitalize(values.entityName)}
327
- className="marginRight-10"
328
- />
329
- <Components.Tag
330
- onClick={() => {
331
- this.selectTypeFilter('private');
332
- }}
333
- text="Private Message"
334
- />
335
- </Components.Popup>
336
- );
337
- }
338
-
339
- render() {
340
- return (
341
- <div>
342
- {this.renderTypeFilterPopup()}
343
- {this.renderUserFilterPopup()}
344
- <Components.Header>
345
- {this.canAddNew() && <Components.AddButton onClick={this.onAddNew} text={`NEW ${_.upperCase(values.entityName)}`} />}
346
- </Components.Header>
347
- <div className="pageContainer paddingVertical-20 paddingHorizontal-40">
348
- <Components.Text type="h1" className="">
349
- {values.textFeatureTitle}
350
- </Components.Text>
351
- {this.renderFilters()}
352
-
353
- <Table className="plussTable" striped bordered condensed hover style={{ minWidth: '100%' }}>
354
- <thead>
355
- <tr>
356
- <th>Title</th>
357
- <th>Last updated</th>
358
- <th>Members</th>
359
- <th style={{ width: 50 }} />
360
- </tr>
361
- </thead>
362
- <tbody>
363
- {this.getCircles().map((circle) => {
364
- return this.renderRow(circle);
365
- })}
366
- </tbody>
367
- </Table>
368
- </div>
369
- </div>
370
- );
371
- }
16
+ constructor(props) {
17
+ super(props);
18
+ this.state = {
19
+ userSearch: "",
20
+ sortBy: "newest",
21
+ showUnreadOnly: false,
22
+ pollingInterval: null,
23
+ };
24
+ }
25
+
26
+ componentDidMount() {
27
+ this.getData();
28
+ // Poll for updates every 10 seconds
29
+ this.pollingInterval = setInterval(() => {
30
+ this.getData();
31
+ }, 10000);
32
+ }
33
+
34
+ getData = () => {
35
+ const { auth } = this.props;
36
+ this.setState({ loadingAll: true }, async () => {
37
+ try {
38
+ const res = await circleActions.getAll(auth.site);
39
+ console.log("getData", res.data);
40
+ this.props.circlesLoaded(res.data);
41
+ this.setState({ loadingAll: false });
42
+ } catch (error) {
43
+ console.error("getData", error);
44
+ this.setState({ loadingAll: false });
45
+ }
46
+ });
47
+ };
48
+
49
+ componentWillUnmount() {
50
+ if (this.pollingInterval) {
51
+ clearInterval(this.pollingInterval);
52
+ }
53
+ }
54
+
55
+ isCircleUnread(circle) {
56
+ const userId = this.props.user.Id;
57
+ if (!circle.Unread || !circle.Unread[userId]) {
58
+ return false;
59
+ }
60
+ return circle.Unread[userId] > 0;
61
+ }
62
+
63
+ getUnreadCount(circle) {
64
+ const userId = this.props.user.Id;
65
+ if (!circle.Unread || !circle.Unread[userId]) {
66
+ return 0;
67
+ }
68
+ return circle.Unread[userId];
69
+ }
70
+
71
+ selectUnreadFilter = (showUnreadOnly) => {
72
+ this.setState({ showUnreadOnly });
73
+ };
74
+ getCircles() {
75
+ let result = this.props.circles;
76
+ if (this.state.selectedTypeFilter) {
77
+ result = _.filter(result, (circle) => {
78
+ return this.state.selectedTypeFilter === "circle"
79
+ ? !circle.IsPrivate
80
+ : circle.IsPrivate;
81
+ });
82
+ }
83
+ if (this.state.selectedUserFilter) {
84
+ result = _.filter(result, (circle) => {
85
+ return _.some(circle.Audience, (user) => {
86
+ return user.userId === this.state.selectedUserFilter.userId;
87
+ });
88
+ });
89
+ }
90
+ // Apply sorting
91
+ result = _.sortBy(result, (circle) => {
92
+ return moment(circle.Changed).valueOf();
93
+ });
94
+ if (this.state.sortBy === "newest") {
95
+ result.reverse();
96
+ if (this.state.showUnreadOnly) {
97
+ result = _.filter(result, (circle) => {
98
+ return this.isCircleUnread(circle);
99
+ });
100
+ }
101
+ }
102
+ return result;
103
+ }
104
+
105
+ getUsers() {
106
+ let users = [];
107
+ this.props.circles.forEach((circle) => {
108
+ circle.Audience.forEach((user) => {
109
+ users.push(user);
110
+ });
111
+ });
112
+ users = _.sortBy(
113
+ _.uniqBy(users, (user) => {
114
+ return user.userId;
115
+ }),
116
+ "displayName",
117
+ );
118
+ return _.filter(users, (u) => {
119
+ if (!_.isEmpty(this.state.userSearch)) {
120
+ return (
121
+ (u.displayName || "")
122
+ .toLowerCase()
123
+ .indexOf(this.state.userSearch.toLowerCase()) > -1
124
+ );
125
+ }
126
+ return true;
127
+ });
128
+ }
129
+
130
+ validateCircleAdmin(circle, onlyCreator) {
131
+ if (
132
+ Session.validateAccess(
133
+ this.props.auth.site,
134
+ values.permission,
135
+ this.props.auth,
136
+ )
137
+ ) {
138
+ return true;
139
+ }
140
+ if (onlyCreator) {
141
+ return (
142
+ (circle.Creator && circle.Creator.userId === this.props.user.Id) ||
143
+ circle.CreatorId === this.props.user.Id
144
+ );
145
+ }
146
+ return _.some(circle.Audience, (user) => {
147
+ return user.userId === this.props.user.Id && user.isAdmin;
148
+ });
149
+ }
150
+
151
+ canAddNew = () => {
152
+ const { auth } = this.props;
153
+ return Session.validateAccess(auth.site, values.permission, auth);
154
+ };
155
+
156
+ onAddNew = () => {
157
+ const { auth } = this.props;
158
+ if (Session.validateAccess(auth.site, values.permission, auth)) {
159
+ this.props.history.push(`/${values.featureKey}/add`);
160
+ }
161
+ };
162
+
163
+ openUserFilter = () => {
164
+ this.setState({
165
+ userFilterOpen: true,
166
+ });
167
+ };
168
+
169
+ closeUserFilter = () => {
170
+ this.setState({
171
+ userFilterOpen: false,
172
+ });
173
+ };
174
+
175
+ selectUserFilter = (user) => {
176
+ this.setState({
177
+ selectedUserFilter: user,
178
+ userFilterOpen: false,
179
+ });
180
+ };
181
+
182
+ removeUserFilter = (event) => {
183
+ event.stopPropagation();
184
+ this.setState({
185
+ selectedUserFilter: null,
186
+ });
187
+ };
188
+
189
+ openTypeFilter = () => {
190
+ this.setState({
191
+ typeFilterOpen: true,
192
+ });
193
+ };
194
+
195
+ closeTypeFilter = () => {
196
+ this.setState({
197
+ typeFilterOpen: false,
198
+ });
199
+ };
200
+
201
+ selectTypeFilter = (type) => {
202
+ this.setState({
203
+ selectedTypeFilter: type,
204
+ typeFilterOpen: false,
205
+ });
206
+ };
207
+
208
+ removeTypeFilter = (event) => {
209
+ event.stopPropagation();
210
+ this.setState({
211
+ selectedTypeFilter: null,
212
+ });
213
+ };
214
+
215
+ selectSort = (sortType) => {
216
+ this.setState({
217
+ sortBy: sortType,
218
+ });
219
+ };
220
+
221
+ onHandleChange = (event) => {
222
+ var stateChange = {};
223
+ stateChange[event.target.getAttribute("id")] = event.target.value;
224
+ this.setState(stateChange);
225
+ };
226
+
227
+ removeCircle = (circle) => {
228
+ if (
229
+ window.confirm(
230
+ `Are you sure you want to delete that ${values.entityName}? You will no longer be able to access the messages in the ${values.entityName}.`,
231
+ )
232
+ ) {
233
+ this.props.circleRemoved(circle.Id);
234
+ circleActions
235
+ .delete(circle.Id)
236
+ .then((res) => {
237
+ this.getData();
238
+ })
239
+ .catch((res) => {
240
+ alert("Something went wrong with the request. Please try again.");
241
+ });
242
+ }
243
+ };
244
+
245
+ getTypeFilterText = (type) => {
246
+ if (type === "private") {
247
+ return "Private Message";
248
+ }
249
+ return _.capitalize(values.entityName);
250
+ };
251
+
252
+ getTitle = (circle) => {
253
+ if (circle.IsPrivate) {
254
+ return `PM: ${circle.Audience.map((user) => {
255
+ return user.displayName;
256
+ }).join(", ")}`;
257
+ }
258
+ return circle.Title;
259
+ };
260
+
261
+ renderRow(circle) {
262
+ return (
263
+ <tr key={circle.Id}>
264
+ <td className="table-TitleColumn">
265
+ <Link to={`/${values.featureKey}/${values.entityKey}/${circle.Id}`}>
266
+ {this.getTitle(circle)}
267
+ </Link>
268
+ </td>
269
+ <td>{moment(circle.Changed).local().format("D MMM YYYY")}</td>
270
+ <td>
271
+ {circle.Audience.map((user) => {
272
+ return (
273
+ <Components.ProfilePic
274
+ size={30}
275
+ image={user.profilePic}
276
+ hoverText={user.displayName}
277
+ containerClass="circleTableProfilePic"
278
+ />
279
+ );
280
+ })}
281
+ </td>
282
+ <td className="table-options">
283
+ <div style={{ display: "flex", alignItems: "center" }}>
284
+ {this.validateCircleAdmin(circle) && !circle.IsPrivate && (
285
+ <Link to={`/${values.featureKey}/edit/${circle.Id}`}>
286
+ <FontAwesome
287
+ style={{
288
+ fontSize: 20,
289
+ padding: 5,
290
+ marginLeft: 12,
291
+ cursor: "pointer",
292
+ }}
293
+ name="pencil"
294
+ />
295
+ </Link>
296
+ )}
297
+ {this.validateCircleAdmin(circle, true) && !circle.IsPrivate && (
298
+ <a
299
+ onClick={() => {
300
+ this.removeCircle(circle);
301
+ }}
302
+ >
303
+ <FontAwesome
304
+ style={{
305
+ fontSize: 20,
306
+ padding: 5,
307
+ marginLeft: 12,
308
+ cursor: "pointer",
309
+ }}
310
+ name="minus-circle"
311
+ />
312
+ </a>
313
+ )}
314
+ </div>
315
+ </td>
316
+ </tr>
317
+ );
318
+ }
319
+
320
+ renderFilters() {
321
+ let userFilter = (
322
+ <Components.Tag
323
+ className="marginRight-10"
324
+ onClick={this.openUserFilter}
325
+ text="User"
326
+ />
327
+ );
328
+
329
+ let unreadFilter = (
330
+ <Components.Tag
331
+ className="marginRight-10"
332
+ onClick={() => this.selectUnreadFilter(!this.state.showUnreadOnly)}
333
+ leftIcon={this.state.showUnreadOnly ? "check" : null}
334
+ text="Unread Only"
335
+ />
336
+ );
337
+
338
+ let typeFilter = (
339
+ <Components.Tag
340
+ className="marginRight-10"
341
+ onClick={this.openTypeFilter}
342
+ text="Type"
343
+ />
344
+ );
345
+
346
+ if (this.state.selectedUserFilter) {
347
+ userFilter = (
348
+ <Components.Tag
349
+ className="marginRight-10"
350
+ onClick={this.openUserFilter}
351
+ rightIcon="close"
352
+ rightClick={this.removeUserFilter}
353
+ >
354
+ <Components.UserListing
355
+ size={15}
356
+ user={this.state.selectedUserFilter}
357
+ textClass="tag_text"
358
+ />
359
+ </Components.Tag>
360
+ );
361
+ }
362
+ if (this.state.selectedTypeFilter) {
363
+ typeFilter = (
364
+ <Components.Tag
365
+ className="marginRight-10"
366
+ onClick={this.openTypeFilter}
367
+ rightIcon="close"
368
+ rightClick={this.removeTypeFilter}
369
+ text={this.getTypeFilterText(this.state.selectedTypeFilter)}
370
+ />
371
+ );
372
+ }
373
+ return (
374
+ <div className="flex flex-center marginTop-20">
375
+ <Components.Text type="h5" className="marginRight-20">
376
+ Filter by
377
+ </Components.Text>
378
+ {userFilter}
379
+ {unreadFilter}
380
+ {typeFilter}
381
+ <Components.Text type="h5" className="marginRight-20 marginLeft-20">
382
+ Sort by:
383
+ </Components.Text>
384
+ <Components.Tag
385
+ className="marginRight-10"
386
+ onClick={() => this.selectSort("newest")}
387
+ leftIcon={this.state.sortBy === "newest" ? "check" : null}
388
+ text="Newest first"
389
+ />
390
+ <Components.Tag
391
+ onClick={() => this.selectSort("oldest")}
392
+ leftIcon={this.state.sortBy === "oldest" ? "check" : null}
393
+ text="Oldest first"
394
+ />
395
+ </div>
396
+ );
397
+ }
398
+
399
+ renderUserFilterPopup() {
400
+ if (!this.state.userFilterOpen) {
401
+ return null;
402
+ }
403
+ return (
404
+ <Components.Popup
405
+ title="Select User"
406
+ maxWidth={600}
407
+ minWidth={400}
408
+ minHeight={400}
409
+ hasPadding
410
+ onClose={this.closeUserFilter}
411
+ >
412
+ <Components.GenericInput
413
+ id="userSearch"
414
+ type="text"
415
+ label="Search"
416
+ placeholder="Enter name"
417
+ value={this.state.userSearch}
418
+ onChange={(e) => this.onHandleChange(e)}
419
+ alwaysShowLabel
420
+ />
421
+ {this.getUsers().map((user) => {
422
+ return (
423
+ <Components.UserListing
424
+ key={user.userId}
425
+ user={user}
426
+ onClick={() => {
427
+ this.selectUserFilter(user);
428
+ }}
429
+ />
430
+ );
431
+ })}
432
+ </Components.Popup>
433
+ );
434
+ }
435
+
436
+ renderTypeFilterPopup() {
437
+ if (!this.state.typeFilterOpen) {
438
+ return null;
439
+ }
440
+ return (
441
+ <Components.Popup
442
+ title="Select Type"
443
+ maxWidth={600}
444
+ minWidth={400}
445
+ hasPadding
446
+ onClose={this.closeTypeFilter}
447
+ >
448
+ <Components.Tag
449
+ onClick={() => {
450
+ this.selectTypeFilter("circle");
451
+ }}
452
+ text={_.capitalize(values.entityName)}
453
+ className="marginRight-10"
454
+ />
455
+ <Components.Tag
456
+ onClick={() => {
457
+ this.selectTypeFilter("private");
458
+ }}
459
+ text="Private Message"
460
+ />
461
+ </Components.Popup>
462
+ );
463
+ }
464
+
465
+ render() {
466
+ return (
467
+ <div>
468
+ {this.renderTypeFilterPopup()}
469
+ {this.renderUserFilterPopup()}
470
+ <Components.Header>
471
+ {this.canAddNew() && (
472
+ <Components.AddButton
473
+ onClick={this.onAddNew}
474
+ text={`NEW ${_.upperCase(values.entityName)}`}
475
+ />
476
+ )}
477
+ </Components.Header>
478
+ <div className="pageContainer paddingVertical-20 paddingHorizontal-40">
479
+ <Components.Text type="h1" className="">
480
+ {values.textFeatureTitle}
481
+ </Components.Text>
482
+ {this.renderFilters()}
483
+
484
+ <Table
485
+ className="plussTable"
486
+ striped
487
+ bordered
488
+ condensed
489
+ hover
490
+ style={{ minWidth: "100%" }}
491
+ >
492
+ <thead>
493
+ <tr>
494
+ <th>Title</th>
495
+ <th>Last updated</th>
496
+ <th>Members</th>
497
+ <th style={{ width: 50 }} />
498
+ </tr>
499
+ </thead>
500
+ <tbody>
501
+ {this.getCircles().map((circle) => {
502
+ return this.renderRow(circle);
503
+ })}
504
+ </tbody>
505
+ </Table>
506
+ </div>
507
+ </div>
508
+ );
509
+ }
372
510
  }
373
511
 
374
512
  const styles = {};
375
513
 
376
514
  const mapStateToProps = (state) => {
377
- const { circles } = state[values.reducerKey];
378
- const { auth } = state;
379
-
380
- return {
381
- circles,
382
- auth,
383
- user: Helper.getUserFromState(state),
384
- };
515
+ const { circles } = state[values.reducerKey];
516
+ const { auth } = state;
517
+
518
+ return {
519
+ circles,
520
+ auth,
521
+ user: Helper.getUserFromState(state),
522
+ };
385
523
  };
386
524
 
387
- export default connect(mapStateToProps, { circlesLoaded, circleRemoved })(Circles);
525
+ export default connect(mapStateToProps, { circlesLoaded, circleRemoved })(
526
+ Circles,
527
+ );