@plusscommunities/pluss-feeds-web 1.0.1-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.
- package/.babelrc +3 -0
- package/dist/index.cjs.js +2912 -0
- package/dist/index.esm.js +2874 -0
- package/dist/index.umd.js +2906 -0
- package/package.json +56 -0
- package/rollup.config.js +59 -0
- package/src/actions/FeedActions.js +73 -0
- package/src/actions/index.js +6 -0
- package/src/actions/types.js +8 -0
- package/src/apis/feedActions.js +94 -0
- package/src/apis/index.js +9 -0
- package/src/apis/reactionActions.js +46 -0
- package/src/components/FeedList.js +682 -0
- package/src/components/FeedSubmissions.js +169 -0
- package/src/components/FeedTypes.js +324 -0
- package/src/components/PreviewFull.js +25 -0
- package/src/components/PreviewGrid.js +29 -0
- package/src/components/PreviewWidget.js +27 -0
- package/src/components/ViewFull.js +18 -0
- package/src/components/ViewWidget.js +16 -0
- package/src/feature.config.js +87 -0
- package/src/images/full.png +0 -0
- package/src/images/fullNoTitle.png +0 -0
- package/src/images/previewWidget.png +0 -0
- package/src/images/widget.png +0 -0
- package/src/index.js +27 -0
- package/src/reducers/FeedReducer.js +71 -0
- package/src/screens/AddFeed.js +402 -0
- package/src/screens/Feed.js +323 -0
- package/src/screens/FeedHub.js +245 -0
- package/src/values.config.default.js +42 -0
- package/src/values.config.js +42 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { withRouter } from 'react-router';
|
|
3
|
+
import { Link } from 'react-router-dom';
|
|
4
|
+
import moment from 'moment';
|
|
5
|
+
import _ from 'lodash';
|
|
6
|
+
import FontAwesome from 'react-fontawesome';
|
|
7
|
+
import Textarea from 'react-textarea-autosize';
|
|
8
|
+
import { connect } from 'react-redux';
|
|
9
|
+
import { feedsLoaded, removeFeedSubmission } from '../actions';
|
|
10
|
+
import { PlussCore } from '../feature.config';
|
|
11
|
+
import { feedActions, reactionActions } from '../apis';
|
|
12
|
+
import { values } from '../values.config';
|
|
13
|
+
|
|
14
|
+
const { Helper, Session, Colours, Components } = PlussCore;
|
|
15
|
+
|
|
16
|
+
class Feed extends Component {
|
|
17
|
+
constructor(props) {
|
|
18
|
+
super(props);
|
|
19
|
+
this.state = {
|
|
20
|
+
feedId: Helper.safeReadParams(props, 'feedId') ? props.match.params.feedId : null,
|
|
21
|
+
feed: null,
|
|
22
|
+
types: [],
|
|
23
|
+
comments: [],
|
|
24
|
+
commentInput: '',
|
|
25
|
+
loadingComments: false,
|
|
26
|
+
editing: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
31
|
+
Session.checkLoggedIn(this, this.props.auth);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
componentDidMount() {
|
|
35
|
+
this.getFeedTypes();
|
|
36
|
+
if (this.state.feedId) {
|
|
37
|
+
this.getFeed();
|
|
38
|
+
this.getComments();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getFeed = async () => {
|
|
43
|
+
try {
|
|
44
|
+
const res = await feedActions.getFeed(this.state.feedId);
|
|
45
|
+
// console.log('getFeed:', res.data);
|
|
46
|
+
this.setState({ feed: res.data });
|
|
47
|
+
this.props.feedsLoaded([res.data]);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('getFeed', error);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
getFeedTypes = async () => {
|
|
54
|
+
try {
|
|
55
|
+
const res = await feedActions.getFeedTypes(this.props.auth.site);
|
|
56
|
+
this.setState({ types: res.data });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('getFeedTypes', error);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
canEdit = () => {
|
|
63
|
+
return Session.validateAccess(this.props.auth.site, values.permissionFeedManagement, this.props.auth);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
canApprove = () => {
|
|
67
|
+
const { feed } = this.state;
|
|
68
|
+
return feed && _.isNil(feed.approved) && this.canEdit();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
editFeed = () => {};
|
|
72
|
+
|
|
73
|
+
getComments = () => {
|
|
74
|
+
reactionActions.getComments(this.state.feedId, values.featureKey, 0).then((res) => {
|
|
75
|
+
this.setState({ comments: res.data });
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
onAddComment = async () => {
|
|
80
|
+
const { commentInput, feedId, feed, comments } = this.state;
|
|
81
|
+
try {
|
|
82
|
+
this.setState({ commentInput: '' });
|
|
83
|
+
const res = await reactionActions.addComment(feedId, values.featureKey, feed.title, feed.site, commentInput);
|
|
84
|
+
this.setState({ comments: [...comments, res.data] });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error('onAddComment', error);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
onHandleChange = (event) => {
|
|
91
|
+
var stateChange = {};
|
|
92
|
+
stateChange[event.target.getAttribute('id')] = event.target.value;
|
|
93
|
+
this.setState(stateChange);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
onReviewFeed = async (approved = true) => {
|
|
97
|
+
if (window.confirm(approved ? values.textAreYouSureYouWantToApprove : values.textAreYouSureYouWantToReject)) {
|
|
98
|
+
try {
|
|
99
|
+
this.setState({ editing: true });
|
|
100
|
+
|
|
101
|
+
const { feed } = this.state;
|
|
102
|
+
const res = await feedActions.reviewFeed(feed.id, approved);
|
|
103
|
+
// console.log('onReviewFeed:', res.data);
|
|
104
|
+
const updated = res.data && res.data.updated;
|
|
105
|
+
this.props.removeFeedSubmission(updated.id);
|
|
106
|
+
this.setState({ editing: false, feed: updated });
|
|
107
|
+
} catch (error) {
|
|
108
|
+
this.setState({ editing: false });
|
|
109
|
+
console.log('onReviewFeed', error);
|
|
110
|
+
alert('Something went wrong with the request. Please try again.');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
renderComment(c) {
|
|
116
|
+
return <Components.Comment key={c.Id} comment={c} />;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
renderCommentSection() {
|
|
120
|
+
if (this.state.loadingComments) return null;
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<div className="padding-60 paddingTop-8 paddingLeft-20">
|
|
124
|
+
<div className="newTopBar paddingLeft-40">
|
|
125
|
+
<Components.Text type="formTitleSmall" className="marginBottom-16">
|
|
126
|
+
Comments
|
|
127
|
+
</Components.Text>
|
|
128
|
+
<div className="commentSection">{this.state.comments.map((c) => this.renderComment(c))}</div>
|
|
129
|
+
<div className="commentReply">
|
|
130
|
+
<div
|
|
131
|
+
className={`commentReply_button${!_.isEmpty(this.state.commentInput) ? ' commentReply_button-active' : ''}`}
|
|
132
|
+
onClick={this.onAddComment}
|
|
133
|
+
>
|
|
134
|
+
<FontAwesome className="commentReply_icon" name="paper-plane-o" />
|
|
135
|
+
</div>
|
|
136
|
+
<Textarea
|
|
137
|
+
id="commentInput"
|
|
138
|
+
placeholder="Reply here..."
|
|
139
|
+
type="text"
|
|
140
|
+
className="commentReply_input"
|
|
141
|
+
value={this.state.commentInput}
|
|
142
|
+
onChange={(e) => this.onHandleChange(e)}
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
renderImages() {
|
|
151
|
+
const { feed } = this.state;
|
|
152
|
+
if (_.isEmpty(feed.photo) && _.isEmpty(feed.photos)) return null;
|
|
153
|
+
|
|
154
|
+
const imagesToUse = _.isEmpty(feed.photo) ? feed.photos : [feed.photo];
|
|
155
|
+
return (
|
|
156
|
+
<div className="imageGrid">
|
|
157
|
+
{imagesToUse.map((image, i) => {
|
|
158
|
+
return (
|
|
159
|
+
<a href={image} target="_blank" rel="noopener noreferrer" key={i}>
|
|
160
|
+
<div className="imageGrid_image" style={{ backgroundImage: `url('${Helper.get1400(image)}')` }}></div>
|
|
161
|
+
</a>
|
|
162
|
+
);
|
|
163
|
+
})}
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
renderInner() {
|
|
169
|
+
const { feed, types } = this.state;
|
|
170
|
+
if (feed == null) return null;
|
|
171
|
+
|
|
172
|
+
const feedType = types.find((t) => t.label === feed.type);
|
|
173
|
+
const editable = this.canEdit();
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<div style={{ paddingBottom: 40 }}>
|
|
177
|
+
<div className="padding-60 paddingVertical-40 relative">
|
|
178
|
+
<Components.Text type="formTitleLarge" className="marginBottom-8">
|
|
179
|
+
{feed.title || 'Feed'}
|
|
180
|
+
</Components.Text>
|
|
181
|
+
<div className="marginTop-16">
|
|
182
|
+
<div className={'fieldLabel'}>Posted to</div>
|
|
183
|
+
<div className={'marginTop-5'}>
|
|
184
|
+
<Components.UserListing size={25} user={feed.user} />
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
{editable && feed.author ? (
|
|
188
|
+
<div className="marginTop-16">
|
|
189
|
+
<div className={'fieldLabel'}>Posted by</div>
|
|
190
|
+
<div className={'marginTop-5'}>
|
|
191
|
+
<Components.UserListing size={25} user={feed.author} />
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
) : null}
|
|
195
|
+
<div className="marginTop-16">
|
|
196
|
+
<Components.Tag
|
|
197
|
+
text={feed.type}
|
|
198
|
+
style={{ backgroundColor: feedType ? feedType.colour : undefined, borderRadius: 8, marginRight: 10 }}
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
{this.renderImages()}
|
|
202
|
+
<div className="marginTop-16">
|
|
203
|
+
<div className={'fontRegular fontSize-16 text-dark marginTop-5'}>{feed.text}</div>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
{feed.approved ? this.renderCommentSection() : null}
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
renderHistoryEntry(e, i) {
|
|
212
|
+
const action = (() => {
|
|
213
|
+
const { approved, deleted } = e.changes;
|
|
214
|
+
if (approved && approved.new === true) return 'Approved';
|
|
215
|
+
if (approved && approved.new === false) return 'Rejected';
|
|
216
|
+
if (deleted && deleted.new === true) return 'Deleted';
|
|
217
|
+
return 'Edited';
|
|
218
|
+
})();
|
|
219
|
+
return (
|
|
220
|
+
<div className="ticketHistoryEntry" key={i}>
|
|
221
|
+
<p className="ticketHistoryEntry_timestamp">{moment.utc(e.timestamp).local().format('D MMM YYYY h:mma')}</p>
|
|
222
|
+
<div className="statusLabel statusLabel-large statusLabel-full" style={{ backgroundColor: Colours.COLOUR_DUSK }}>
|
|
223
|
+
<span className="statusLabel_text">{`${action} by ${e.user.displayName}`}</span>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
renderEditHistory() {
|
|
230
|
+
const { feed } = this.state;
|
|
231
|
+
if (!feed || !feed.history) return null;
|
|
232
|
+
|
|
233
|
+
const source = _.sortBy(feed.history, 'timestamp');
|
|
234
|
+
// console.log('renderEditHistory', JSON.stringify(source, null, 2));
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<div className="padding-32 paddingVertical-40 bottomDivideBorder relative">
|
|
238
|
+
<div className="newTopBar clearfix flex flex-reverse">
|
|
239
|
+
<Components.Text type="formTitleSmall" className="flex-1">
|
|
240
|
+
Edit History
|
|
241
|
+
</Components.Text>
|
|
242
|
+
</div>
|
|
243
|
+
{source.map(this.renderHistoryEntry)}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
renderButtons() {
|
|
249
|
+
const editable = this.canEdit();
|
|
250
|
+
const approvable = this.canApprove();
|
|
251
|
+
const isEditing = this.state.editing;
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<div>
|
|
255
|
+
<Components.Button
|
|
256
|
+
inline
|
|
257
|
+
buttonType="tertiary"
|
|
258
|
+
onClick={() => {
|
|
259
|
+
window.history.back();
|
|
260
|
+
}}
|
|
261
|
+
isActive
|
|
262
|
+
style={{ marginRight: 16 }}
|
|
263
|
+
>
|
|
264
|
+
Back
|
|
265
|
+
</Components.Button>
|
|
266
|
+
{!_.isEmpty(this.state.feed) ? (
|
|
267
|
+
<>
|
|
268
|
+
{editable ? (
|
|
269
|
+
<Link to={`${values.routeAddFeed}/${this.state.feedId}`}>
|
|
270
|
+
<Components.Button inline style={{ marginRight: 25 }} buttonType="outlined" isActive={!isEditing} onClick={this.editFeed}>
|
|
271
|
+
Edit
|
|
272
|
+
</Components.Button>
|
|
273
|
+
</Link>
|
|
274
|
+
) : null}
|
|
275
|
+
{approvable ? (
|
|
276
|
+
<>
|
|
277
|
+
<Components.Button
|
|
278
|
+
inline
|
|
279
|
+
style={{ marginRight: 25 }}
|
|
280
|
+
buttonType="outlined"
|
|
281
|
+
isActive={!isEditing}
|
|
282
|
+
onClick={() => this.onReviewFeed(false)}
|
|
283
|
+
>
|
|
284
|
+
Reject
|
|
285
|
+
</Components.Button>
|
|
286
|
+
<Components.Button
|
|
287
|
+
inline
|
|
288
|
+
style={{ marginRight: 25 }}
|
|
289
|
+
buttonType="primary"
|
|
290
|
+
isActive={!isEditing}
|
|
291
|
+
onClick={() => this.onReviewFeed(true)}
|
|
292
|
+
>
|
|
293
|
+
Approve
|
|
294
|
+
</Components.Button>
|
|
295
|
+
</>
|
|
296
|
+
) : null}
|
|
297
|
+
</>
|
|
298
|
+
) : null}
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
render() {
|
|
304
|
+
return (
|
|
305
|
+
<Components.OverlayPage>
|
|
306
|
+
<Components.OverlayPageContents>
|
|
307
|
+
<Components.OverlayPageSection className="pageSectionWrapper--fixedPopupSize">{this.renderInner()}</Components.OverlayPageSection>
|
|
308
|
+
<Components.OverlayPageSection className="pageSectionWrapper--newPopupSide pageSectionWrapper--newPopupSide-fixedWidth">
|
|
309
|
+
{this.renderEditHistory()}
|
|
310
|
+
</Components.OverlayPageSection>
|
|
311
|
+
</Components.OverlayPageContents>
|
|
312
|
+
<Components.OverlayPageBottomButtons>{this.renderButtons()}</Components.OverlayPageBottomButtons>
|
|
313
|
+
</Components.OverlayPage>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const mapStateToProps = (state) => {
|
|
319
|
+
const { auth } = state;
|
|
320
|
+
return { auth };
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
export default connect(mapStateToProps, { feedsLoaded, removeFeedSubmission })(withRouter(Feed));
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { connect } from 'react-redux';
|
|
3
|
+
import { withRouter } from 'react-router';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import FontAwesome from 'react-fontawesome';
|
|
6
|
+
import Config, { PlussCore } from '../feature.config';
|
|
7
|
+
import { feedsLoaded, feedsSubmissionsLoaded } from '../actions';
|
|
8
|
+
import { feedActions } from '../apis';
|
|
9
|
+
import FeedList from '../components/FeedList';
|
|
10
|
+
import FeedSubmissions from '../components/FeedSubmissions';
|
|
11
|
+
import FeedTypes from '../components/FeedTypes';
|
|
12
|
+
import { values } from '../values.config';
|
|
13
|
+
|
|
14
|
+
const { Components, Session, Helper } = PlussCore;
|
|
15
|
+
|
|
16
|
+
class FeedHub extends Component {
|
|
17
|
+
constructor(props) {
|
|
18
|
+
super(props);
|
|
19
|
+
this.state = {
|
|
20
|
+
selectedSection: 'all',
|
|
21
|
+
loadingFeeds: false,
|
|
22
|
+
feeds: [],
|
|
23
|
+
feedSubmissions: [],
|
|
24
|
+
selectedUserId: '',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
UNSAFE_componentWillMount() {
|
|
29
|
+
this.updateProps(this.props);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
componentDidMount() {
|
|
33
|
+
this.getFeeds();
|
|
34
|
+
this.getSubmissions();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
38
|
+
if (!_.isEqual(this.props.feeds, nextProps.feeds) || !_.isEqual(this.props.submissions, nextProps.submissions))
|
|
39
|
+
this.updateProps(nextProps);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
updateProps(props) {
|
|
43
|
+
this.setState({ feeds: props.feeds, feedSubmissions: props.submissions }, this.setData);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setData = () => {
|
|
47
|
+
const feeds = [];
|
|
48
|
+
const feedSubmissions = [];
|
|
49
|
+
|
|
50
|
+
this.state.feeds.forEach((ev) => {
|
|
51
|
+
if (ev != null && !ev.deleted) feeds.push(ev);
|
|
52
|
+
});
|
|
53
|
+
this.state.feedSubmissions.forEach((ev) => {
|
|
54
|
+
if (ev != null && !ev.deleted) feedSubmissions.push(ev);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
this.setState({ feeds, feedSubmissions });
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
getFeeds = () => {
|
|
61
|
+
const { auth } = this.props;
|
|
62
|
+
this.setState({ loadingFeeds: true }, async () => {
|
|
63
|
+
try {
|
|
64
|
+
const res = await feedActions.getFeedsRecursive(auth.site);
|
|
65
|
+
if (!_.isEmpty(res) && res[0].site === auth.site) {
|
|
66
|
+
this.props.feedsLoaded(res);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error('getFeeds', error);
|
|
70
|
+
} finally {
|
|
71
|
+
this.setState({ loadingFeeds: false });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
getSubmissions = () => {
|
|
77
|
+
const { auth } = this.props;
|
|
78
|
+
if (!Session.validateAccess(auth.site, values.permissionFeedManagement, auth)) return;
|
|
79
|
+
|
|
80
|
+
this.setState({ loadingSubmissions: true }, async () => {
|
|
81
|
+
try {
|
|
82
|
+
const res = await feedActions.getFeedSubmissions(auth.site);
|
|
83
|
+
const submissions = res.data.Items;
|
|
84
|
+
// console.log('getSubmissions', submissions && submissions[0]);
|
|
85
|
+
if (!_.isEmpty(submissions) && submissions[0].site === auth.site) {
|
|
86
|
+
this.props.feedsSubmissionsLoaded(submissions);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.log('getSubmissions error', error);
|
|
90
|
+
} finally {
|
|
91
|
+
this.setState({ loadingSubmissions: false });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
canAddNew = (isClass) => {
|
|
97
|
+
const { auth } = this.props;
|
|
98
|
+
if (
|
|
99
|
+
Session.validateAccess(auth.site, values.permissionFeedPost, auth) ||
|
|
100
|
+
Session.validateAccess(auth.site, values.permissionFeedDraft, auth)
|
|
101
|
+
)
|
|
102
|
+
return isClass ? '' : true;
|
|
103
|
+
return isClass ? ' hub-sideContent-topButton--hide' : false;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
onAddNew = () => {
|
|
107
|
+
const { selectedUserId } = this.state;
|
|
108
|
+
if (this.canAddNew()) {
|
|
109
|
+
// Preselect user if filter set
|
|
110
|
+
this.props.history.push(`${values.routeAddFeed}${selectedUserId ? `?userId=${selectedUserId}` : ''}`);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
getSideBarSectionColour = (id) => (this.state.selectedSection === id ? { backgroundColor: '#fff' } : {});
|
|
115
|
+
|
|
116
|
+
renderStats = (stat, loading) => (loading ? <FontAwesome style={styles.spinner} name="spinner fa-pulse fa-fw" /> : stat);
|
|
117
|
+
|
|
118
|
+
renderLeftBar() {
|
|
119
|
+
const sectionItems = [];
|
|
120
|
+
|
|
121
|
+
if (this.canAddNew()) {
|
|
122
|
+
sectionItems.push({
|
|
123
|
+
type: 'newButton',
|
|
124
|
+
text: 'New Feed',
|
|
125
|
+
onClick: this.onAddNew,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
sectionItems.push({
|
|
130
|
+
type: 'navItem',
|
|
131
|
+
text: 'View Posts',
|
|
132
|
+
icon: 'eye',
|
|
133
|
+
isFontAwesome: true,
|
|
134
|
+
selected: this.state.selectedSection === 'all',
|
|
135
|
+
onClick: () => {
|
|
136
|
+
this.setState({ selectedSection: 'all' });
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (Session.validateAccess(this.props.auth.site, values.permissionFeedManagement, this.props.auth)) {
|
|
141
|
+
let submissionText = 'View Submissions';
|
|
142
|
+
if (!this.state.loadingSubmissions) {
|
|
143
|
+
submissionText = `View Submission${Helper.getPluralS(this.state.feedSubmissions.length)} (${this.state.feedSubmissions.length})`;
|
|
144
|
+
}
|
|
145
|
+
sectionItems.push({
|
|
146
|
+
type: 'navItem',
|
|
147
|
+
text: submissionText,
|
|
148
|
+
// icon: 'question-circle-o',
|
|
149
|
+
// isFontAwesome: true,
|
|
150
|
+
selected: this.state.selectedSection === 'submissions',
|
|
151
|
+
onClick: () => {
|
|
152
|
+
this.setState({ selectedSection: 'submissions' });
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (Session.validateAccess(this.props.auth.site, values.permissionFeedManagement, this.props.auth)) {
|
|
158
|
+
sectionItems.push({
|
|
159
|
+
type: 'navItem',
|
|
160
|
+
text: 'Feed Types',
|
|
161
|
+
// icon: 'maintenance2',
|
|
162
|
+
// isSVG: true,
|
|
163
|
+
selected: this.state.selectedSection === 'feedTypes',
|
|
164
|
+
onClick: () => {
|
|
165
|
+
this.setState({ selectedSection: 'feedTypes' });
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<Components.HubSidebar
|
|
172
|
+
sections={[
|
|
173
|
+
{
|
|
174
|
+
title: this.props.strings[`${values.featureKey}_textTitleRequests`] || values.textTitleFeeds,
|
|
175
|
+
items: sectionItems,
|
|
176
|
+
},
|
|
177
|
+
]}
|
|
178
|
+
// helpGuide={{
|
|
179
|
+
// text: `Help with Feeds`,
|
|
180
|
+
// url: Urls.HelpGuide.Feeds,
|
|
181
|
+
// }}
|
|
182
|
+
/>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
renderRight() {
|
|
187
|
+
const { selectedSection, feeds, feedSubmissions } = this.state;
|
|
188
|
+
|
|
189
|
+
if (selectedSection === 'submissions') {
|
|
190
|
+
return <FeedSubmissions source={feedSubmissions} />;
|
|
191
|
+
}
|
|
192
|
+
if (selectedSection === 'feedTypes') {
|
|
193
|
+
return <FeedTypes />;
|
|
194
|
+
}
|
|
195
|
+
return <FeedList source={feeds} onUserSelected={(userId) => this.setState({ selectedUserId: userId })} />;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
render() {
|
|
199
|
+
return (
|
|
200
|
+
<div className="hub-wrapperContainer">
|
|
201
|
+
{this.renderLeftBar()}
|
|
202
|
+
<div className="hub-headerContentWrapper">
|
|
203
|
+
<Components.Header />
|
|
204
|
+
<div className="hub-contentWrapper">{this.renderRight()}</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const styles = {
|
|
212
|
+
sideBarTitleSection: {
|
|
213
|
+
lineHeight: '40px',
|
|
214
|
+
marginTop: 30,
|
|
215
|
+
marginBottom: 30,
|
|
216
|
+
paddingLeft: 24,
|
|
217
|
+
paddingRight: 24,
|
|
218
|
+
},
|
|
219
|
+
sideBarSection: {
|
|
220
|
+
weight: '100%',
|
|
221
|
+
minWidth: 200,
|
|
222
|
+
padding: 32,
|
|
223
|
+
paddingLeft: 24,
|
|
224
|
+
cursor: 'pointer',
|
|
225
|
+
display: 'flex',
|
|
226
|
+
flexDirection: 'column',
|
|
227
|
+
justifyContent: 'center',
|
|
228
|
+
},
|
|
229
|
+
spinner: {
|
|
230
|
+
fontSize: 32,
|
|
231
|
+
color: Config.env.colourBrandingOff,
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const mapStateToProps = (state) => {
|
|
236
|
+
const { auth } = state;
|
|
237
|
+
return {
|
|
238
|
+
feeds: state[values.reducerKey].feeds,
|
|
239
|
+
submissions: state[values.reducerKey].submissions,
|
|
240
|
+
auth,
|
|
241
|
+
strings: (state.strings && state.strings.config) || {},
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export default connect(mapStateToProps, { feedsLoaded, feedsSubmissionsLoaded })(withRouter(FeedHub));
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const values = {
|
|
2
|
+
featureKey: 'feeds',
|
|
3
|
+
aliases: [],
|
|
4
|
+
serviceKey: 'feeds',
|
|
5
|
+
reducerKey: 'feeds',
|
|
6
|
+
analyticsKey: 'feeds',
|
|
7
|
+
actionFeedsLoading: 'FEEDS_LOADING',
|
|
8
|
+
actionFeedsLoaded: 'FEEDS_LOADED',
|
|
9
|
+
actionFeedRemoved: 'FEEDS_REMOVED',
|
|
10
|
+
actionFeedsSubmissionsLoaded: 'FEEDS_SUBMISSIONS_LOADED',
|
|
11
|
+
actionFeedsSubmissionsRemoved: 'FEEDS_SUBMISSIONS_REMOVED',
|
|
12
|
+
actionFeedTypeLoaded: 'FEED_TYPES_LOADED',
|
|
13
|
+
permissionFeedManagement: 'feedManagement',
|
|
14
|
+
permissionFeedPost: 'feedPost',
|
|
15
|
+
permissionFeedDraft: 'feedDraft',
|
|
16
|
+
routeHub: '/feedHub',
|
|
17
|
+
routeAddFeed: '/feedHub/feed',
|
|
18
|
+
routeFeedDetails: '/feedHub/feedDetails',
|
|
19
|
+
routeFeedTypes: '/feedTypes',
|
|
20
|
+
screenFeedHub: 'FeedHub',
|
|
21
|
+
screenAddFeed: 'AddFeed',
|
|
22
|
+
screenFeed: 'Feed',
|
|
23
|
+
screenFeedTypes: 'FeedTypes',
|
|
24
|
+
svgPathGridIcon:
|
|
25
|
+
'M5 4.5C4.17157 4.5 3.5 5.17157 3.5 6C3.5 6.82843 4.17157 7.5 5 7.5H14C14.8284 7.5 15.5 6.82843 15.5 6C15.5 5.17157 14.8284 4.5 14 4.5H5ZM5 11.5C4.17157 11.5 3.5 12.1716 3.5 13C3.5 13.8284 4.17157 14.5 5 14.5H21C21.8284 14.5 22.5 13.8284 22.5 13C22.5 12.1716 21.8284 11.5 21 11.5H5ZM5 18.5C4.17157 18.5 3.5 19.1716 3.5 20C3.5 20.8284 4.17157 21.5 5 21.5H17C17.8284 21.5 18.5 20.8284 18.5 20C18.5 19.1716 17.8284 18.5 17 18.5H5Z',
|
|
26
|
+
svgPathGridIconViewBox: '0 0 26 26',
|
|
27
|
+
menuOrder: 20,
|
|
28
|
+
textEmptyDescription: 'allows your users to submit feed posts.',
|
|
29
|
+
textEmptyExample: '',
|
|
30
|
+
textAreYouSureYouWantToDelete: 'Are you sure you want to delete the post?',
|
|
31
|
+
textAreYouSureYouWantToApprove: 'Are you sure you want to approve the post?',
|
|
32
|
+
textAreYouSureYouWantToReject: 'Are you sure you want to reject the post?',
|
|
33
|
+
textSingularName: 'Resident Feed',
|
|
34
|
+
textEmptyState: 'Your Resident Feeds will show here',
|
|
35
|
+
textTitleFeeds: 'Care Feeds',
|
|
36
|
+
textMenuTitle: 'Care Feeds',
|
|
37
|
+
textPermissionFeedManagement: 'Resident Feed Management',
|
|
38
|
+
textPermissionFeedPost: 'Post Resident Feed',
|
|
39
|
+
textPermissionFeedDraft: 'Draft Resident Feed',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { values };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const values = {
|
|
2
|
+
featureKey: 'feeds',
|
|
3
|
+
aliases: [],
|
|
4
|
+
serviceKey: 'feeds',
|
|
5
|
+
reducerKey: 'feeds',
|
|
6
|
+
analyticsKey: 'feeds',
|
|
7
|
+
actionFeedsLoading: 'FEEDS_LOADING',
|
|
8
|
+
actionFeedsLoaded: 'FEEDS_LOADED',
|
|
9
|
+
actionFeedRemoved: 'FEEDS_REMOVED',
|
|
10
|
+
actionFeedsSubmissionsLoaded: 'FEEDS_SUBMISSIONS_LOADED',
|
|
11
|
+
actionFeedsSubmissionsRemoved: 'FEEDS_SUBMISSIONS_REMOVED',
|
|
12
|
+
actionFeedTypeLoaded: 'FEED_TYPES_LOADED',
|
|
13
|
+
permissionFeedManagement: 'feedManagement',
|
|
14
|
+
permissionFeedPost: 'feedPost',
|
|
15
|
+
permissionFeedDraft: 'feedDraft',
|
|
16
|
+
routeHub: '/feedHub',
|
|
17
|
+
routeAddFeed: '/feedHub/feed',
|
|
18
|
+
routeFeedDetails: '/feedHub/feedDetails',
|
|
19
|
+
routeFeedTypes: '/feedTypes',
|
|
20
|
+
screenFeedHub: 'FeedHub',
|
|
21
|
+
screenAddFeed: 'AddFeed',
|
|
22
|
+
screenFeed: 'Feed',
|
|
23
|
+
screenFeedTypes: 'FeedTypes',
|
|
24
|
+
svgPathGridIcon:
|
|
25
|
+
'M5 4.5C4.17157 4.5 3.5 5.17157 3.5 6C3.5 6.82843 4.17157 7.5 5 7.5H14C14.8284 7.5 15.5 6.82843 15.5 6C15.5 5.17157 14.8284 4.5 14 4.5H5ZM5 11.5C4.17157 11.5 3.5 12.1716 3.5 13C3.5 13.8284 4.17157 14.5 5 14.5H21C21.8284 14.5 22.5 13.8284 22.5 13C22.5 12.1716 21.8284 11.5 21 11.5H5ZM5 18.5C4.17157 18.5 3.5 19.1716 3.5 20C3.5 20.8284 4.17157 21.5 5 21.5H17C17.8284 21.5 18.5 20.8284 18.5 20C18.5 19.1716 17.8284 18.5 17 18.5H5Z',
|
|
26
|
+
svgPathGridIconViewBox: '0 0 26 26',
|
|
27
|
+
menuOrder: 20,
|
|
28
|
+
textEmptyDescription: 'allows your users to submit feed posts.',
|
|
29
|
+
textEmptyExample: '',
|
|
30
|
+
textAreYouSureYouWantToDelete: 'Are you sure you want to delete the post?',
|
|
31
|
+
textAreYouSureYouWantToApprove: 'Are you sure you want to approve the post?',
|
|
32
|
+
textAreYouSureYouWantToReject: 'Are you sure you want to reject the post?',
|
|
33
|
+
textSingularName: 'Resident Feed',
|
|
34
|
+
textEmptyState: 'Your Resident Feeds will show here',
|
|
35
|
+
textTitleFeeds: 'Care Feeds',
|
|
36
|
+
textMenuTitle: 'Care Feeds',
|
|
37
|
+
textPermissionFeedManagement: 'Resident Feed Management',
|
|
38
|
+
textPermissionFeedPost: 'Post Resident Feed',
|
|
39
|
+
textPermissionFeedDraft: 'Draft Resident Feed',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { values };
|