diff --git a/src/actions/challenges.js b/src/actions/challenges.js
index f1dabb7e..60eb631f 100644
--- a/src/actions/challenges.js
+++ b/src/actions/challenges.js
@@ -57,7 +57,7 @@ import {
} from '../config/constants'
import { loadProject } from './projects'
import { removeChallengeFromPhaseProduct, saveChallengeAsPhaseProduct } from '../services/projects'
-import { checkAdmin } from '../util/tc'
+import { checkAdmin, checkManager } from '../util/tc'
/**
* Member challenges related redux actions
@@ -159,7 +159,11 @@ export function loadChallengesByPage (
filters['projectId'] = projectId
} else if (_.isObject(projectId) && projectId.value > 0) {
filters['projectId'] = projectId.value
- } else if (!checkAdmin(getState().auth.token) && userId) {
+ } else if (
+ !checkAdmin(getState().auth.token) &&
+ !checkManager(getState().auth.token) &&
+ userId
+ ) {
// Note that we only add the memberId field if *no* project ID is given,
// so that the list of *all challenges shows only those that the member is on
filters['memberId'] = userId
diff --git a/src/actions/sidebar.js b/src/actions/sidebar.js
index 4fd02fd1..0c02d8f4 100644
--- a/src/actions/sidebar.js
+++ b/src/actions/sidebar.js
@@ -11,7 +11,7 @@ import {
UNLOAD_PROJECTS_SUCCESS,
PROJECTS_PAGE_SIZE
} from '../config/constants'
-import { checkAdmin } from '../util/tc'
+import { checkAdmin, checkManager } from '../util/tc'
import _ from 'lodash'
/**
@@ -50,7 +50,7 @@ export function loadProjects (filterProjectName = '', paramFilters = {}) {
}
}
- if (!checkAdmin(getState().auth.token)) {
+ if (!checkAdmin(getState().auth.token) && !checkManager(getState().auth.token)) {
filters['memberOnly'] = true
}
diff --git a/src/actions/users.js b/src/actions/users.js
index 46a9a56f..31a65ab2 100644
--- a/src/actions/users.js
+++ b/src/actions/users.js
@@ -10,33 +10,55 @@ import {
SEARCH_USER_PROJECTS_SUCCESS,
SEARCH_USER_PROJECTS_FAILURE
} from '../config/constants'
+import _ from 'lodash'
/**
* Loads projects of the authenticated user
*/
-export function loadAllUserProjects (isAdmin = true) {
- return (dispatch) => {
+export function loadAllUserProjects (params, isAdmin = true, isManager = true) {
+ return (dispatch, getState) => {
dispatch({
type: LOAD_ALL_USER_PROJECTS_PENDING
})
+ const state = getState().users
+
const filters = {
status: 'active',
- sort: 'lastActivityAt desc'
+ sort: 'lastActivityAt desc',
+ perPage: 20,
+ ...params
}
- if (!isAdmin) {
+
+ if (!isAdmin && !isManager) {
filters['memberOnly'] = true
}
- fetchMemberProjects(filters).then(({ projects }) => dispatch({
+ fetchMemberProjects(filters).then(({ projects, pagination }) => dispatch({
type: LOAD_ALL_USER_PROJECTS_SUCCESS,
- projects
+ projects: _.uniqBy((filters.page ? state.allUserProjects || [] : []).concat(projects), 'id'),
+ total: pagination.xTotal,
+ page: pagination.xPage
})).catch(() => dispatch({
type: LOAD_ALL_USER_PROJECTS_FAILURE
}))
}
}
+export function loadNextProjects (isAdmin = true, isManager = true) {
+ return (dispatch, getState) => {
+ const { page, total, allUserProjects } = getState().users
+ if (allUserProjects.length >= total) {
+ return
+ }
+
+ loadAllUserProjects(_.assign({}, {
+ perPage: 20,
+ page: page + 1
+ }), isAdmin, isManager)(dispatch, getState)
+ }
+}
+
/**
* Filter projects of the authenticated user
*
diff --git a/src/components/Users/index.js b/src/components/Users/index.js
index 07d862dc..1eb1b46f 100644
--- a/src/components/Users/index.js
+++ b/src/components/Users/index.js
@@ -9,7 +9,7 @@ import PrimaryButton from '../Buttons/PrimaryButton'
import Modal from '../Modal'
import SelectUserAutocomplete from '../SelectUserAutocomplete'
import { PROJECT_ROLES, AUTOCOMPLETE_DEBOUNCE_TIME_MS } from '../../config/constants'
-import { checkAdmin } from '../../util/tc'
+import { checkAdmin, checkManager } from '../../util/tc'
import { addUserToProject, removeUserFromProject } from '../../services/projects'
import ConfirmationModal from '../Modal/ConfirmationModal'
@@ -213,7 +213,8 @@ class Users extends Component {
updateProjectNember,
isEditable,
isSearchingUserProjects,
- resultSearchUserProjects
+ resultSearchUserProjects,
+ loadNextProjects
} = this.props
const {
searchKey
@@ -228,7 +229,8 @@ class Users extends Component {
const membersExist = projectMembers && projectMembers.length > 0
const isCopilotOrManager = this.checkIsCopilotOrManager(projectMembers, loggedInHandle)
const isAdmin = checkAdmin(this.props.auth.token)
- const showAddUser = isEditable && this.state.projectOption && (isCopilotOrManager || isAdmin)
+ const isManager = checkManager(this.props.auth.token)
+ const showAddUser = isEditable && this.state.projectOption && (isCopilotOrManager || isAdmin || isManager)
return (
@@ -246,6 +248,7 @@ class Users extends Component {
onChange={(e) => { this.setProjectOption(e) }}
onInputChange={this.debouncedOnInputChange}
isLoading={isSearchingUserProjects}
+ onMenuScrollBottom={loadNextProjects}
filterOption={() => true}
noOptionsMessage={() => isSearchingUserProjects ? 'Searching...' : 'No options'}
/>
@@ -457,7 +460,8 @@ Users.propTypes = {
projects: PropTypes.arrayOf(PropTypes.object),
projectMembers: PropTypes.arrayOf(PropTypes.object),
searchUserProjects: PropTypes.func.isRequired,
- resultSearchUserProjects: PropTypes.arrayOf(PropTypes.object)
+ resultSearchUserProjects: PropTypes.arrayOf(PropTypes.object),
+ loadNextProjects: PropTypes.func.isRequired
}
export default Users
diff --git a/src/containers/Projects/index.js b/src/containers/Projects/index.js
index 97a5e189..e3dd4167 100644
--- a/src/containers/Projects/index.js
+++ b/src/containers/Projects/index.js
@@ -18,7 +18,7 @@ import styles from './styles.module.scss'
const Projects = ({ projects, auth, isLoading, projectsCount, loadProjects, loadMoreProjects, unloadProjects }) => {
const [search, setSearch] = useState()
const [projectStatus, setProjectStatus] = useState('')
- const [showOnlyMyProjects, setOnlyMyProjects] = useState(true)
+ const [showOnlyMyProjects, setOnlyMyProjects] = useState(false)
const selectedStatus = useMemo(() => PROJECT_STATUSES.find(s => s.value === projectStatus))
const isProjectManager = checkManager(auth.token)
diff --git a/src/containers/Users/index.js b/src/containers/Users/index.js
index 7a1ecf3f..c8666784 100644
--- a/src/containers/Users/index.js
+++ b/src/containers/Users/index.js
@@ -5,10 +5,11 @@ import PT from 'prop-types'
import UsersComponent from '../../components/Users'
import { PROJECT_ROLES } from '../../config/constants'
import { fetchProjectById } from '../../services/projects'
-import { checkAdmin } from '../../util/tc'
+import { checkAdmin, checkManager } from '../../util/tc'
import {
loadAllUserProjects,
+ loadNextProjects,
searchUserProjects
} from '../../actions/users'
@@ -25,19 +26,32 @@ class Users extends Component {
this.updateProjectNember = this.updateProjectNember.bind(this)
this.removeProjectNember = this.removeProjectNember.bind(this)
this.addNewProjectMember = this.addNewProjectMember.bind(this)
+ this.loadNextProjects = this.loadNextProjects.bind(this)
}
componentDidMount () {
- const { token, isLoading, loadAllUserProjects } = this.props
+ const { token, isLoading, loadAllUserProjects, page } = this.props
if (!isLoading) {
const isAdmin = checkAdmin(token)
- loadAllUserProjects(isAdmin)
+ const isManager = checkManager(token)
+ const params = {
+ page
+ }
+ loadAllUserProjects(params, isAdmin, isManager)
this.setState({
isAdmin
})
}
}
+ loadNextProjects () {
+ const { loadNextProjects: nextProjectsHandler, token } = this.props
+ const isAdmin = checkAdmin(token)
+ const isManager = checkManager(token)
+
+ nextProjectsHandler(isAdmin, isManager)
+ }
+
isEditable () {
const { loginUserRoleInProject } = this.state
if (loginUserRoleInProject === PROJECT_ROLES.READ) {
@@ -129,6 +143,7 @@ class Users extends Component {
updateProjectNember={this.updateProjectNember}
removeProjectNember={this.removeProjectNember}
addNewProjectMember={this.addNewProjectMember}
+ loadNextProjects={this.loadNextProjects}
projectMembers={projectMembers}
auth={auth}
isAdmin={isAdmin}
@@ -146,6 +161,7 @@ class Users extends Component {
const mapStateToProps = ({ users, auth }) => {
return {
projects: users.allUserProjects,
+ page: users.page,
isLoading: users.isLoadingAllUserProjects,
resultSearchUserProjects: users.searchUserProjects,
isSearchingUserProjects: users.isSearchingUserProjects,
@@ -164,12 +180,15 @@ Users.propTypes = {
isLoading: PT.bool,
isSearchingUserProjects: PT.bool,
loadAllUserProjects: PT.func.isRequired,
- searchUserProjects: PT.func.isRequired
+ searchUserProjects: PT.func.isRequired,
+ loadNextProjects: PT.func.isRequired,
+ page: PT.number
}
const mapDispatchToProps = {
loadAllUserProjects,
- searchUserProjects
+ searchUserProjects,
+ loadNextProjects
}
export default connect(mapStateToProps, mapDispatchToProps)(Users)
diff --git a/src/reducers/users.js b/src/reducers/users.js
index 8dc18247..e293c154 100644
--- a/src/reducers/users.js
+++ b/src/reducers/users.js
@@ -14,7 +14,9 @@ const initialState = {
allUserProjects: [],
isLoadingAllUserProjects: false,
searchUserProjects: [],
- isSearchingUserProjects: false
+ isSearchingUserProjects: false,
+ page: 1,
+ total: null
}
export default function (state = initialState, action) {
@@ -23,7 +25,9 @@ export default function (state = initialState, action) {
return {
...state,
allUserProjects: action.projects,
- isLoadingAllUserProjects: false
+ isLoadingAllUserProjects: false,
+ page: action.page,
+ total: action.total
}
case LOAD_ALL_USER_PROJECTS_PENDING:
return { ...state, isLoadingAllUserProjects: true }