86ee80f72ed32d16a7c238a77a45960583c25ab0
[sdc.git] /
1 /*!
2  * Copyright © 2016-2017 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16
17 import React from 'react';
18 import PropTypes from 'prop-types';
19 import { DragSource, DropTarget } from 'react-dnd';
20
21 import Common from '../../../../../../common/Common';
22
23 import Icon from '../../../../../icons/Icon';
24 import iconHandle from '../../../../../../../../../../res/ecomp/asdc/sequencer/sprites/icons/handle.svg';
25 import iconDelete from '../../../../../../../../../../res/ecomp/asdc/sequencer/sprites/icons/delete.svg';
26
27 /**
28  * LHS lifeline row view.
29  */
30 class Lifeline extends React.Component {
31
32   // ///////////////////////////////////////////////////////////////////////////////////////////////
33
34   /**
35    * Construct editor view.
36    * @param props element properties.
37    * @param context react context.
38    */
39   constructor(props, context) {
40     super(props, context);
41
42     this.state = {
43       active: false,
44       name: props.lifeline.name,
45     };
46
47     const metamodel = Common.assertNotNull(this.props.metamodel).unwrap();
48     this.canReorder = metamodel.diagram.lifelines.constraints.reorder;
49     this.canDelete = metamodel.diagram.lifelines.constraints.delete;
50
51     // Bindings.
52
53     this.onChangeName = this.onChangeName.bind(this);
54     this.onBlurName = this.onBlurName.bind(this);
55     this.onClickDelete = this.onClickDelete.bind(this);
56     this.onMouseEnter = this.onMouseEnter.bind(this);
57     this.onMouseLeave = this.onMouseLeave.bind(this);
58   }
59
60   // ///////////////////////////////////////////////////////////////////////////////////////////////
61
62   /**
63    * Handle name change.
64    * @param event change event.
65    */
66   onChangeName(event) {
67     this.setState({ name: event.target.value });
68   }
69
70   // ///////////////////////////////////////////////////////////////////////////////////////////////
71
72   /**
73    * Handle name change.
74    * @param event change event.
75    */
76   onBlurName(event) {
77     const options = this.props.application.getOptions();
78     const sanitized = Common.sanitizeText(event.target.value, options, 'lifeline');
79     const props = {
80       id: this.props.lifeline.id,
81       name: sanitized,
82     };
83     this.props.designer.updateLifeline(props);
84     this.setState({ name: sanitized });
85   }
86
87   // ///////////////////////////////////////////////////////////////////////////////////////////////
88
89   /**
90    * Handle lifeline delete.
91    */
92   onClickDelete() {
93     this.props.designer.deleteLifeline(this.props.lifeline.id);
94   }
95
96   // ///////////////////////////////////////////////////////////////////////////////////////////////
97
98   /**
99    * Handle mouseover event.
100    */
101   onMouseEnter() {
102     this.setState({ active: true });
103     this.props.designer.onMouseEnterLifeline(this.props.lifeline.id);
104   }
105
106   // ///////////////////////////////////////////////////////////////////////////////////////////////
107
108   /**
109    * Handle mouseleave event.
110    */
111   onMouseLeave() {
112     this.setState({ active: false });
113     this.props.designer.onMouseLeaveLifeline(this.props.lifeline.id);
114   }
115
116   // ///////////////////////////////////////////////////////////////////////////////////////////////
117
118   /**
119    * Get whether metadata permits reorder.
120    * @returns true if reorderable.
121    */
122   isCanReorder() {
123     return this.canReorder;
124   }
125
126   // ///////////////////////////////////////////////////////////////////////////////////////////////
127
128   /**
129    * Get whether metadata permits delete.
130    * @returns true if lifeline can be deleted.
131    */
132   isCanDelete() {
133     return this.canDelete;
134   }
135
136   // ///////////////////////////////////////////////////////////////////////////////////////////////
137
138   /**
139    * React render.
140    * @returns {*}
141    */
142   render() {
143
144     const id = this.props.lifeline.id;
145     const activeClass = (this.props.active === true) ? 'asdcs-active' : '';
146     const { connectDragSource, connectDropTarget } = this.props;
147     return connectDragSource(connectDropTarget(
148
149       <div
150         className={`asdcs-designer-lifeline ${activeClass}`}
151         data-id={id}
152         onMouseEnter={this.onMouseEnter}
153         onMouseLeave={this.onMouseLeave}
154       >
155         <table className="asdcs-designer-layout asdcs-designer-lifeline-row1">
156           <tbody>
157             <tr>
158               <td>
159                 <div className="asdcs-designer-sort asdcs-designer-icon">
160                   <Icon glyph={iconHandle} />
161                 </div>
162               </td>
163               <td>
164                 <div className="asdcs-designer-lifeline-index">{this.props.lifeline.index}.</div>
165               </td>
166               <td>
167                 <div className="asdcs-designer-lifeline-name">
168                   <input
169                     type="text"
170                     className="asdcs-editable"
171                     placeholder="Unnamed"
172                     value={this.state.name}
173                     onChange={this.onChangeName}
174                     onBlur={this.onBlurName}
175                   />
176                 </div>
177               </td>
178               <td>
179                 <div className="asdcs-designer-delete asdcs-designer-icon" onClick={this.onClickDelete}>
180                   <Icon glyph={iconDelete} />
181                 </div>
182               </td>
183             </tr>
184           </tbody>
185         </table>
186       </div>
187     ));
188   }
189 }
190
191 /**
192  * Declare properties.
193  */
194 Lifeline.propTypes = {
195   application: PropTypes.object.isRequired,
196   designer: PropTypes.object.isRequired,
197   lifeline: PropTypes.object.isRequired,
198   active: PropTypes.bool.isRequired,
199   metamodel: PropTypes.object.isRequired,
200   id: PropTypes.any.isRequired,
201   index: PropTypes.number.isRequired,
202   lifelines: PropTypes.object.isRequired,
203   isDragging: PropTypes.bool.isRequired,
204   connectDragSource: PropTypes.func.isRequired,
205   connectDropTarget: PropTypes.func.isRequired,
206 };
207
208 /** DND. */
209 const source = {
210   beginDrag(props) {
211     return {
212       id: props.id,
213       index: props.index,
214     };
215   },
216 };
217
218 /** DND. */
219 const sourceCollect = function collection(connect, monitor) {
220   return {
221     connectDragSource: connect.dragSource(),
222     isDragging: monitor.isDragging(),
223   };
224 };
225
226 /** DND. */
227 const target = {
228   drop(props, monitor, component) {
229     Common.assertNotNull(props);
230     Common.assertNotNull(monitor);
231     const decorated = component.getDecoratedComponentInstance();
232     if (decorated) {
233       const lifelines = decorated.props.lifelines;
234       if (lifelines) {
235         const dragIndex = monitor.getItem().index;
236         const hoverIndex = lifelines.getHoverIndex();
237         lifelines.onDrop(dragIndex, hoverIndex);
238       }
239     }
240   },
241   hover(props, monitor, component) {
242     Common.assertNotNull(props);
243     Common.assertNotNull(monitor);
244     if (component) {
245       const decorated = component.getDecoratedComponentInstance();
246       if (decorated) {
247         const lifelines = decorated.props.lifelines;
248         if (lifelines) {
249           lifelines.setHoverIndex(decorated.props.index);
250         }
251       }
252     }
253   },
254 };
255
256 /** DND. */
257 function targetCollect(connect, monitor) {
258   return {
259     connectDropTarget: connect.dropTarget(),
260     isOver: monitor.isOver(),
261   };
262 }
263
264 const wrapper1 = DragSource('lifeline', source, sourceCollect)(Lifeline);
265 export default DropTarget(['lifeline', 'lifeline-new'], target, targetCollect)(wrapper1);