Skip to content

Commit 9d049dc

Browse files
timeline final fix
1 parent a248c7d commit 9d049dc

File tree

11 files changed

+106
-57
lines changed

11 files changed

+106
-57
lines changed

config/default.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,5 +460,6 @@ module.exports = {
460460
PLATFORMUI_SITE_URL: 'https://platform-ui.topcoder-dev.com',
461461
TIMELINE: {
462462
REJECTION_EVENT_REASONS: ['Duplicate Event'],
463+
ALLOWED_FILETYPES: ['image/jpeg', 'image/png', 'video/mp4', 'video/x-msvideo', 'video/webm'],
463464
},
464465
};

src/shared/components/GUIKit/PhotoVideoPicker/index.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ function PhotoVideoPicker({
3131
]);
3232
}}
3333
{...options}
34+
accept={['image/jpeg', 'image/png', 'video/mp4', 'video/x-msvideo', 'video/webm']}
35+
maxFiles={3}
3436
>
3537
{({ getRootProps, getInputProps }) => (
3638
<div styleName="wrapper-container">
@@ -60,7 +62,7 @@ function PhotoVideoPicker({
6062
) : null
6163
}
6264
{
63-
file.length < 3 ? (
65+
file.length <= 3 ? (
6466
<React.Fragment>
6567

6668
<section

src/shared/containers/timeline-wall/index.jsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function TimelineWallContainer(props) {
3434
getAvatar,
3535
userAvatars,
3636
pendingApprovals,
37+
uploading,
3738
} = props;
3839

3940
const role = 'Admin User';
@@ -75,6 +76,15 @@ function TimelineWallContainer(props) {
7576
}
7677
}, [pendingApprovals]);
7778

79+
useEffect(() => {
80+
const target = document.getElementById(`${selectedFilterValue.year}-${selectedFilterValue.month}`);
81+
if (target) {
82+
target.scrollIntoView({ behavior: 'smooth' }, true);
83+
} else {
84+
window.scrollTo({ top: 0, behavior: 'smooth' });
85+
}
86+
}, [selectedFilterValue]);
87+
7888

7989
const deleteEvent = (id) => {
8090
deleteEventById(authToken, id, () => {
@@ -96,7 +106,7 @@ function TimelineWallContainer(props) {
96106

97107
return (
98108
<div styleName="container">
99-
<div styleName="header">
109+
<div styleName={isAdmin ? 'header header-admin' : 'header'}>
100110
<img src={TopBanner} alt="top-banner" styleName="header-bg hide-mobile" />
101111
<img src={TopBannerMobile} alt="top-banner" styleName="header-bg hide-desktop show-mobile" />
102112

@@ -153,8 +163,12 @@ function TimelineWallContainer(props) {
153163
createNewEvent={(body) => {
154164
createNewEvent(authToken, body);
155165
}}
166+
onDoneAddEvent={() => {
167+
getTimelineEvents();
168+
}}
156169
getAvatar={getAvatar}
157170
userAvatars={userAvatars}
171+
uploading={uploading}
158172
/>
159173
<React.Fragment>
160174
{
@@ -185,6 +199,7 @@ TimelineWallContainer.defaultProps = {
185199
auth: null,
186200
isAdmin: false,
187201
loading: false,
202+
uploading: false,
188203
events: [],
189204
userAvatars: {},
190205
pendingApprovals: [],
@@ -197,6 +212,7 @@ TimelineWallContainer.propTypes = {
197212
auth: PT.shape(),
198213
isAdmin: PT.bool,
199214
loading: PT.bool,
215+
uploading: PT.bool,
200216
events: PT.arrayOf(PT.shape()),
201217
loadUserDetails: PT.func.isRequired,
202218
createNewEvent: PT.func.isRequired,
@@ -213,6 +229,7 @@ const mapStateToProps = state => ({
213229
},
214230
isAdmin: state.timelineWall.isAdmin,
215231
loading: state.timelineWall.loading,
232+
uploading: state.timelineWall.uploading,
216233
events: state.timelineWall.events,
217234
userAvatars: state.timelineWall.userAvatars,
218235
pendingApprovals: state.timelineWall.pendingApprovals,

src/shared/containers/timeline-wall/modal-event-add/index.jsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import React from 'react';
22
import PT from 'prop-types';
33
import { Modal } from 'topcoder-react-ui-kit';
44
import IconCloseGreen from 'assets/images/icon-close-green.svg';
5+
import LoadingIndicator from 'components/LoadingIndicator';
56

67
import style from './styles.scss';
78

8-
function ModalEventAdd({ onClose, isAdmin }) {
9+
function ModalEventAdd({ onClose, isAdmin, uploading }) {
910
return (
1011
<Modal
1112
theme={{ container: style.container, overlay: style.overlay }}
@@ -15,12 +16,18 @@ function ModalEventAdd({ onClose, isAdmin }) {
1516
<span styleName="text-title">Confirmation</span>
1617
<button styleName="btn-close" onClick={onClose} type="button"><IconCloseGreen /></button>
1718
</div>
18-
<span styleName="text-description">
19-
{
20-
isAdmin ? 'Thank you! Your event was submitted for review. You’ll receive an email once the review is completed'
21-
: 'Thank you! Your event was added to the Timeline Wall.'
22-
}
23-
</span>
19+
{
20+
uploading ? (
21+
<LoadingIndicator />
22+
) : (
23+
<span styleName="text-description">
24+
{
25+
!isAdmin ? 'Thank you! Your event was submitted for review. You’ll receive an email once the review is completed'
26+
: 'Thank you! Your event was added to the Timeline Wall.'
27+
}
28+
</span>
29+
)
30+
}
2431
<div styleName="separator" />
2532
<div styleName="bottom">
2633
<button
@@ -34,6 +41,7 @@ function ModalEventAdd({ onClose, isAdmin }) {
3441
onClick={onClose}
3542
styleName="btn-primary"
3643
type="button"
44+
disabled={uploading}
3745
>OK
3846
</button>
3947
</div>
@@ -47,6 +55,7 @@ function ModalEventAdd({ onClose, isAdmin }) {
4755
ModalEventAdd.defaultProps = {
4856
onClose: () => { },
4957
isAdmin: false,
58+
uploading: false,
5059
};
5160

5261
/**
@@ -55,6 +64,7 @@ ModalEventAdd.defaultProps = {
5564
ModalEventAdd.propTypes = {
5665
onClose: PT.func,
5766
isAdmin: PT.bool,
67+
uploading: PT.bool,
5868
};
5969

6070
export default ModalEventAdd;

src/shared/containers/timeline-wall/modal-photo-viewer/index.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import PhotoVideoItem from 'components/GUIKit/PhotoVideoItem';
1111
import style from './styles.scss';
1212

1313
function ModalPhotoViewer({ onClose, selectedPhoto, photos }) {
14+
const newPhotos = photos.map((photo, index) => ({ ...photo, id: index }));
1415
const [localSelectedPhoto, setLocalSelectedPhoto] = useState(selectedPhoto);
1516
const selectedPhotoObject = useMemo(
16-
() => _.find(photos, { id: localSelectedPhoto }), [localSelectedPhoto],
17+
() => _.find(newPhotos, { id: localSelectedPhoto }), [localSelectedPhoto],
1718
);
1819

1920
return (

src/shared/containers/timeline-wall/styles.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import '~styles/mixins';
1+
@import "~styles/mixins";
22

33
.container {
44
display: flex;
@@ -19,6 +19,10 @@
1919
}
2020
}
2121

22+
.header-admin {
23+
min-height: 207px;
24+
}
25+
2226
.header-content-1 {
2327
font-family: BarlowCondensed, sans-serif;
2428
font-weight: 500;

src/shared/containers/timeline-wall/timeline-events/add-event/index.jsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ import FormField from 'components/Settings/FormField';
1010
import FormInputDatePicker from 'components/Settings/FormInputDatePicker';
1111
import FormInputTextArea from 'components/Settings/FormInputTextArea';
1212
import PhotoVideoPicker from 'components/GUIKit/PhotoVideoPicker';
13+
import { config } from 'topcoder-react-utils';
1314
import IconCloseGreen from 'assets/images/icon-close-green.svg';
1415
import IconCloseBlack from 'assets/images/tc-edu/icon-close-big.svg';
1516
import ModalEventAdd from '../../modal-event-add';
1617

1718
import style from './styles.scss';
1819

1920
function AddEvents({
20-
className, isAuthenticated, createNewEvent, isAdmin,
21+
className, isAuthenticated, createNewEvent, isAdmin, onDoneAddEvent, uploading,
2122
}) {
2223
const [formData, setFormData] = useState({
2324
eventName: '',
@@ -31,13 +32,7 @@ function AddEvents({
3132
&& !!formData.description, [formData]);
3233

3334
const submitEvent = () => {
34-
const form = new FormData();
35-
form.append('title', formData.eventName);
36-
form.append('description', formData.description);
37-
form.append('eventDate', formData.date);
38-
form.append('mediaFiles', formData.files || []);
39-
40-
createNewEvent(form);
35+
createNewEvent(formData);
4136

4237
setFormData({
4338
eventName: '',
@@ -157,6 +152,10 @@ function AddEvents({
157152
infoText={'Drag & drop your photo or video here\nYou can upload only up to 3 photos/videos'}
158153
infoTextMobile="Drag & drop your photo or video here"
159154
btnText="BROWSE"
155+
options={{
156+
accept: config.TIMELINE.ALLOWED_FILETYPES || [],
157+
maxFiles: 3,
158+
}}
160159
/>
161160
</div>
162161

@@ -190,8 +189,14 @@ function AddEvents({
190189
{
191190
showModal ? (
192191
<ModalEventAdd
193-
onClose={() => setShowModal(false)}
192+
onClose={() => {
193+
setShowModal(false);
194+
if (isAdmin) {
195+
onDoneAddEvent();
196+
}
197+
}}
194198
isAdmin={isAdmin}
199+
uploading={uploading}
195200
/>
196201
) : null
197202
}
@@ -206,6 +211,7 @@ AddEvents.defaultProps = {
206211
className: '',
207212
isAuthenticated: false,
208213
isAdmin: false,
214+
uploading: false,
209215
};
210216

211217
/**
@@ -216,6 +222,8 @@ AddEvents.propTypes = {
216222
isAuthenticated: PT.bool,
217223
createNewEvent: PT.func.isRequired,
218224
isAdmin: PT.bool,
225+
onDoneAddEvent: PT.func.isRequired,
226+
uploading: PT.bool,
219227
};
220228

221229
export default AddEvents;

src/shared/containers/timeline-wall/timeline-events/events/event-item/index.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function EventItem({
3333
'color-red': eventItem.color === 'red',
3434
'color-purple': eventItem.color === 'purple',
3535
})}
36+
id={moment(eventItem.eventDate).format('YYYY-MM')}
3637
>
3738
{isLeft ? null : (<div styleName="dot dot-left" />)}
3839
{isLeft ? null : (<IconTooltipLeft styleName="tooltip-indicator" />)}
@@ -105,7 +106,7 @@ function EventItem({
105106
onClose={() => {
106107
setShowModalPhoto(false);
107108
}}
108-
photos={eventItem.media}
109+
photos={eventItem.mediaFiles}
109110
/>
110111
) : null}
111112

src/shared/containers/timeline-wall/timeline-events/index.jsx

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React from 'react';
22
import PT from 'prop-types';
3-
import moment from 'moment';
4-
import _ from 'lodash';
53
import cn from 'classnames';
64
import AddEvent from './add-event';
75
import Events from './events';
@@ -22,41 +20,23 @@ function TimelineEvents({
2220
createNewEvent,
2321
getAvatar,
2422
userAvatars,
23+
onDoneAddEvent,
24+
uploading,
2525
}) {
26-
const [localEvents, setLocalEvents] = useState([]);
27-
28-
useEffect(() => {
29-
setLocalEvents(_.filter(events, (event) => {
30-
const eventDate = moment(event.eventDate);
31-
if (!selectedFilterValue.year) {
32-
return true;
33-
}
34-
if (eventDate.year() !== selectedFilterValue.year) {
35-
return false;
36-
}
37-
if (selectedFilterValue.month < 0) {
38-
return true;
39-
}
40-
if (eventDate.month() !== selectedFilterValue.month) {
41-
return false;
42-
}
43-
44-
return true;
45-
}));
46-
}, [events, selectedFilterValue]);
47-
4826
return (
4927
<div className={className} styleName="container">
5028
<div styleName="left-content">
5129
<AddEvent
52-
events={localEvents}
30+
events={events}
5331
isAuthenticated={isAuthenticated}
5432
createNewEvent={createNewEvent}
5533
isAdmin={isAdmin}
34+
onDoneAddEvent={onDoneAddEvent}
35+
uploading={uploading}
5636
/>
57-
{localEvents.length ? (
37+
{events.length ? (
5838
<Events
59-
events={localEvents}
39+
events={events}
6040
isAdmin={isAdmin}
6141
isAuthenticated={isAuthenticated}
6242
removeEvent={(event) => {
@@ -67,15 +47,15 @@ function TimelineEvents({
6747
/>
6848
)
6949
: null}
70-
{!localEvents.length && !!events.length && selectedFilterValue.month < 0 ? (
50+
{!events.length && !!events.length && selectedFilterValue.month < 0 ? (
7151
<span styleName="text-empty-result">No events have been added for this year. Be the first who adds one.</span>
7252
)
7353
: null}
74-
{!localEvents.length && !!events.length && selectedFilterValue.month >= 0 ? (
54+
{!events.length && !!events.length && selectedFilterValue.month >= 0 ? (
7555
<span styleName="text-empty-result">No events have been added for this month. Be the first who adds one.</span>
7656
)
7757
: null}
78-
{!localEvents.length && !events.length ? (
58+
{!events.length && !events.length ? (
7959
<span styleName="text-empty-result">No events have been added. Be the first who adds one.</span>
8060
)
8161
: null}
@@ -111,6 +91,7 @@ TimelineEvents.defaultProps = {
11191
isAuthenticated: false,
11292
isAdmin: false,
11393
userAvatars: {},
94+
uploading: false,
11495
};
11596

11697
/**
@@ -128,7 +109,9 @@ TimelineEvents.propTypes = {
128109
isAdmin: PT.bool,
129110
createNewEvent: PT.func.isRequired,
130111
getAvatar: PT.func.isRequired,
112+
onDoneAddEvent: PT.func.isRequired,
131113
userAvatars: PT.shape(),
114+
uploading: PT.bool,
132115
};
133116

134117
export default TimelineEvents;

0 commit comments

Comments
 (0)