blob: 6b6f5dff70d589750fefb880d5e2d6354292a8a4 [file] [log] [blame]
Simon Hunt8d28a552016-01-11 14:01:02 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Simon Hunt8d28a552016-01-11 14:01:02 -08003 *
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 or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Layer -- Dialog Service
19
20 Builds on the panel service to provide dialog functionality.
21 */
22(function () {
23 'use strict';
24
25 // injected refs
Simon Hunt5c3ed732017-07-20 19:03:28 +000026 var $log, $window, fs, ps, bns, ks;
Simon Hunt8d28a552016-01-11 14:01:02 -080027
28 // configuration
29 var defaultSettings = {
30 width: 300,
Simon Hunt5c3ed732017-07-20 19:03:28 +000031 edge: 'left'
Simon Hunt8d28a552016-01-11 14:01:02 -080032 };
33
34 // internal state
Simon Hunt5198f082016-02-04 13:41:17 -080035 var pApi, panel, dApi,
36 keyBindings = {};
Simon Hunt8d28a552016-01-11 14:01:02 -080037
38 // create the dialog; return its API
39 function createDialog(id, opts) {
40 var header, body, footer,
41 settings = angular.extend({}, defaultSettings, opts),
42 p = ps.createPanel(id, settings),
43 cls = opts && opts.cssCls;
44
45 p.classed('dialog', true);
46 if (cls) {
47 p.classed(cls, true);
48 }
49 panel = p;
50
51 function reset() {
52 p.empty();
53 p.append('div').classed('header', true);
54 p.append('div').classed('body', true);
55 p.append('div').classed('footer', true);
56
57 header = p.el().select('.header');
58 body = p.el().select('.body');
59 footer = p.el().select('.footer');
60 }
61
62 function hAppend(x) {
63 if (typeof x === 'string') {
64 return header.append(x);
65 }
66 header.node().appendChild(x.node());
67 return header;
68 }
69
70 function bAppend(x) {
71 if (typeof x === 'string') {
72 return body.append(x);
73 }
74 body.node().appendChild(x.node());
75 return body;
76 }
77
78 function fAppend(x) {
79 if (typeof x === 'string') {
80 return footer.append(x);
81 }
82 footer.node().appendChild(x.node());
83 return footer;
84 }
85
86 function destroy() {
87 ps.destroyPanel(id);
88 }
89
90 return {
91 reset: reset,
92 appendHeader: hAppend,
93 appendBody: bAppend,
94 appendFooter: fAppend,
Simon Hunt5c3ed732017-07-20 19:03:28 +000095 destroy: destroy
Simon Hunt8d28a552016-01-11 14:01:02 -080096 };
97 }
98
Simon Huntb1ced8e2016-05-27 19:34:34 -070099 function makeButton(callback, text, keyName, chained) {
Simon Hunt5198f082016-02-04 13:41:17 -0800100 var cb = fs.isF(callback),
101 key = fs.isS(keyName);
Simon Hunt8d28a552016-01-11 14:01:02 -0800102
103 function invoke() {
104 cb && cb();
Simon Huntb1ced8e2016-05-27 19:34:34 -0700105 if (!chained) {
106 clearBindings();
107 panel.hide();
108 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800109 }
Simon Hunt5198f082016-02-04 13:41:17 -0800110
111 if (key) {
112 keyBindings[key] = invoke;
113 }
114
Simon Hunt8d28a552016-01-11 14:01:02 -0800115 return createDiv('dialog-button')
116 .text(text)
117 .on('click', invoke);
118 }
119
120 function setTitle(title) {
121 if (pApi) {
122 pApi.appendHeader('h2').text(title);
123 }
124 return dApi;
125 }
126
127 function addContent(content) {
128 if (pApi) {
129 pApi.appendBody(content);
130 }
131 return dApi;
132 }
133
Simon Huntb1ced8e2016-05-27 19:34:34 -0700134 function addButton(cb, text, key, chained) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800135 if (pApi) {
Simon Huntb1ced8e2016-05-27 19:34:34 -0700136 pApi.appendFooter(makeButton(cb, text, key, chained));
Simon Hunt8d28a552016-01-11 14:01:02 -0800137 }
138 return dApi;
139 }
140
Simon Huntb1ced8e2016-05-27 19:34:34 -0700141 function _addOk(cb, text, chained) {
142 return addButton(cb, text || 'OK', 'enter', chained);
143 }
Simon Hunt5c3ed732017-07-20 19:03:28 +0000144
Simon Hunte75cf182016-02-05 09:39:45 -0800145 function addOk(cb, text) {
Simon Huntb1ced8e2016-05-27 19:34:34 -0700146 return _addOk(cb, text, false);
147 }
148
149 function addOkChained(cb, text) {
150 return _addOk(cb, text, true);
Simon Hunt5198f082016-02-04 13:41:17 -0800151 }
152
Simon Hunte75cf182016-02-05 09:39:45 -0800153 function addCancel(cb, text) {
154 return addButton(cb, text || 'Cancel', 'esc');
Simon Hunt5198f082016-02-04 13:41:17 -0800155 }
156
157 function clearBindings() {
158 keyBindings = {};
159 ks.dialogKeys();
160 }
161
Simon Hunt8d28a552016-01-11 14:01:02 -0800162 // opens the dialog (creates if necessary)
163 function openDialog(id, opts) {
164 $log.debug('Open DIALOG', id, opts);
165 if (!pApi) {
166 pApi = createDialog(id, opts);
167 }
168 pApi.reset();
169 panel.show();
170
171 // return the dialog object API
172 dApi = {
173 setTitle: setTitle,
174 addContent: addContent,
Simon Hunt5198f082016-02-04 13:41:17 -0800175 addButton: addButton,
176 addOk: addOk,
Simon Huntb1ced8e2016-05-27 19:34:34 -0700177 addOkChained: addOkChained,
Simon Hunt5198f082016-02-04 13:41:17 -0800178 addCancel: addCancel,
179 bindKeys: function () {
180 ks.dialogKeys(keyBindings);
Simon Hunt5c3ed732017-07-20 19:03:28 +0000181 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800182 };
183 return dApi;
184 }
185
186 // closes the dialog (destroying panel)
187 function closeDialog() {
188 $log.debug('Close DIALOG');
189 if (pApi) {
Simon Hunt5198f082016-02-04 13:41:17 -0800190 clearBindings();
Simon Hunt8d28a552016-01-11 14:01:02 -0800191 panel.hide();
192 pApi.destroy();
193 pApi = null;
194 dApi = null;
195 }
196 }
197
198 // creates a detached div, returning D3 selection
199 // optional CSS class may be provided
200 function createDiv(cls) {
201 var div = d3.select(document.createElement('div'));
202 if (cls) {
203 div.classed(cls, true);
204 }
205 return div;
206 }
207
208 angular.module('onosLayer')
209 .factory('DialogService',
Simon Hunt5c3ed732017-07-20 19:03:28 +0000210 ['$log', '$window', 'FnService', 'PanelService', 'ButtonService',
211 'KeyService',
Simon Hunt8d28a552016-01-11 14:01:02 -0800212
Simon Hunt5c3ed732017-07-20 19:03:28 +0000213 // TODO: for now, $window is not used, but we should provide an option
214 // to center the dialog on the window.
Simon Hunt8d28a552016-01-11 14:01:02 -0800215
Simon Hunt5c3ed732017-07-20 19:03:28 +0000216 function (_$log_, _$window_, _fs_, _ps_, _bns_, _ks_) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800217 $log = _$log_;
Simon Hunt5c3ed732017-07-20 19:03:28 +0000218 $window = _$window_;
Simon Hunt8d28a552016-01-11 14:01:02 -0800219 fs = _fs_;
220 ps = _ps_;
Simon Hunt5c3ed732017-07-20 19:03:28 +0000221 bns = _bns_;
Simon Hunt5198f082016-02-04 13:41:17 -0800222 ks = _ks_;
Simon Hunt8d28a552016-01-11 14:01:02 -0800223
224 return {
225 openDialog: openDialog,
226 closeDialog: closeDialog,
Simon Hunt5c3ed732017-07-20 19:03:28 +0000227 createDiv: createDiv
Simon Hunt8d28a552016-01-11 14:01:02 -0800228 };
229 }]);
Simon Hunt5c3ed732017-07-20 19:03:28 +0000230
Simon Hunt8d28a552016-01-11 14:01:02 -0800231}());