labo-components
Version:
211 lines (194 loc) • 6.94 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import Project from '../../../model/Project';
import ComponentUtil from '../../../util/ComponentUtil';
import IDUtil from '../../../util/IDUtil';
import ProjectForm from './crud/ProjectForm';
import ProjectAPI from '../../../api/ProjectAPI';
/**
* Returns the project list and send it to the output callback.
*
* FIXME this component does not handle new properties yet! (e.g. if you pass a new this.props.projects, the project list is NOT updated at all)
*/
export default class ProjectList extends React.Component {
constructor(props) {
super(props);
this.state = {
allProjects: this.props.projects || [],
visibleProjects: this.props.projects || [],
showNewProjectForm: false
};
this.filterField = React.createRef();
this.CLASS_PREFIX = 'prl';
}
onProjectSaved = project => {
if (project) {
const projects = [...this.state.allProjects, project];
this.setState(
{
showNewProjectForm: false,
allProjects: projects,
visibleProjects: projects
},
() => this.selectProject(project.id)
);
}
};
handleProjectClicked = e => {
this.selectProject(e.target.id);
};
selectProject = projectId => {
const selectedProject = this.state.allProjects.filter(
item => item.id === projectId
);
this.props.onSelect(selectedProject[0]);
if (this.filterField.current) {
this.filterField.current.value = '';
this.filterProjects();
}
};
filterProjects = () => {
const filteredProjects = this.state.allProjects.filter(item =>
item.name
.toLowerCase()
.includes(this.filterField.current.value.toLowerCase())
);
this.setState({
visibleProjects: filteredProjects
});
};
newProject = () => {
this.setState({
showNewProjectForm: true
});
};
renderProjectForm = () => (
<ProjectForm
id="bg__project-selector"
submitButton="save"
onCancel={() => {
ComponentUtil.hideModal(
this,
'showNewProjectForm',
'project__modal',
true
);
}}
project={{
name: '',
description: '',
user: this.props.user.id
}}
projectDidSave={projectId => {
ProjectAPI.get(
this.props.user.id,
projectId,
project => {
if (project && project.id) {
this.onProjectSaved(project);
}
}
);
ComponentUtil.hideModal(
this,
'showNewProjectForm',
'project__modal',
true
);
}}
user={this.props.user}
api={ProjectAPI}
/>
);
renderProjectsList = modalOpened => {
// remove active project from list of available options
const listItems = this.props.activeProject ? this.state.visibleProjects.filter(
item => item.name !== this.props.activeProject.name
) : this.state.visibleProjects;
const menuClasses = [IDUtil.cssClassName('menu', this.CLASS_PREFIX)]
if(modalOpened) {
menuClasses.push('hidden');
}
// only show filter if there are more than N items (or something is typed in the filter)
const showFilter = (this.filterField.current && this.filterField.current.value.length > 0) || listItems.length > 8;
return (
<ul className={menuClasses.join(' ')}>
{showFilter && (
<input
ref={this.filterField}
type="text"
onChange={this.filterProjects}
placeholder="Filter projects"
className={IDUtil.cssClassName(
'filter-list',
this.CLASS_PREFIX
)}
/>
)}
{listItems.map(item => (
<li
id={item.id}
key={item.id}
onClick={this.handleProjectClicked}
>
{item.name}
</li>
))}
<button
onClick={this.newProject}
className={IDUtil.cssClassName('new', this.CLASS_PREFIX)}
>
{' '}
+ New Project
</button>
</ul>
);
};
render() {
const projectList = this.renderProjectsList(this.state.showNewProjectForm);
const newProjectForm = this.state.showNewProjectForm
? this.renderProjectForm(this.props.newProjectInModal)
: null;
return (
<label className={IDUtil.cssClassName('project-list')}>
{this.props.activeProject && (this.props.activeProject.name !== null) ? (
<div className="active-project">
<div className={this.props.projectIcon ? 'title with-icon' : 'title'}>
{this.props.activeProject.name}
</div>
<a href={
'/workspace/projects/' +
this.props.activeProject.id
}
/>
</div>
) : (
<div className="select">{this.props.buttonText}</div>
)}
<input
type="checkbox"
className={IDUtil.cssClassName(
'checkbox',
this.CLASS_PREFIX
)}
/>
{projectList}
{newProjectForm}
</label>
);
}
}
ProjectList.propTypes = {
onSelect: PropTypes.func.isRequired,
buttonText: PropTypes.string.isRequired,
projects: PropTypes.array,
activeProject: Project.getPropTypes(false),
user: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string,
attributes: PropTypes.shape({
allowPersonalCollections: PropTypes.bool
})
}).isRequired,
projectIcon: PropTypes.bool //whether or not to show the project icon
};