Skip to content

Commit 07446aa

Browse files
Merge pull request #5 from appirio-tech/cf16
Cf16
2 parents dfc0e69 + b61abb4 commit 07446aa

File tree

25 files changed

+5448
-5330
lines changed

25 files changed

+5448
-5330
lines changed

package-lock.json

Lines changed: 5173 additions & 5177 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/ActionCard/Comment.jsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ class Comment extends React.Component {
5858
}
5959

6060
render() {
61-
const {message, author, date, edited, children, noInfo, self, isSaving, hasError, readonly, allMembers, canDelete, projectMembers} = this.props
62-
const messageAnchor = `comment-${message.id}`
61+
const {message, author, date, edited, children, noInfo, self, isSaving, hasError, readonly, allMembers, canDelete, projectMembers, commentAnchorPrefix} = this.props
62+
const messageAnchor = commentAnchorPrefix + message.id
6363
const messageLink = window.location.pathname.substr(0, window.location.pathname.indexOf('#')) + `#${messageAnchor}`
6464
const authorName = author ? (author.firstName + ' ' + author.lastName) : 'Connect user'
6565
const avatarUrl = _.get(author, 'photoURL', null)
@@ -141,6 +141,10 @@ class Comment extends React.Component {
141141
}
142142
}
143143

144+
Comment.defaultProps = {
145+
commentAnchorPrefix: 'comment-',
146+
}
147+
144148
Comment.propTypes = {
145149
/**
146150
* The author (user object)
@@ -204,6 +208,10 @@ Comment.propTypes = {
204208
* The can delete flag
205209
*/
206210
canDelete: PropTypes.bool,
211+
/**
212+
* The prefix for comment anchor
213+
*/
214+
commentAnchorPrefix: PropTypes.string,
207215
}
208216

209217
export default Comment

