Merge branch 'projects' of https://osm.etsi.org/gerrit/osm/UI into projects
[osm/UI.git] / skyquake / plugins / project_management / src / dashboard / dashboard.jsx
1 /*
2  * STANDARD_RIFT_IO_COPYRIGHT
3  */
4
5 import React from 'react';
6 import ReactDOM from 'react-dom';
7 import AppHeader from 'widgets/header/header.jsx';
8 import ProjectManagementStore from './projectMgmtStore.js';
9 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
10 import 'style/layout.scss';
11 import './projectMgmt.scss';
12 import {Panel, PanelWrapper} from 'widgets/panel/panel';
13 import {InputCollection, FormSection} from 'widgets/form_controls/formControls.jsx';
14
15 import TextInput from 'widgets/form_controls/textInput.jsx';
16 import Input from 'widgets/form_controls/input.jsx';
17 import Button, {ButtonGroup} from 'widgets/button/sq-button.jsx';
18 import SelectOption from 'widgets/form_controls/selectOption.jsx';
19 import 'widgets/form_controls/formControls.scss';
20 import imgAdd from '../../node_modules/open-iconic/svg/plus.svg'
21 import imgRemove from '../../node_modules/open-iconic/svg/trash.svg'
22
23 class ProjectManagementDashboard extends React.Component {
24     constructor(props) {
25         super(props);
26         this.Store = this.props.flux.stores.hasOwnProperty('ProjectManagementStore') ? this.props.flux.stores.ProjectManagementStore : this.props.flux.createStore(ProjectManagementStore);
27         this.Store.getProjects();
28         this.Store.getUsers();
29         this.state = this.Store.getState();
30         this.actions = this.state.actions;
31     }
32     componentDidUpdate() {
33         let self = this;
34         ReactDOM.findDOMNode(this.projectList).addEventListener('transitionend', this.onTransitionEnd, false);
35         setTimeout(function() {
36             let element = self[`project-ref-${self.state.activeIndex}`]
37             element && !isElementInView(element) && element.scrollIntoView({block: 'end', behavior: 'smooth'});
38         })
39     }
40     componentWillMount() {
41         this.Store.listen(this.updateState);
42     }
43     componentWillUnmount() {
44         this.Store.unlisten(this.updateState);
45     }
46     updateState = (state) => {
47         this.setState(state);
48     }
49     updateInput = (key, e) => {
50         let property = key;
51         this.actions.handleUpdateInput({
52             [property]:e.target.value
53         })
54     }
55     disabledChange = (e) => {
56         this.actions.handleDisabledChange(e.target.checked);
57     }
58     platformChange = (platformRole, e) => {
59         this.actions.handlePlatformRoleUpdate(platformRole, e.currentTarget.checked);
60     }
61     addProjectRole = (e) => {
62         this.actions.handleAddProjectItem();
63     }
64     removeProjectRole = (i, e) => {
65         this.actions.handleRemoveProjectItem(i);
66     }
67     updateProjectRole = (i, e) => {
68         this.actions.handleUpdateProjectRole(i, e)
69     }
70     addProject = () => {
71         this.actions.handleAddProject();
72     }
73     viewProject = (un, index) => {
74         this.actions.viewProject(un, index);
75     }
76     editProject = () => {
77         this.actions.editProject(false);
78     }
79     cancelEditProject = () => {
80         this.actions.editProject(true)
81     }
82     closePanel = () => {
83         this.actions.handleCloseProjectPanel();
84     }
85
86     deleteProject = (e) => {
87         e.preventDefault();
88         e.stopPropagation();
89         this.Store.deleteProject({
90                 'name': this.state['name']
91             });
92     }
93     createProject = (e) => {
94         let self = this;
95         e.preventDefault();
96         e.stopPropagation();
97         let projectName = self.state['name'];
98         let projectUsers = self.state.projectUsers;
99         let cleanUsers = this.cleanUsers(projectUsers, projectName);
100
101
102         this.Store.createProject({
103             'name': projectName,
104             'description': self.state.description,
105             'project-config' : {
106                 'name-ref': projectName,
107                 'user': cleanUsers
108             }
109         });
110     }
111     updateProject = (e) => {
112         let self = this;
113         e.preventDefault();
114         e.stopPropagation();
115          let projectName = self.state['name'];
116         let projectUsers = self.state.projectUsers;
117         let cleanUsers = this.cleanUsers(projectUsers, projectName);
118
119
120         this.Store.updateProject(_.merge({
121             'name': projectName,
122             'description': self.state.description,
123             'project-config' : {
124                 'name-ref': projectName,
125                 'user': cleanUsers
126             }
127         }));
128     }
129     cleanUsers(projectUsers, projectName) {
130         let cleanUsers = [];
131         //Remove null values from role
132         projectUsers.map((u) => {
133             let cleanRoles = [];
134            u.role && u.role.map((r,i) => {
135              let role = {};
136              //you may add a user without a role or a keys, but if one is present then the other must be as well.
137             if(!r.role ) {
138             } else {
139                 delete r.keys;
140                     // r.keys = projectName;
141                     cleanRoles.push(r)
142             }
143            });
144            u.role = cleanRoles;
145            cleanUsers.push(u);
146         });
147         return cleanUsers;
148     }
149      evaluateSubmit = (e) => {
150         if (e.keyCode == 13) {
151             if (this.props.isEdit) {
152                 this.updateProject(e);
153             } else {
154                 this.createProject(e);
155             }
156             e.preventDefault();
157             e.stopPropagation();
158         }
159     }
160     updateSelectedUser = (e) => {
161         this.setState({
162             selected
163         })
164     }
165     addUserToProject = (e) => {
166         let selectUserList = this.selectUserList;
167         console.log(ReactDOM.findDOMNode(selectUserList))
168         this.actions.handleAddUser(e);
169     }
170     removeUserFromProject = (userIndex, e) => {
171         this.actions.handleRemoveUserFromProject(userIndex);
172     }
173     updateUserRoleInProject = (userIndex, roleIndex, e) => {
174         this.actions.handleUpdateUserRoleInProject({
175             userIndex,
176             roleIndex,
177             value: JSON.parse(e.target.value)
178         })
179     }
180     toggleUserRoleInProject = (userIndex, roleIndex, e) => {
181         this.actions.handleToggleUserRoleInProject({
182             userIndex,
183             roleIndex,
184             checked: JSON.parse(e.currentTarget.checked)
185         })
186     }
187     removeRoleFromUserInProject = (userIndex, roleIndex, e) => {
188         this.actions.handleRemoveRoleFromUserInProject({
189             userIndex,
190             roleIndex
191         })
192     }
193     addRoleToUserInProject = (userIndex, e) => {
194         this.actions.addRoleToUserInProject(userIndex);
195     }
196     onTransitionEnd = (e) => {
197         this.actions.handleHideColumns(e);
198         console.log('transition end')
199     }
200     disableChange = (e) => {
201         let value = e.target.value;
202         value = value.toUpperCase();
203         if (value=="TRUE") {
204             value = true;
205         } else {
206             value = false;
207         }
208         console.log(value)
209     }
210     render() {
211         let self = this;
212         let html;
213         let props = this.props;
214         let state = this.state;
215         let passwordSectionHTML = null;
216         let formButtonsHTML = (
217             <ButtonGroup className="buttonGroup">
218                 <Button label="EDIT" type="submit" onClick={this.editProject} />
219             </ButtonGroup>
220         );
221         let projectUsers = [];
222         self.state.projectUsers.map((u) => {
223             projectUsers.push(u['user-name']);
224         });
225         let availableUsers = state.users && state.users.filter((u) => {
226             return projectUsers.indexOf(u['user-name']) == -1
227         }).map((u) => {
228             return {
229                 label: u['user-name'],
230                 value: u
231             }
232         });
233
234         if(!this.state.isReadOnly) {
235             formButtonsHTML = (
236                                 state.isEdit ?
237                                 (
238                                     <ButtonGroup className="buttonGroup">
239                                         <Button label="Update" type="submit" onClick={this.updateProject} />
240                                         <Button label="Delete" onClick={this.deleteProject} />
241                                         <Button label="Cancel" onClick={this.cancelEditProject} />
242                                     </ButtonGroup>
243                                 )
244                                 : (
245                                     <ButtonGroup className="buttonGroup">
246                                         <Button label="Create" type="submit" onClick={this.createProject}  />
247                                     </ButtonGroup>
248                                 )
249                             )
250         }
251
252         html = (
253             <PanelWrapper className={`row projectManagement ${!this.state.projectOpen ? 'projectList-open' : ''}`} style={{'alignContent': 'center', 'flexDirection': 'row'}} >
254                 <PanelWrapper ref={(div) => { this.projectList = div}} className={`column projectList expanded ${this.state.projectOpen ? 'collapsed ' : ' '} ${this.state.hideColumns ? 'hideColumns ' : ' '}`}>
255                     <Panel title="Project List" style={{marginBottom: 0}} no-corners>
256                         <div className="tableRow tableRow--header">
257                             <div className="projectName">
258                                 Project Name
259                             </div>
260                             <div>
261                                 Description
262                             </div>
263                         </div>
264                         {state.projects && state.projects.map((u, k) => {
265                             let platformRoles = [];
266                             for(let role in u.platformRoles) {
267                                 platformRoles.push(<div>{`${role}: ${u.platformRoles[role]}`}</div>)
268                             }
269                             return (
270                                 <div onClick={self.viewProject.bind(null, u, k)} ref={(el) => this[`project-ref-${k}`] = el} className={`tableRow tableRow--data ${((self.state.activeIndex == k) && self.state.projectOpen) ? 'tableRow--data-active' : ''}`} key={k}>
271                                     <div
272                                         className={`projectName projectName-header ${((self.state.activeIndex == k) && self.state.projectOpen) ? 'activeProject' : ''}`}
273                                         >
274                                         {u['name']}
275                                     </div>
276                                     <div>
277                                         {u['description']}
278                                     </div>
279
280
281                                 </div>
282                             )
283                         })}
284                     </Panel>
285                     <ButtonGroup  className="buttonGroup" style={{margin: '0 0.5rem 0.5rem', background: '#ddd', paddingBottom: '0.5rem'}}>
286                         <Button label="Add Project" onClick={this.addProject} />
287                     </ButtonGroup>
288                 </PanelWrapper>
289                 <PanelWrapper onKeyUp={this.evaluateSubmit}
290                     className={`ProjectAdmin column`}>
291                     <Panel
292                         title={state.isEdit ? state['name'] : 'Create Project'}
293                         style={{marginBottom: 0}}
294                         hasCloseButton={this.closePanel}
295                         no-corners>
296                         <FormSection title="PROJECT INFO">
297                         {
298                             this.state.isEdit ?
299                                 null
300                                 : <Input  readonly={state.isReadOnly}  label="Name" value={state['name']} onChange={this.updateInput.bind(null, 'name')} />
301                         }
302                             <Input readonly={state.isReadOnly} type="textarea" label="Description" value={state['description']}  onChange={this.updateInput.bind(null, 'description')}></Input>
303                         </FormSection>
304                         <FormSection title="USER ROLES"  className="userTable">
305
306                         <table>
307                             <thead>
308                                 <tr>
309                                     {!state.isReadOnly ? <td></td> : null}
310                                     <td>User Name</td>
311                                     {
312                                         state.roles.map((r,i) => {
313                                             return <td key={i}>{r}</td>
314                                         })
315                                     }
316                                 </tr>
317                             </thead>
318                             <tbody>
319                                 {
320                             state.projectUsers.map((u,i)=> {
321                                 let userRoles = u.role && u.role.map((r) => {
322                                     return r.role;
323                                 }) || [];
324                                 return (
325                                     <tr key={i}>
326                                         {!state.isReadOnly ? <td><span
327                                                                     className="removeInput"
328                                                                     onClick={self.removeUserFromProject.bind(self, i)}
329                                                                 >
330                                                                     <img src={imgRemove} />
331
332                                                                 </span></td> : null}
333                                         <td>
334                                             {u['user-name']}
335                                         </td>
336                                         {
337                                             state.roles.map((r,j) => {
338                                                 return <td key={j}><Input readonly={state.isReadOnly} type="checkbox" onChange={self.toggleUserRoleInProject.bind(self, i, j)} checked={(userRoles.indexOf(r) > -1)} /></td>
339                                             })
340                                         }
341                                     </tr>
342                                 )
343                             })
344                         }
345                             </tbody>
346                         </table>
347
348                             {
349                                 !state.isReadOnly ?
350                                     <div className="tableRow tableRow--header">
351                                         <div>
352                                             <div className="addUser">
353                                                 <SelectOption
354                                                     onChange={this.actions.handleSelectedUser}
355                                                     value={state.selectedUser}
356                                                     initial={true}
357                                                     options={availableUsers}
358                                                     ref={(el) => self.selectUserList = el}
359                                                 />
360                                                 <span className="addInput" onClick={this.addUserToProject}><img src={imgAdd} />
361                                                     Add User
362                                                 </span>
363                                             </div>
364                                         </div>
365                                     </div> : null
366                             }
367
368                         </FormSection>
369
370                     </Panel>
371                         {formButtonsHTML}
372
373                 </PanelWrapper>
374
375
376             </PanelWrapper>
377         );
378         return html;
379     }
380 }
381 // onClick={this.Store.update.bind(null, Account)}
382 ProjectManagementDashboard.contextTypes = {
383     router: React.PropTypes.object
384 };
385
386 ProjectManagementDashboard.defaultProps = {
387     projectList: [],
388     selectedProject: {}
389 }
390
391 export default SkyquakeComponent(ProjectManagementDashboard);
392
393
394 function isElementInView(el) {
395     var rect = el && el.getBoundingClientRect() || {};
396
397     return (
398         rect.top >= 0 &&
399         rect.left >= 0 &&
400         rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
401         rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
402     );
403 }
404
405
406 // isReadOnly={state.isReadOnly} disabled={state.disabled} onChange={this.disableChange}
407
408 class isDisabled extends React.Component {
409     constructor(props) {
410         super(props);
411     }
412     render() {
413         let props = this.props;
414         return (<div/>)
415     }
416 }
417
418
419
420