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