src/components/Feed/Feed.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class Feed extends React.Component {
8686
id, user, currentUser, topicMessage, totalComments, hasMoreComments, onLoadMoreComments, isLoadingComments,
8787
allowComments, comments, children, onNewCommentChange, onAddNewComment, isAddingComment, onSaveMessageChange,
8888
onEditMessage, onSaveMessage, isSavingTopic, onDeleteMessage, onDeleteTopic, isDeletingTopic, error, allMembers,
89-
onEnterFullscreenClick, onExitFullscreenClick, isFullScreen, commentId, projectMembers
89+
onEnterFullscreenClick, onExitFullscreenClick, isFullScreen, commentId, projectMembers, commentAnchorPrefix
9090
} = this.props
9191
const { editTopicMode, headerHeight } = this.state
9292
let authorName = user ? user.firstName : 'Unknown'
@@ -182,6 +182,7 @@ class Feed extends React.Component {
182182
headerHeight={headerHeight}
183183
commentId={commentId}
184184
error={error}
185+
commentAnchorPrefix={commentAnchorPrefix}
185186
/>
186187
{children}
187188
{isDeletingTopic &&
@@ -223,6 +224,7 @@ Feed.propTypes = {
223224
isSavingTopic: PropTypes.bool,
224225
onEnterFullscreenClick: PropTypes.func,
225226
isFullScreen: PropTypes.bool,
227+
commentAnchorPrefix: PropTypes.string,
226228
}
227229

228230
export default Feed

src/components/Feed/FeedComments.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ class FeedComments extends React.Component {
179179
const {
180180
comments, currentUser, onLoadMoreComments, isLoadingComments, hasMoreComments, onAddNewComment,
181181
onNewCommentChange, error, avatarUrl, isAddingComment, allowComments, onSaveMessage, onDeleteMessage, allMembers,
182-
totalComments, isFullScreen, headerHeight, projectMembers
182+
totalComments, isFullScreen, headerHeight, projectMembers, commentAnchorPrefix
183183
} = this.props
184184
const { isNewCommentMobileOpen, stickyRowNext, stickyRowPrev } = this.state
185185
let authorName = currentUser.firstName
@@ -322,6 +322,7 @@ class FeedComments extends React.Component {
322322
projectMembers={projectMembers}
323323
noInfo={item.noInfo}
324324
canDelete={idx !== 0}
325+
commentAnchorPrefix={commentAnchorPrefix}
325326
>
326327
<div dangerouslySetInnerHTML={{__html: markdownToHTML(itemContent)}} />
327328
</Comment>
@@ -435,10 +436,11 @@ class FeedComments extends React.Component {
435436
}
436437
}
437438
FeedComments.defaultProps = {
438-
comments: []
439+
comments: [],
439440
}
440441
FeedComments.propTypes = {
441-
comments: PropTypes.array
442+
comments: PropTypes.array,
443+
commentAnchorPrefix: PropTypes.string,
442444
}
443445

444446
export default FeedComments

src/components/LinksMenu/FileLinksMenu.jsx

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33
import {Link} from 'react-router-dom'
4+
import * as filepicker from 'filestack-js'
5+
46
import './LinksMenu.scss'
57
import Panel from '../Panel/Panel'
6-
import AddFiles from '../FileList/AddFiles'
78
import AddFilePermission from '../FileList/AddFilePermissions'
89
import DeleteLinkModal from './DeleteLinkModal'
910
import EditFileAttachment from './EditFileAttachment'
@@ -13,10 +14,15 @@ import cn from 'classnames'
1314
import BtnRemove from '../../assets/icons/ui-16px-1_trash-simple.svg'
1415
import BtnEdit from '../../assets/icons/icon-edit.svg'
1516
import _ from 'lodash'
16-
import Modal from '../Modal/Modal'
17+
18+
import {
19+
FILE_PICKER_API_KEY,
20+
FILE_PICKER_FROM_SOURCES,
21+
FILE_PICKER_CNAME,
22+
FILE_PICKER_SUBMISSION_CONTAINER_NAME
23+
} from '../../config/constants'
1724

1825
const FileLinksMenu = ({
19-
canAdd,
2026
canDelete,
2127
noDots,
2228
isAddingNewLink,
@@ -45,6 +51,11 @@ const FileLinksMenu = ({
4551
projectMembers,
4652
loggedInUser,
4753
}) => {
54+
55+
const fileUploadClient = filepicker.init(FILE_PICKER_API_KEY, {
56+
cname: FILE_PICKER_CNAME
57+
})
58+
4859
const renderLink = (link) => {
4960
if (link.onClick) {
5061
return (
@@ -95,19 +106,41 @@ const FileLinksMenu = ({
95106
})
96107
}
97108

98-
const onClose = () => {
99-
onAddingNewLink(false)
109+
const openFileUpload = () => {
110+
if (fileUploadClient) {
111+
const picker = fileUploadClient.picker({
112+
storeTo: {
113+
location: 's3',
114+
path: attachmentsStorePath,
115+
container: FILE_PICKER_SUBMISSION_CONTAINER_NAME,
116+
region: 'us-east-1'
117+
},
118+
maxFiles: 4,
119+
fromSources: FILE_PICKER_FROM_SOURCES,
120+
uploadInBackground: false,
121+
onFileUploadFinished: (files) => {
122+
processUploadedFiles(files, category)
123+
},
124+
onOpen: () => {
125+
onAddingNewLink(true)
126+
},
127+
onClose: () => {
128+
onAddingNewLink(false)
129+
}
130+
})
131+
132+
picker.open()
133+
}
100134
}
101135

102136
return (
103137
<MobileExpandable title={`${title} (${links.length})`}>
104138
<Panel className={cn({'modal-active': (isAddingNewLink || linkToDelete >= 0)}, 'panel-links-container')}>
105-
{canAdd && !isAddingNewLink && onAddingNewLink &&
106-
<Panel.AddBtn onClick={() => onAddingNewLink(true)}>Upload File</Panel.AddBtn>}
139+
<Panel.AddBtn onClick={openFileUpload}>Upload File</Panel.AddBtn>
107140

108-
{!isAddingNewLink && <Panel.Title>
141+
<Panel.Title>
109142
{title} ({links.length})
110-
</Panel.Title>}
143+
</Panel.Title>
111144

112145
{(isAddingNewLink || linkToDelete >= 0) && <div className="modal-overlay"/>}
113146

@@ -123,22 +156,6 @@ const FileLinksMenu = ({
123156
/>
124157
}
125158

126-
{isAddingNewLink &&
127-
<Modal onClose={onClose}>
128-
<Modal.Title>
129-
UPLOAD A FILE
130-
</Modal.Title>
131-
{
132-
pendingAttachments &&
133-
<AddFilePermission />
134-
}
135-
<AddFiles successHandler={processUploadedFiles.bind(this)}
136-
storePath={attachmentsStorePath}
137-
category={category}
138-
/>
139-
</Modal>
140-
}
141-
142159
<div
143160
className={cn('panel-links', {
144161
'panel-links-nodots': noDots,
@@ -156,7 +173,7 @@ const FileLinksMenu = ({
156173
const handleDeleteClick = () => onDeleteIntent(idx)
157174

158175
const onEditConfirm = (title, allowedUsers) => {
159-
onEdit(idx, title, allowedUsers)
176+
onEdit(link.id, title, allowedUsers)
160177
onEditIntent(-1)
161178
}
162179
const onEditCancel = () => onEditIntent(-1)
@@ -223,9 +240,9 @@ const FileLinksMenu = ({
223240
<a href="javascript:" onClick={() => onChangeLimit(10000)}>{moreText}</a>
224241
</div>}
225242
</div>
226-
{canAdd && !isAddingNewLink && (
243+
{!isAddingNewLink && (
227244
<div className="add-link-mobile">
228-
<button className="tc-btn tc-btn-secondary tc-btn-md" onClick={() => onAddingNewLink(true)}>Add New Link
245+
<button className="tc-btn tc-btn-secondary tc-btn-md" onClick={() => onAddingNewLink(true)}>Upload File
229246
</button>
230247
</div>
231248
)}
@@ -235,7 +252,6 @@ const FileLinksMenu = ({
235252
}
236253

237254
FileLinksMenu.propTypes = {
238-
canAdd: PropTypes.bool,
239255
canDelete: PropTypes.bool,
240256
canEdit: PropTypes.bool,
241257
noDots: PropTypes.bool,

src/components/TeamManagement/AutocompleteInputContainer.jsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ class AutocompleteInputContainer extends React.Component {
1414
}
1515

1616
onInputChange(inputValue) {
17+
const indexOfSpace = inputValue.indexOf(' ')
18+
const indexOfSemiColon = inputValue.indexOf(';')
19+
20+
// if user enter only ' ' or ';' we should clean it to not allow
21+
if (indexOfSpace === 0 || indexOfSemiColon === 0 ) {
22+
return ''
23+
}
24+
25+
if (indexOfSpace >= 1 || indexOfSemiColon >= 1 ) {
26+
inputValue = inputValue.substring(0, inputValue.length -1 )
27+
this.onUpdate([...this.props.selectedMembers, {label: inputValue, value: inputValue}])
28+
this.props.onClearUserSuggestions()
29+
// this is return empty to nullify inputValue post processing
30+
return ''
31+
}
32+
1733
if (inputValue.length >= AUTOCOMPLETE_TRIGGER_LENGTH) {
1834
this.props.onLoadUserSuggestions(inputValue)
1935
} else {

src/components/TeamManagement/ProjectManagementDialog.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ProjectManagementDialog extends React.Component {
2424

2525
if (processingInvites && !nextProps.processingInvites ) {
2626
const notInvitedSelectedMembers = _.reject(selectedMembers, (selectedMember) => (
27-
this.isSelectedMemberAlreadyInvited(nextProps.invites, selectedMember)
27+
this.isSelectedMemberAlreadyInvited(nextProps.projectTeamInvites, selectedMember)
2828
))
2929

3030
this.props.onSelectedMembersUpdate(notInvitedSelectedMembers)
@@ -36,10 +36,12 @@ class ProjectManagementDialog extends React.Component {
3636
}
3737

3838
onChange(selectedMembers) {
39-
const { invites } = this.props
39+
const { projectTeamInvites, members, topcoderTeamInvites } = this.props
4040

4141
const present = _.some(selectedMembers, (selectedMember) => (
42-
this.isSelectedMemberAlreadyInvited(invites, selectedMember)
42+
this.isSelectedMemberAlreadyInvited(members, selectedMember)
43+
|| this.isSelectedMemberAlreadyInvited(topcoderTeamInvites, selectedMember)
44+
|| this.isSelectedMemberAlreadyInvited(projectTeamInvites, selectedMember)
4345
))
4446

4547
this.setState({
@@ -51,8 +53,8 @@ class ProjectManagementDialog extends React.Component {
5153
this.props.onSelectedMembersUpdate(selectedMembers)
5254
}
5355

54-
isSelectedMemberAlreadyInvited(invites = [], selectedMember) {
55-
return !!invites.find((invite) => (
56+
isSelectedMemberAlreadyInvited(projectTeamInvites = [], selectedMember) {
57+
return !!projectTeamInvites.find((invite) => (
5658
(invite.email && invite.email === selectedMember.label) ||
5759
(invite.userId && this.resolveUserHandle(invite.userId) === selectedMember.label)
5860
))
@@ -94,7 +96,7 @@ class ProjectManagementDialog extends React.Component {
9496
render() {
9597
const {
9698
members, currentUser, isMember, removeMember, removeInvite,
97-
onCancel, invites = [], selectedMembers, processingInvites,
99+
onCancel, projectTeamInvites = [], selectedMembers, processingInvites,
98100
} = this.props
99101
const showRemove = currentUser.isAdmin || (!currentUser.isCopilot && isMember)
100102
let i = 0
@@ -151,7 +153,7 @@ class ProjectManagementDialog extends React.Component {
151153
</div>
152154
)
153155
}))}
154-
{(invites.map((invite) => {
156+
{(projectTeamInvites.map((invite) => {
155157
const remove = () => {
156158
removeInvite(invite)
157159
}
@@ -221,7 +223,8 @@ class ProjectManagementDialog extends React.Component {
221223
}
222224

223225
ProjectManagementDialog.defaultProps = {
224-
invites: [],
226+
projectTeamInvites: [],
227+
topcoderTeamInvites: [],
225228
members: []
226229
}
227230

@@ -233,7 +236,8 @@ ProjectManagementDialog.propTypes = {
233236
isMember: PT.bool.isRequired,
234237
onCancel: PT.func.isRequired,
235238
removeMember: PT.func.isRequired,
236-
invites: PT.arrayOf(PT.object),
239+
projectTeamInvites: PT.arrayOf(PT.object),
240+
topcoderTeamInvites: PT.arrayOf(PT.object),
237241
sendInvite: PT.func.isRequired,
238242
removeInvite: PT.func.isRequired,
239243
onSelectedMembersUpdate: PT.func.isRequired,

src/components/TeamManagement/TeamManagement.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ class TeamManagement extends React.Component {
198198
isMember={!!currentMember}
199199
onCancel={onClickCancel}
200200
removeMember={removeMember}
201-
invites={projectTeamInvites}
201+
projectTeamInvites={projectTeamInvites}
202+
topcoderTeamInvites={topcoderTeamInvites}
202203
sendInvite={onProjectInviteSend}
203204
removeInvite={removeInvite}
204205
onSelectedMembersUpdate={onSelectedMembersUpdate}
@@ -230,7 +231,8 @@ class TeamManagement extends React.Component {
230231
removeMember={removeMember}
231232
addUsers={onTopcoderInviteSend}
232233
approveOrDecline={onAcceptOrRefuse}
233-
invites={topcoderTeamInvites}
234+
projectTeamInvites={projectTeamInvites}
235+
topcoderTeamInvites={topcoderTeamInvites}
234236
removeInvite={removeInvite}
235237
changeRole={changeRole}
236238
onSelectedMembersUpdate={onSelectedMembersUpdate}

0 commit comments

Comments
 (0)