Committed by
Gerrit Code Review
Simplified Custom View code (ui archetype).
Change-Id: Ia9d1f1023f287653d00abc3a2f9cf7498f3875e0
Showing
4 changed files
with
101 additions
and
283 deletions
| ... | @@ -22,165 +22,56 @@ import com.fasterxml.jackson.databind.node.ObjectNode; | ... | @@ -22,165 +22,56 @@ import com.fasterxml.jackson.databind.node.ObjectNode; |
| 22 | import com.google.common.collect.ImmutableSet; | 22 | import com.google.common.collect.ImmutableSet; |
| 23 | import org.onosproject.ui.RequestHandler; | 23 | import org.onosproject.ui.RequestHandler; |
| 24 | import org.onosproject.ui.UiMessageHandler; | 24 | import org.onosproject.ui.UiMessageHandler; |
| 25 | -import org.onosproject.ui.table.TableModel; | ||
| 26 | -import org.onosproject.ui.table.TableRequestHandler; | ||
| 27 | import org.slf4j.Logger; | 25 | import org.slf4j.Logger; |
| 28 | import org.slf4j.LoggerFactory; | 26 | import org.slf4j.LoggerFactory; |
| 29 | 27 | ||
| 30 | -import java.lang.Override; | ||
| 31 | -import java.util.ArrayList; | ||
| 32 | import java.util.Collection; | 28 | import java.util.Collection; |
| 33 | -import java.util.List; | ||
| 34 | 29 | ||
| 35 | /** | 30 | /** |
| 36 | * Skeletal ONOS UI Custom-View message handler. | 31 | * Skeletal ONOS UI Custom-View message handler. |
| 37 | */ | 32 | */ |
| 38 | public class AppUiMessageHandler extends UiMessageHandler { | 33 | public class AppUiMessageHandler extends UiMessageHandler { |
| 39 | - // TODO: reduce the code down to just the custom view example | ||
| 40 | 34 | ||
| 41 | private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest"; | 35 | private static final String SAMPLE_CUSTOM_DATA_REQ = "sampleCustomDataRequest"; |
| 42 | private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse"; | 36 | private static final String SAMPLE_CUSTOM_DATA_RESP = "sampleCustomDataResponse"; |
| 43 | - private static final String SAMPLE_CUSTOMS = "sampleCustoms"; | ||
| 44 | 37 | ||
| 45 | - private static final String SAMPLE_CUSTOM_DETAIL_REQ = "sampleCustomDetailsRequest"; | 38 | + private static final String NUMBER = "number"; |
| 46 | - private static final String SAMPLE_CUSTOM_DETAIL_RESP = "sampleCustomDetailsResponse"; | 39 | + private static final String SQUARE = "square"; |
| 47 | - private static final String DETAILS = "details"; | 40 | + private static final String CUBE = "cube"; |
| 48 | - | 41 | + private static final String MESSAGE = "message"; |
| 49 | - private static final String ID = "id"; | 42 | + private static final String MSG_FORMAT = "Next incrememt is %d units"; |
| 50 | - private static final String LABEL = "label"; | ||
| 51 | - private static final String CODE = "code"; | ||
| 52 | - private static final String COMMENT = "comment"; | ||
| 53 | - private static final String RESULT = "result"; | ||
| 54 | - | ||
| 55 | - private static final String[] COLUMN_IDS = { ID, LABEL, CODE }; | ||
| 56 | 43 | ||
| 57 | private final Logger log = LoggerFactory.getLogger(getClass()); | 44 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 58 | 45 | ||
| 46 | + private long someNumber = 1; | ||
| 47 | + private long someIncrement = 1; | ||
| 59 | 48 | ||
| 60 | @Override | 49 | @Override |
| 61 | protected Collection<RequestHandler> createRequestHandlers() { | 50 | protected Collection<RequestHandler> createRequestHandlers() { |
| 62 | return ImmutableSet.of( | 51 | return ImmutableSet.of( |
| 63 | - new SampleCustomDataRequestHandler(), | 52 | + new SampleCustomDataRequestHandler() |
| 64 | - new SampleCustomDetailRequestHandler() | ||
| 65 | ); | 53 | ); |
| 66 | } | 54 | } |
| 67 | 55 | ||
| 68 | - // handler for sample table requests | 56 | + // handler for sample data requests |
| 69 | - private final class SampleCustomDataRequestHandler extends TableRequestHandler { | 57 | + private final class SampleCustomDataRequestHandler extends RequestHandler { |
| 70 | 58 | ||
| 71 | private SampleCustomDataRequestHandler() { | 59 | private SampleCustomDataRequestHandler() { |
| 72 | - super(SAMPLE_CUSTOM_DATA_REQ, SAMPLE_CUSTOM_DATA_RESP, SAMPLE_CUSTOMS); | 60 | + super(SAMPLE_CUSTOM_DATA_REQ); |
| 73 | - } | ||
| 74 | - | ||
| 75 | - @Override | ||
| 76 | - protected String[] getColumnIds() { | ||
| 77 | - return COLUMN_IDS; | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | - @Override | ||
| 81 | - protected void populateTable(TableModel tm, ObjectNode payload) { | ||
| 82 | - // === set custom column cell formatters/comparators if need be... | ||
| 83 | - // tm.setFormatter(CODE, new CodeFormatter()); | ||
| 84 | - // tm.setComparator(CODE, new CodeComparator()); | ||
| 85 | - | ||
| 86 | - // === retrieve table row items from some service... | ||
| 87 | - // SomeService ss = get(SomeService.class); | ||
| 88 | - // List<Item> items = ss.getItems() | ||
| 89 | - | ||
| 90 | - // fake data for demonstration purposes... | ||
| 91 | - List<Item> items = getItems(); | ||
| 92 | - for (Item item: items) { | ||
| 93 | - populateRow(tm.addRow(), item); | ||
| 94 | - } | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - private void populateRow(TableModel.Row row, Item item) { | ||
| 98 | - row.cell(ID, item.id()) | ||
| 99 | - .cell(LABEL, item.label()) | ||
| 100 | - .cell(CODE, item.code()); | ||
| 101 | - } | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - | ||
| 105 | - // handler for sample item details requests | ||
| 106 | - private final class SampleCustomDetailRequestHandler extends RequestHandler { | ||
| 107 | - | ||
| 108 | - private SampleCustomDetailRequestHandler() { | ||
| 109 | - super(SAMPLE_CUSTOM_DETAIL_REQ); | ||
| 110 | } | 61 | } |
| 111 | 62 | ||
| 112 | @Override | 63 | @Override |
| 113 | public void process(long sid, ObjectNode payload) { | 64 | public void process(long sid, ObjectNode payload) { |
| 114 | - String id = string(payload, ID, "(none)"); | 65 | + someIncrement++; |
| 115 | - | 66 | + someNumber += someIncrement; |
| 116 | - // SomeService ss = get(SomeService.class); | 67 | + log.debug("Computing data for {}...", someNumber); |
| 117 | - // Item item = ss.getItemDetails(id) | ||
| 118 | 68 | ||
| 119 | - // fake data for demonstration purposes... | 69 | + ObjectNode result = objectNode(); |
| 120 | - Item item = getItem(id); | 70 | + result.put(NUMBER, someNumber); |
| 121 | - | 71 | + result.put(SQUARE, someNumber * someNumber); |
| 122 | - ObjectNode rootNode = MAPPER.createObjectNode(); | 72 | + result.put(CUBE, someNumber * someNumber * someNumber); |
| 123 | - ObjectNode data = MAPPER.createObjectNode(); | 73 | + result.put(MESSAGE, String.format(MSG_FORMAT, someIncrement + 1)); |
| 124 | - rootNode.set(DETAILS, data); | 74 | + sendMessage(SAMPLE_CUSTOM_DATA_RESP, 0, result); |
| 125 | - | ||
| 126 | - if (item == null) { | ||
| 127 | - rootNode.put(RESULT, "Item with id '" + id + "' not found"); | ||
| 128 | - log.warn("attempted to get item detail for id '{}'", id); | ||
| 129 | - | ||
| 130 | - } else { | ||
| 131 | - rootNode.put(RESULT, "Found item with id '" + id + "'"); | ||
| 132 | - | ||
| 133 | - data.put(ID, item.id()); | ||
| 134 | - data.put(LABEL, item.label()); | ||
| 135 | - data.put(CODE, item.code()); | ||
| 136 | - data.put(COMMENT, "Some arbitrary comment"); | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - sendMessage(SAMPLE_CUSTOM_DETAIL_RESP, 0, rootNode); | ||
| 140 | - } | ||
| 141 | } | 75 | } |
| 142 | - | ||
| 143 | - | ||
| 144 | - // =================================================================== | ||
| 145 | - // NOTE: The code below this line is to create fake data for this | ||
| 146 | - // sample code. Normally you would use existing services to | ||
| 147 | - // provide real data. | ||
| 148 | - | ||
| 149 | - // Lookup a single item. | ||
| 150 | - private static Item getItem(String id) { | ||
| 151 | - // We realize this code is really inefficient, but | ||
| 152 | - // it suffices for our purposes of demonstration... | ||
| 153 | - for (Item item : getItems()) { | ||
| 154 | - if (item.id().equals(id)) { | ||
| 155 | - return item; | ||
| 156 | - } | ||
| 157 | - } | ||
| 158 | - return null; | ||
| 159 | - } | ||
| 160 | - | ||
| 161 | - // Produce a list of items. | ||
| 162 | - private static List<Item> getItems() { | ||
| 163 | - List<Item> items = new ArrayList<>(); | ||
| 164 | - items.add(new Item("item-1", "foo", 42)); | ||
| 165 | - items.add(new Item("item-2", "bar", 99)); | ||
| 166 | - items.add(new Item("item-3", "baz", 65)); | ||
| 167 | - return items; | ||
| 168 | - } | ||
| 169 | - | ||
| 170 | - // Simple model class to provide sample data | ||
| 171 | - private static class Item { | ||
| 172 | - private final String id; | ||
| 173 | - private final String label; | ||
| 174 | - private final int code; | ||
| 175 | - | ||
| 176 | - Item(String id, String label, int code) { | ||
| 177 | - this.id = id; | ||
| 178 | - this.label = label; | ||
| 179 | - this.code = code; | ||
| 180 | - } | ||
| 181 | - | ||
| 182 | - String id() { return id; } | ||
| 183 | - String label() { return label; } | ||
| 184 | - int code() { return code; } | ||
| 185 | } | 76 | } |
| 186 | } | 77 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -/* css for sample app view */ | 1 | +/* css for sample app custom view */ |
| 2 | 2 | ||
| 3 | -#ov-sample h2 { | 3 | +#ov-sample-custom { |
| 4 | - display: inline-block; | 4 | + padding: 20px; |
| 5 | +} | ||
| 6 | +.light #ov-sample-custom { | ||
| 7 | + color: navy; | ||
| 8 | +} | ||
| 9 | +.dark #ov-sample-custom { | ||
| 10 | + color: #88f; | ||
| 5 | } | 11 | } |
| 6 | 12 | ||
| 7 | -/* Panel Styling */ | 13 | +#ov-sample-custom .button-panel { |
| 8 | -#ov-sample-custom-item-details-panel.floatpanel { | 14 | + margin: 10px; |
| 9 | - position: absolute; | 15 | + width: 200px; |
| 10 | - top: 115px; | ||
| 11 | } | 16 | } |
| 12 | 17 | ||
| 13 | -.light #ov-sample-custom-item-details-panel.floatpanel { | 18 | +.light #ov-sample-custom .button-panel { |
| 14 | - background-color: rgb(229, 234, 237); | 19 | + background-color: #ccf; |
| 15 | } | 20 | } |
| 16 | -.dark #ov-sample-custom-item-details-panel.floatpanel { | 21 | +.dark #ov-sample-custom .button-panel { |
| 17 | - background-color: #3A4042; | 22 | + background-color: #444; |
| 18 | } | 23 | } |
| 19 | 24 | ||
| 20 | -#ov-sample-custom-item-details-panel h3 { | 25 | +#ov-sample-custom .my-button { |
| 21 | - margin: 0; | 26 | + cursor: pointer; |
| 22 | - font-size: large; | 27 | + padding: 4px; |
| 28 | + text-align: center; | ||
| 23 | } | 29 | } |
| 24 | 30 | ||
| 25 | -#ov-sample-custom-item-details-panel h4 { | 31 | +.light #ov-sample-custom .my-button { |
| 26 | - margin: 0; | 32 | + color: white; |
| 33 | + background-color: #99d; | ||
| 34 | +} | ||
| 35 | +.dark #ov-sample-custom .my-button { | ||
| 36 | + color: black; | ||
| 37 | + background-color: #aaa; | ||
| 27 | } | 38 | } |
| 28 | 39 | ||
| 29 | -#ov-sample-custom-item-details-panel td { | 40 | +#ov-sample-custom .number { |
| 30 | - padding: 5px; | 41 | + font-size: 140%; |
| 42 | + text-align: right; | ||
| 31 | } | 43 | } |
| 32 | -#ov-sample-custom-item-details-panel td.label { | 44 | + |
| 45 | +#ov-sample-custom .quote { | ||
| 46 | + margin: 10px 20px; | ||
| 33 | font-style: italic; | 47 | font-style: italic; |
| 34 | - opacity: 0.8; | ||
| 35 | } | 48 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | <!-- partial HTML --> | 1 | <!-- partial HTML --> |
| 2 | <div id="ov-sample-custom"> | 2 | <div id="ov-sample-custom"> |
| 3 | - <div class="tabular-header"> | 3 | + <div class="button-panel"> |
| 4 | - <h2>Items ({{tableData.length}} total)</h2> | 4 | + <div class="my-button" ng-click="getData()"> |
| 5 | - <div class="ctrl-btns"> | 5 | + Fetch Data |
| 6 | - <div class="refresh" ng-class="{active: autoRefresh}" | ||
| 7 | - icon icon-id="refresh" icon-size="36" | ||
| 8 | - tooltip tt-msg="autoRefreshTip" | ||
| 9 | - ng-click="toggleRefresh()"></div> | ||
| 10 | </div> | 6 | </div> |
| 11 | </div> | 7 | </div> |
| 12 | 8 | ||
| 13 | - <div class="summary-list" onos-table-resize> | 9 | + <div class="data-panel"> |
| 14 | - | ||
| 15 | - <div class="table-header" onos-sortable-header> | ||
| 16 | <table> | 10 | <table> |
| 17 | <tr> | 11 | <tr> |
| 18 | - <td colId="id" sortable>Item ID </td> | 12 | + <td> Number </td> |
| 19 | - <td colId="label" sortable>Label </td> | 13 | + <td class="number"> {{data.number}} </td> |
| 20 | - <td colId="code" sortable>Code </td> | ||
| 21 | </tr> | 14 | </tr> |
| 22 | - </table> | 15 | + <tr> |
| 23 | - </div> | 16 | + <td> Square </td> |
| 24 | - | 17 | + <td class="number"> {{data.square}} </td> |
| 25 | - <div class="table-body"> | ||
| 26 | - <table> | ||
| 27 | - <tr ng-if="!tableData.length" class="no-data"> | ||
| 28 | - <td colspan="3"> | ||
| 29 | - No Items found | ||
| 30 | - </td> | ||
| 31 | </tr> | 18 | </tr> |
| 32 | - | 19 | + <tr> |
| 33 | - <tr ng-repeat="item in tableData track by $index" | 20 | + <td> Cube </td> |
| 34 | - ng-click="selectCallback($event, item)" | 21 | + <td class="number"> {{data.cube}} </td> |
| 35 | - ng-class="{selected: item.id === selId}"> | ||
| 36 | - <td>{{item.id}}</td> | ||
| 37 | - <td>{{item.label}}</td> | ||
| 38 | - <td>{{item.code}}</td> | ||
| 39 | </tr> | 22 | </tr> |
| 40 | </table> | 23 | </table> |
| 41 | - </div> | ||
| 42 | 24 | ||
| 25 | + <p> | ||
| 26 | + A message from our sponsors: | ||
| 27 | + </p> | ||
| 28 | + <p> | ||
| 29 | + <span class="quote">{{data.message}} </span> | ||
| 30 | + </p> | ||
| 43 | </div> | 31 | </div> |
| 44 | - | ||
| 45 | - <ov-sample-custom-item-details-panel></ov-sample-custom-item-details-panel> | ||
| 46 | </div> | 32 | </div> | ... | ... |
| ... | @@ -3,139 +3,67 @@ | ... | @@ -3,139 +3,67 @@ |
| 3 | 'use strict'; | 3 | 'use strict'; |
| 4 | 4 | ||
| 5 | // injected refs | 5 | // injected refs |
| 6 | - var $log, $scope, fs, wss; | 6 | + var $log, $scope, wss, ks; |
| 7 | 7 | ||
| 8 | // constants | 8 | // constants |
| 9 | - var detailsReq = 'sampleCustomDetailsRequest', | 9 | + var dataReq = 'sampleCustomDataRequest', |
| 10 | - detailsResp = 'sampleCustomDetailsResponse', | 10 | + dataResp = 'sampleCustomDataResponse'; |
| 11 | - pName = 'ov-sample-custom-item-details-panel', | ||
| 12 | 11 | ||
| 13 | - propOrder = ['id', 'label', 'code'], | 12 | + function addKeyBindings() { |
| 14 | - friendlyProps = ['Item ID', 'Item Label', 'Special Code']; | 13 | + var map = { |
| 14 | + space: [getData, 'Fetch data from server'], | ||
| 15 | 15 | ||
| 16 | + _helpFormat: [ | ||
| 17 | + ['space'] | ||
| 18 | + ] | ||
| 19 | + }; | ||
| 16 | 20 | ||
| 17 | - function addProp(tbody, index, value) { | 21 | + ks.keyBindings(map); |
| 18 | - var tr = tbody.append('tr'); | ||
| 19 | - | ||
| 20 | - function addCell(cls, txt) { | ||
| 21 | - tr.append('td').attr('class', cls).html(txt); | ||
| 22 | } | 22 | } |
| 23 | - addCell('label', friendlyProps[index] + ' :'); | ||
| 24 | - addCell('value', value); | ||
| 25 | - } | ||
| 26 | - | ||
| 27 | - function populatePanel(panel) { | ||
| 28 | - var title = panel.append('h3'), | ||
| 29 | - tbody = panel.append('table').append('tbody'); | ||
| 30 | - | ||
| 31 | - title.text('Item Details'); | ||
| 32 | - | ||
| 33 | - propOrder.forEach(function (prop, i) { | ||
| 34 | - addProp(tbody, i, $scope.panelDetails[prop]); | ||
| 35 | - }); | ||
| 36 | 23 | ||
| 37 | - panel.append('hr'); | 24 | + function getData() { |
| 38 | - panel.append('h4').text('Comments'); | 25 | + wss.sendEvent(dataReq); |
| 39 | - panel.append('p').text($scope.panelDetails.comment); | ||
| 40 | } | 26 | } |
| 41 | 27 | ||
| 42 | - function respDetailsCb(data) { | 28 | + function respDataCb(data) { |
| 43 | - $scope.panelDetails = data.details; | 29 | + $scope.data = data; |
| 44 | $scope.$apply(); | 30 | $scope.$apply(); |
| 45 | } | 31 | } |
| 46 | 32 | ||
| 33 | + | ||
| 47 | angular.module('ovSampleCustom', []) | 34 | angular.module('ovSampleCustom', []) |
| 48 | .controller('OvSampleCustomCtrl', | 35 | .controller('OvSampleCustomCtrl', |
| 49 | - ['$log', '$scope', 'TableBuilderService', | 36 | + ['$log', '$scope', 'WebSocketService', 'KeyService', |
| 50 | - 'FnService', 'WebSocketService', | ||
| 51 | 37 | ||
| 52 | - function (_$log_, _$scope_, tbs, _fs_, _wss_) { | 38 | + function (_$log_, _$scope_, _wss_, _ks_) { |
| 53 | $log = _$log_; | 39 | $log = _$log_; |
| 54 | $scope = _$scope_; | 40 | $scope = _$scope_; |
| 55 | - fs = _fs_; | ||
| 56 | wss = _wss_; | 41 | wss = _wss_; |
| 42 | + ks = _ks_; | ||
| 57 | 43 | ||
| 58 | var handlers = {}; | 44 | var handlers = {}; |
| 59 | - $scope.panelDetails = {}; | 45 | + $scope.data = {}; |
| 60 | 46 | ||
| 61 | - // details response handler | 47 | + // data response handler |
| 62 | - handlers[detailsResp] = respDetailsCb; | 48 | + handlers[dataResp] = respDataCb; |
| 63 | wss.bindHandlers(handlers); | 49 | wss.bindHandlers(handlers); |
| 64 | 50 | ||
| 65 | - // custom selection callback | 51 | + addKeyBindings(); |
| 66 | - function selCb($event, row) { | ||
| 67 | - if ($scope.selId) { | ||
| 68 | - wss.sendEvent(detailsReq, { id: row.id }); | ||
| 69 | - } else { | ||
| 70 | - $scope.hidePanel(); | ||
| 71 | - } | ||
| 72 | - $log.debug('Got a click on:', row); | ||
| 73 | - } | ||
| 74 | 52 | ||
| 75 | - // TableBuilderService creating a table for us | 53 | + // custom click handler |
| 76 | - tbs.buildTable({ | 54 | + $scope.getData = getData; |
| 77 | - scope: $scope, | 55 | + |
| 78 | - tag: 'sampleCustom', | 56 | + // get data the first time... |
| 79 | - selCb: selCb | 57 | + getData(); |
| 80 | - }); | ||
| 81 | 58 | ||
| 82 | // cleanup | 59 | // cleanup |
| 83 | $scope.$on('$destroy', function () { | 60 | $scope.$on('$destroy', function () { |
| 84 | wss.unbindHandlers(handlers); | 61 | wss.unbindHandlers(handlers); |
| 62 | + ks.unbindKeys(); | ||
| 85 | $log.log('OvSampleCustomCtrl has been destroyed'); | 63 | $log.log('OvSampleCustomCtrl has been destroyed'); |
| 86 | }); | 64 | }); |
| 87 | 65 | ||
| 88 | $log.log('OvSampleCustomCtrl has been created'); | 66 | $log.log('OvSampleCustomCtrl has been created'); |
| 89 | - }]) | ||
| 90 | - | ||
| 91 | - .directive('ovSampleCustomItemDetailsPanel', ['PanelService', 'KeyService', | ||
| 92 | - function (ps, ks) { | ||
| 93 | - return { | ||
| 94 | - restrict: 'E', | ||
| 95 | - link: function (scope, element, attrs) { | ||
| 96 | - // insert details panel with PanelService | ||
| 97 | - // create the panel | ||
| 98 | - var panel = ps.createPanel(pName, { | ||
| 99 | - width: 200, | ||
| 100 | - margin: 20, | ||
| 101 | - hideMargin: 0 | ||
| 102 | - }); | ||
| 103 | - panel.hide(); | ||
| 104 | - scope.hidePanel = function () { panel.hide(); }; | ||
| 105 | - | ||
| 106 | - function closePanel() { | ||
| 107 | - if (panel.isVisible()) { | ||
| 108 | - $scope.selId = null; | ||
| 109 | - panel.hide(); | ||
| 110 | - return true; | ||
| 111 | - } | ||
| 112 | - return false; | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - // create key bindings to handle panel | ||
| 116 | - ks.keyBindings({ | ||
| 117 | - esc: [closePanel, 'Close the details panel'], | ||
| 118 | - _helpFormat: ['esc'] | ||
| 119 | - }); | ||
| 120 | - ks.gestureNotes([ | ||
| 121 | - ['click', 'Select a row to show item details'] | ||
| 122 | - ]); | ||
| 123 | - | ||
| 124 | - // update the panel's contents when the data is changed | ||
| 125 | - scope.$watch('panelDetails', function () { | ||
| 126 | - if (!fs.isEmptyObject(scope.panelDetails)) { | ||
| 127 | - panel.empty(); | ||
| 128 | - populatePanel(panel); | ||
| 129 | - panel.show(); | ||
| 130 | - } | ||
| 131 | - }); | ||
| 132 | - | ||
| 133 | - // cleanup on destroyed scope | ||
| 134 | - scope.$on('$destroy', function () { | ||
| 135 | - ks.unbindKeys(); | ||
| 136 | - ps.destroyPanel(pName); | ||
| 137 | - }); | ||
| 138 | - } | ||
| 139 | - }; | ||
| 140 | }]); | 67 | }]); |
| 68 | + | ||
| 141 | }()); | 69 | }()); | ... | ... |
-
Please register or login to post a comment