update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b third try
[osm/UI.git] / skyquake / plugins / user_management / src / userProfile / userProfile.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 UserProfileStore from './userProfileStore.js';
9 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
10 import 'style/layout.scss';
11 import '../dashboard/userMgmt.scss';
12 import { Panel, PanelWrapper } from 'widgets/panel/panel';
13
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 UserProfileDashboard extends React.Component {
24     constructor(props) {
25         super(props);
26         this.Store = this.props.flux.stores.hasOwnProperty('UserProfileStore') ? this.props.flux.stores.UserProfileStore : this.props.flux.createStore(UserProfileStore);
27         this.state = this.Store.getState();
28         this.actions = this.state.actions;
29
30     }
31     componentDidUpdate() {
32         let self = this;
33         ReactDOM.findDOMNode(this.UserList).addEventListener('transitionend', this.onTransitionEnd, false);
34         setTimeout(function () {
35             let element = self[`user-ref-${self.state.activeIndex}`]
36             element && !isElementInView(element) && element.scrollIntoView({ block: 'end', behavior: 'smooth' });
37         })
38     }
39     componentWillMount() {
40         this.Store.listen(this.updateState);
41     }
42     componentWillUnmount() {
43         this.Store.unlisten(this.updateState);
44     }
45     updateState = (state) => {
46         this.setState(state);
47     }
48     updateInput = (key, e) => {
49         let property = key;
50         this.actions.handleUpdateInput({
51             [property]: e.target.value
52         })
53     }
54     disabledChange = (e) => {
55         this.actions.handleDisabledChange(e.target.checked);
56     }
57     platformChange = (platformRole, e) => {
58         this.actions.handlePlatformRoleUpdate(platformRole, e.currentTarget.checked);
59     }
60     addProjectRole = (e) => {
61         this.actions.handleAddProjectItem();
62     }
63     removeProjectRole = (i, e) => {
64         this.actions.handleRemoveProjectItem(i);
65     }
66     updateProjectRole = (i, e) => {
67         this.actions.handleUpdateProjectRole(i, e)
68     }
69     addUser = () => {
70         this.actions.handleAddUser();
71     }
72     viewUser = (un, index) => {
73         this.actions.viewUser(un, index);
74     }
75     editUser = () => {
76         this.actions.editUser(false);
77     }
78     cancelEditUser = () => {
79         this.actions.editUser(true)
80     }
81     osePanel = () => {
82         this.actions.handleCloseUserPanel();
83     }
84     // updateUser = (e) => {
85     //     e.preventDefault();
86     //     e.stopPropagation();
87
88     //     this.Store.updateUser();
89     // }
90     deleteUser = (e) => {
91         e.preventDefault();
92         e.stopPropagation();
93         this.Store.deleteUser({
94             'user-name': this.state['user-name'],
95             'user-domain': this.state['user-domain']
96         });
97     }
98     createUser = (e) => {
99         e.preventDefault();
100         e.stopPropagation();
101         if (this.state['new-password'] != this.state['confirm-password']) {
102             this.props.actions.showNotification('Passwords do not match')
103         } else {
104             this.Store.createUser({
105                 'user-name': this.state['user-name'],
106                 'user-domain': this.state['user-domain'],
107                 'password': this.state['new-password']
108                 // 'confirm-password': this.state['confirm-password']
109             });
110         }
111     }
112     updateUser = (e) => {
113         let self = this;
114         e.preventDefault();
115         e.stopPropagation();
116         let validatedPasswords = validatePasswordFields(this.state);
117         if (validatedPasswords) {
118             this.Store.updateUser(_.merge({
119                 'user-name': this.context.userProfile.userId,
120                 'user-domain': this.state['user-domain'],
121                 'password': this.state['new-password'],
122                 'ui-state': this.context.userProfile.data['ui-state']
123             }));
124         }
125         function validatePasswordFields(state) {
126             let newOne = state['new-password'];
127             let confirmOne = state['confirm-password'];
128             if (!newOne || !confirmOne) {
129                 self.props.actions.showNotification('Please fill in all fields.');
130                 return false;
131             }
132             if (newOne != confirmOne) {
133                 self.props.actions.showNotification('Passwords do not match');
134                 return false;
135             }
136             return {
137                 'new-password': newOne,
138                 'confirm-password': confirmOne
139             }
140         }
141     }
142     evaluateSubmit = (e) => {
143         if (e.keyCode == 13) {
144             if (this.state.isEdit) {
145                 this.updateUser(e);
146             } else {
147                 this.createUser(e);
148             }
149             e.preventDefault();
150             e.stopPropagation();
151         }
152     }
153     onTransitionEnd = (e) => {
154         this.actions.handleHideColumns(e);
155         console.log('transition end')
156     }
157     disableChange = (e) => {
158         let value = e.target.value;
159         value = value.toUpperCase();
160         if (value == "TRUE") {
161             value = true;
162         } else {
163             value = false;
164         }
165         console.log(value)
166     }
167     render() {
168
169         let self = this;
170         const User = this.context.userProfile || {};
171         let html;
172         let props = this.props;
173         let state = this.state;
174         let passwordSectionHTML = null;
175         let formButtonsHTML = (
176             <ButtonGroup className="buttonGroup">
177                 <Button label="EDIT" type="submit" onClick={this.editUser} />
178             </ButtonGroup>
179         );
180         passwordSectionHTML = (
181             (
182                 <FormSection title="PASSWORD CHANGE">
183                     <Input label="NEW PASSWORD" type="password" value={state['new-password']} onChange={this.updateInput.bind(null, 'new-password')} />
184                     <Input label="REPEAT NEW PASSWORD" type="password" value={state['confirm-password']} onChange={this.updateInput.bind(null, 'confirm-password')} />
185                 </FormSection>
186             )
187         );
188         formButtonsHTML = (
189             <ButtonGroup className="buttonGroup">
190                 <Button label="Update" type="submit" onClick={this.updateUser} />
191             </ButtonGroup>
192         )
193
194         html = (
195             <PanelWrapper column>
196                 <PanelWrapper className={`row userManagement ${!this.state.userOpen ? 'userList-open' : ''}`} style={{ 'flexDirection': 'row' }} >
197                     <PanelWrapper ref={(div) => { this.UserList = div }} className={`column userList expanded hideColumns`}>
198                         <Panel title={User.userId} style={{ marginBottom: 0 }} no-corners>
199                             <FormSection title="USER INFO">
200                                 <table className="userProfile-table">
201                                     <thead>
202                                         <tr>
203                                             <td>Project</td>
204                                             <td>Role</td>
205                                         </tr>
206                                     </thead>
207                                     <tbody>
208                                         {
209                                             User.data && User.data.projectId && User.data.projectId.map((p, i) => {
210                                                 let project = User.data.project[p];
211                                                 let projectConfig = project && project.data['project-config'];
212                                                 let userRoles = [];
213                                                 return (
214                                                     <tr key={i}>
215                                                         <td>
216                                                             {p}
217                                                         </td>
218                                                         <td>
219                                                             {
220                                                                 project && Object.keys(project.role).map(function (k, i) {
221                                                                     return <div key={i}>{k}</div>
222                                                                 })
223                                                             }
224                                                         </td>
225                                                     </tr>
226                                                 )
227                                             })
228                                         }
229                                     </tbody>
230                                 </table>
231                             </FormSection>
232                             {passwordSectionHTML}
233
234                         </Panel>
235                         <div className="buttonSection">
236                             {formButtonsHTML}
237                         </div>
238                     </PanelWrapper>
239
240                 </PanelWrapper>
241             </PanelWrapper>
242         );
243         return html;
244     }
245 }
246 // onClick={this.Store.update.bind(null, Account)}
247 UserProfileDashboard.contextTypes = {
248     router: React.PropTypes.object,
249     userProfile: React.PropTypes.object
250 };
251
252 UserProfileDashboard.defaultProps = {
253     userList: [],
254     selectedUser: {}
255 }
256
257 export default SkyquakeComponent(UserProfileDashboard);
258
259
260 function isElementInView(el) {
261     var rect = el && el.getBoundingClientRect() || {};
262
263     return (
264         rect.top >= 0 &&
265         rect.left >= 0 &&
266         rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
267         rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
268     );
269 }
270
271
272 // isReadOnly={state.isReadOnly} disabled={state.disabled} onChange={this.disableChange}
273
274 class isDisabled extends React.Component {
275     constructor(props) {
276         super(props);
277     }
278     render() {
279         let props = this.props;
280         return (<div />)
281     }
282 }
283
284 /**
285  * AddItemFn:
286  */
287 class InputCollection extends React.Component {
288     constructor(props) {
289         super(props);
290         this.collection = props.collection;
291     }
292     buildTextInput(onChange, v, i) {
293         return (
294             <Input
295                 readonly={this.props.readonly}
296                 style={{ flex: '1 1' }}
297                 key={i}
298                 value={v}
299                 onChange={onChange.bind(null, i)}
300             />
301         )
302     }
303     buildSelectOption(initial, options, onChange, v, i) {
304         return (
305             <SelectOption
306                 readonly={this.props.readonly}
307                 key={`${i}-${v.replace(' ', '_')}`}
308                 intial={initial}
309                 defaultValue={v}
310                 options={options}
311                 onChange={onChange.bind(null, i)}
312             />
313         );
314     }
315     showInput() {
316
317     }
318     render() {
319         const props = this.props;
320         let inputType;
321         let className = "InputCollection";
322         if (props.className) {
323             className = `${className} ${props.className}`;
324         }
325         if (props.type == 'select') {
326             inputType = this.buildSelectOption.bind(this, props.initial, props.options, props.onChange);
327         } else {
328             inputType = this.buildTextInput.bind(this, props.onChange)
329         }
330         let html = (
331             <div className="InputCollection-wrapper">
332                 {props.collection.map((v, i) => {
333                     return (
334                         <div key={i} className={className} >
335                             {inputType(v, i)}
336                             {
337                                 props.readonly ? null : <span onClick={props.RemoveItemFn.bind(null, i)} className="removeInput"><img src={imgRemove} />Remove</span>}
338                         </div>
339                     )
340                 })}
341                 {props.readonly ? null : <span onClick={props.AddItemFn} className="addInput"><img src={imgAdd} />Add</span>}
342             </div>
343         );
344         return html;
345     }
346 }
347
348 InputCollection.defaultProps = {
349     input: Input,
350     collection: [],
351     onChange: function (i, e) {
352         console.log(`
353                         Updating with: ${e.target.value}
354                         At index of: ${i}
355                     `)
356     },
357     AddItemFn: function (e) {
358         console.log(`Adding a new item to collection`)
359     },
360     RemoveItemFn: function (i, e) {
361         console.log(`Removing item from collection at index of: ${i}`)
362     }
363 }
364
365 class FormSection extends React.Component {
366     render() {
367         let className = 'FormSection ' + this.props.className;
368         let html = (
369             <div
370                 style={this.props.style}
371                 className={className}
372             >
373                 <div className="FormSection-title">
374                     {this.props.title}
375                 </div>
376                 <div className="FormSection-body">
377                     {this.props.children}
378                 </div>
379             </div>
380         );
381         return html;
382     }
383 }
384
385 FormSection.defaultProps = {
386     className: ''
387 }