2 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 import React from 'react';
19 import HTML5Backend from 'react-dnd-html5-backend';
20 import { DragDropContext } from 'react-dnd';
22 import Common from '../../../../common/Common';
23 import Logger from '../../../../common/Logger';
25 import Actions from './components/actions/Actions';
26 import Lifelines from './components/lifeline/Lifelines';
27 import Messages from './components/message/Messages';
28 import Metadata from './components/metadata/Metadata';
30 import Icon from '../../../icons/Icon';
31 import iconExpanded from '../../../../../../../../res/ecomp/asdc/sequencer/sprites/icons/expanded.svg';
32 import iconCollapsed from '../../../../../../../../res/ecomp/asdc/sequencer/sprites/icons/collapsed.svg';
35 * LHS design wid` view.
37 class Designer extends React.Component {
39 // ///////////////////////////////////////////////////////////////////////////////////////////////
43 * @param props element properties.
44 * @param context react context.
46 constructor(props, context) {
47 super(props, context);
51 this.application = Common.assertNotNull(props.application);
54 lifelinesExpanded: false,
55 messagesExpanded: true,
56 activeLifelineId: undefined,
57 activeMessageId: undefined,
62 this.onToggle = this.onToggle.bind(this);
63 this.onMouseEnterLifeline = this.onMouseEnterLifeline.bind(this);
64 this.onMouseLeaveLifeline = this.onMouseLeaveLifeline.bind(this);
65 this.onMouseEnterMessage = this.onMouseEnterMessage.bind(this);
66 this.onMouseLeaveMessage = this.onMouseLeaveMessage.bind(this);
68 this.addMessage = this.addMessage.bind(this);
69 this.updateMessage = this.updateMessage.bind(this);
70 this.deleteMessage = this.deleteMessage.bind(this);
71 this.addLifeline = this.addLifeline.bind(this);
72 this.updateLifeline = this.updateLifeline.bind(this);
73 this.deleteLifeline = this.deleteLifeline.bind(this);
75 this.selectMessage = this.selectMessage.bind(this);
76 this.selectLifeline = this.selectLifeline.bind(this);
79 // ///////////////////////////////////////////////////////////////////////////////////////////////
82 * Select message by ID.
83 * @param id message ID.
87 // TODO: scroll into view.
89 this.setState({ activeMessageId: id });
92 // ///////////////////////////////////////////////////////////////////////////////////////////////
95 * Select lifeline by ID.
96 * @param id lifeline ID.
100 // TODO: scroll into view.
102 this.setState({ activeLifelineId: id });
105 // ///////////////////////////////////////////////////////////////////////////////////////////////
108 * Show/hide lifelines section.
111 const lifelinesExpanded = !this.state.lifelinesExpanded;
112 const messagesExpanded = !lifelinesExpanded;
113 this.setState({ lifelinesExpanded, messagesExpanded });
116 // ///////////////////////////////////////////////////////////////////////////////////////////////
119 * Handle mouse event.
120 * @param id lifeline identifier.
122 onMouseEnterLifeline(id) {
123 this.application.selectLifeline(id);
126 // ///////////////////////////////////////////////////////////////////////////////////////////////
129 * Handle mouse event.
131 onMouseLeaveLifeline() {
132 this.application.selectLifeline();
135 // ///////////////////////////////////////////////////////////////////////////////////////////////
138 * Handle mouse event.
139 * @param id message identifier.
141 onMouseEnterMessage(id) {
142 this.application.selectMessage(id);
145 // ///////////////////////////////////////////////////////////////////////////////////////////////
148 * Handle mouse event.
150 onMouseLeaveMessage() {
151 // Only on next selection.
152 // this.application.selectMessage();
155 // ///////////////////////////////////////////////////////////////////////////////////////////////
162 if (this.application.getModel().unwrap().diagram.lifelines.length < 2) {
163 self.application.showErrorDialog('You need at least two lifelines.');
167 this.application.getModel().addMessage();
169 this.application.renderDiagram();
172 // ///////////////////////////////////////////////////////////////////////////////////////////////
175 * Apply property changes to the message identified by props.id.
176 * @param props properties to be updated (excluding 'id').
178 updateMessage(props) {
179 Common.assertPlainObject(props);
180 const model = this.application.getModel();
181 const message = model.getMessageById(props.id);
183 for (const k of Object.keys(props)) {
185 message[k] = props[k];
190 this.application.renderDiagram();
193 // ///////////////////////////////////////////////////////////////////////////////////////////////
196 * Delete message after confirmation.
197 * @param id ID of message to be deleted.
202 const model = this.application.getModel();
204 const confirmComplete = function f() {
205 model.deleteMessageById(id);
207 self.application.renderDiagram();
210 this.application.showConfirmDialog('Delete this message?',
214 // ///////////////////////////////////////////////////////////////////////////////////////////////
220 this.application.getModel().addLifeline();
222 this.application.renderDiagram();
225 // ///////////////////////////////////////////////////////////////////////////////////////////////
228 * Apply property changes to the lifeline identified by props.id.
229 * @param props properties to be updated (excluding 'id').
231 updateLifeline(props) {
232 Common.assertPlainObject(props);
233 const model = this.application.getModel();
234 const lifeline = model.getLifelineById(props.id);
236 for (const k of Object.keys(props)) {
238 lifeline[k] = props[k];
243 this.application.renderDiagram();
246 // ///////////////////////////////////////////////////////////////////////////////////////////////
249 * Delete lifeline after confirmation.
250 * @param id candidate for deletion.
255 const model = this.application.getModel();
257 const confirmComplete = function f() {
258 model.deleteLifelineById(id);
260 self.application.renderDiagram();
262 this.application.showConfirmDialog('Delete this lifeline and all its steps?',
266 // ///////////////////////////////////////////////////////////////////////////////////////////////
273 const application = this.props.application;
274 const model = application.getModel();
275 const diagram = model.unwrap().diagram;
276 const metadata = diagram.metadata;
278 const lifelinesIcon = this.state.lifelinesExpanded ? iconExpanded : iconCollapsed;
279 const lifelinesClass = this.state.lifelinesExpanded ? '' : 'asdcs-hidden';
280 const messagesIcon = this.state.messagesExpanded ? iconExpanded : iconCollapsed;
281 const messagesClass = this.state.messagesExpanded ? '' : 'asdcs-hidden';
285 <div className="asdcs-editor-designer">
286 <div className="asdcs-designer-accordion">
288 <div className="asdcs-designer-metadata-container">
289 <Metadata metadata={metadata} />
292 <h3 onClick={this.onToggle}>Lifelines
293 <div className="asdcs-designer-icon" onClick={this.onToggle}>
294 <Icon glyph={lifelinesIcon} />
298 <div className={`asdcs-designer-lifelines-container ${lifelinesClass}`}>
300 application={this.application}
302 activeLifelineId={this.state.activeLifelineId}
306 <h3 onClick={this.onToggle}>Steps
307 <div className="asdcs-designer-icon" onClick={this.onToggle}>
308 <Icon glyph={messagesIcon} />
312 <div className={`asdcs-designer-steps-container ${messagesClass}`} >
314 application={this.application}
316 activeMessageId={this.state.activeMessageId}
323 application={this.props.application}
325 ref={(r) => { this.actions = r; }}
332 // ///////////////////////////////////////////////////////////////////////////////////////////////
333 // ///////////////////////////////////////////////////////////////////////////////////////////////
334 // ///////////////////////////////////////////////////////////////////////////////////////////////
335 // ///////////////////////////////////////////////////////////////////////////////////////////////
336 // ///////////////////////////////////////////////////////////////////////////////////////////////
337 // ///////////////////////////////////////////////////////////////////////////////////////////////
338 // ///////////////////////////////////////////////////////////////////////////////////////////////
339 // ///////////////////////////////////////////////////////////////////////////////////////////////
340 // ///////////////////////////////////////////////////////////////////////////////////////////////
341 // ///////////////////////////////////////////////////////////////////////////////////////////////
344 * Scroll accordion pane to make
345 * @param $element focused element.
348 static _scrollIntoView($element) {
349 const $pane = $element.closest('.ui-accordion-content');
350 const paneScrollTop = $pane.scrollTop();
351 const paneHeight = $pane.height();
352 const paneBottom = paneScrollTop + paneHeight;
353 const elementTop = $element[0].offsetTop - $pane[0].offsetTop;
354 const elementHeight = $element.height();
355 const elementBottom = elementTop + elementHeight;
356 if (elementBottom > paneBottom) {
357 $pane.scrollTop(elementTop);
358 } else if (elementTop < paneScrollTop) {
359 $pane.scrollTop(elementTop);
363 // ///////////////////////////////////////////////////////////////////////////////////////////////
367 * @param id selected message ID.
368 * @param position page coordinates.
370 showActions(id, position) {
372 this.actions.show(id, position);
376 // ///////////////////////////////////////////////////////////////////////////////////////////////
380 * @param id selected message identifier.
383 const model = this.application.getModel();
384 const options = this.application.getOptions();
385 const message = model.getMessageById(id);
386 const notes = (message.notes && (message.notes.length > 0)) ? message.notes[0] : '';
387 const editComplete = function f(p) {
390 const sanitized = Common.sanitizeText(p.text, options, 'notes');
391 message.notes.push(sanitized);
394 this.application.showEditDialog('Notes:', notes, editComplete);
398 /** Element properties. */
399 Designer.propTypes = {
400 application: React.PropTypes.object.isRequired,
403 export default DragDropContext(HTML5Backend)(Designer);