4 'app/yangui/services/yangui.services',
5 'app/yangui/services/history.services',
6 'app/yangui/services/request-data.services',
7 'app/yangui/services/custom-funct-unsetter.services',
8 'app/yangui/services/plugin-handler.services',
9 'app/yangui/services/mount-points-connector.services',
10 'app/yangui/services/design-utils.services',
11 'app/yangui/services/handle-file.services',
12 'app/yangui/directives/abn_tree.directive',
13 'app/yangui/directives/sticky.directive',
14 'app/yangui/directives/read_file.directive',
15 'app/yangui/directives/ui-codemirror.directive',
16 'app/yangui/controllers/api/augmentation-modal.controller',
17 'app/yangui/controllers/api/case.controller',
18 'app/yangui/controllers/api/coll-box.controller',
19 'app/yangui/controllers/api/container.controller',
20 'app/yangui/controllers/api/filter.controller',
21 'app/yangui/controllers/api/filter-type.controller',
22 'app/yangui/controllers/api/filter-type-bit.controller',
23 'app/yangui/controllers/api/filter-type-empty.controller',
24 'app/yangui/controllers/api/filter-type-enum.controller',
25 'app/yangui/controllers/parameters/history-param.controller',
26 'app/yangui/controllers/api/choice.controller',
27 'app/yangui/controllers/api/input.controller',
28 'app/yangui/controllers/api/leaf.controller',
29 'app/yangui/controllers/api/leaf-list.controller',
30 'app/yangui/controllers/api/list.controller',
31 'app/yangui/controllers/api/output.controller',
32 'app/yangui/controllers/parameters/param-box.controller',
33 'app/yangui/controllers/parameters/params-view.controller',
34 'app/yangui/controllers/history/req-in-history.controller',
35 'app/yangui/controllers/history/request-history.controller',
36 'app/yangui/controllers/api/rpc.controller',
37 'app/yangui/controllers/api/type.controller',
38 'app/yangui/controllers/api/type-bit.controller',
39 'app/yangui/controllers/api/type-empty.controller',
40 'app/yangui/controllers/api/type-enum.controller',
44 angular.module('app.yangui').controller('YanguiCtrl', YanguiCtrl);
46 YanguiCtrl.$inject = ['$scope', '$timeout', '$rootScope', '$http', '$filter', 'YangUtilsRestangularService',
47 'YangUtilsService', 'RequestBuilderService', 'CustomFuncService', 'PluginHandlerService', 'PathUtilsService',
48 'constants', 'NodeWrapperService', 'MountPointsConnectorService', 'DesignUtilsService',
49 'EventDispatcherService', 'SyncService', 'CustomFunctUnsetterService', 'HistoryService', 'DataBackupService',
50 'ParsingJsonService'];
52 // todo: comment the whole controller
53 function YanguiCtrl($scope, $timeout, $rootScope, $http, $filter, YangUtilsRestangularService, YangUtilsService,
54 RequestBuilderService, CustomFuncService, PluginHandlerService, PathUtilsService, constants,
55 NodeWrapperService, MountPointsConnectorService, DesignUtilsService, EventDispatcherService,
56 SyncService, CustomFunctUnsetterService, HistoryService, DataBackupService, ParsingJsonService){
59 $rootScope.section_logo = 'assets/images/logo_yangui.gif';
61 $scope.constants = constants;
62 $scope.currentPath = 'src/app/yangui/views/';
63 $scope.defaultTreeName = $filter('translate')('YANGUI_ROOT');
64 $scope.filterConstants = constants;
65 $scope.filterRootNode = null;
72 $scope.mpSynchronizer = SyncService.generateObj();
73 $scope.previewDelay = 2000;
74 $scope.previewValidity = true;
75 $scope.selCustFunct = null;
76 $scope.selCustFunctButts = [];
81 $scope.treeName = $scope.defaultTreeName;
85 processingModulesErrorCallback: $scope.processingModulesErrorCallback,
86 requestErrorCallback: requestErrorCallback,
87 requestSuccessCallback: requestSuccessCallback,
88 requestWorkingCallback: requestWorkingCallback,
89 processingModulesCallback: processingModulesCallback,
90 processingModulesSuccessCallback: $scope.processingModulesSuccessCallback,
93 $scope.buildPreview = buildPreview;
94 $scope.buildRoot = buildRoot;
95 $scope.changePathInPreview = changePathInPreview;
96 $scope.checkAddingListElement = checkAddingListElement;
97 $scope.close_popup = close_popup;
98 $scope.copyReqPathToClipboard = copyReqPathToClipboard;
99 $scope.dismissStatus = dismissStatus;
100 $scope.executeCustFunctionality = executeCustFunctionality;
101 $scope.executeOperation = executeOperation;
102 $scope.fallback = fallback;
103 $scope.fillApi = fillApi;
104 $scope.fillApiAndData = fillApiAndData;
105 $scope.fillApiData = fillApiData;
106 $scope.fillMPApi = fillMPApi;
107 $scope.fillNodeData = fillNodeData;
108 $scope.fillStandardApi = fillStandardApi;
109 $scope.getNodeName = getNodeName;
110 $scope.hidePreview = hidePreview;
111 $scope.initMp = initMp;
112 $scope.invalidatePreview = invalidatePreview;
113 $scope.isMountPointSelected = isMountPointSelected;
114 $scope.isPreviewValid = isPreviewValid;
115 $scope.loadController = loadController;
116 $scope.parameterizeData = parameterizeData;
117 $scope.preview = preview;
118 $scope.processingModulesErrorCallback = processingModulesErrorCallback;
119 $scope.processingModulesSuccessCallback = processingModulesSuccessCallback;
120 $scope.removeMountPointPath = removeMountPointPath;
121 $scope.selectMP = selectMP;
122 $scope.setApiNode = setApiNode;
123 $scope.setNode = setNode;
124 $scope.setStatusMessage = setStatusMessage;
125 $scope.show_add_data_popup = show_add_data_popup;
126 $scope.showCustFunctButton = showCustFunctButton;
127 $scope.showCustFunctCancelButton = showCustFunctCancelButton;
128 $scope.showModalRequestWin = showModalRequestWin;
129 $scope.showPreview = showPreview;
130 $scope.showTabs = showTabs;
132 $scope.unsetCustomFunctionality = unsetCustomFunctionality;
133 $scope.validatePreview = validatePreview;
135 $scope.$on('SET_SCOPE_TREE_ROWS', setScopeTreeRows);
137 var mountPrefix = constants.MPPREFIX;
139 EventDispatcherService.registerHandler(constants.EV_SRC_MAIN, statusChangeEvent);
140 EventDispatcherService.registerHandler(constants.EV_FILL_PATH, fillPathIdentifiersByKey);
141 EventDispatcherService.registerHandler(constants.EV_LIST_CHANGED, fillPathIdentifiersByListData);
143 $scope.loadController();
145 function showTabs(tabs, tabName){
146 for (var prop in tabs){
147 tabs[prop] = tabName === prop;
150 DesignUtilsService.triggerWindowResize(100);
153 function statusChangeEvent(messages) {
154 // var newMessage = $scope.status.rawMsg + '\r\n' + messages.join('\r\n');
155 processingModulesCallback(messages[0]);
158 function fillPathIdentifiersByKey(inputs) {
159 var node = inputs[0],
160 value = inputs[1] || '';
162 // or $scope.node === node.parent?
163 if ($scope.selSubApi && node.parent && $scope.selSubApi.node.id === node.parent.id) {
164 var identifiers = $scope.selSubApi.pathArray[$scope.selSubApi.pathArray.length - 1].identifiers;
165 PathUtilsService.fillIdentifiers(identifiers, node.label, value);
169 function fillPathIdentifiersByListData(inputs) {
170 var node = inputs[0];
172 if ($scope.selSubApi && node && $scope.selSubApi.node.id === node.id) { // or $scope.node === node.parent?
173 var identifiers = $scope.selSubApi.pathArray[$scope.selSubApi.pathArray.length - 1].identifiers,
176 keys.forEach(function (key) {
177 PathUtilsService.fillIdentifiers(identifiers, key.label, key.value);
182 function parameterizeData(path) {
183 var parameterList = null;
185 $scope.$broadcast('GET_PARAMETER_LIST', function (parameters) {
186 parameterList = parameters;
189 return HistoryService.parametrizeData(parameterList.list, path);
192 function processingModulesCallback(e) {
196 msg: 'PROCESSING_MODULES',
201 function processingModulesSuccessCallback(e) {
204 msg: 'PROCESSING_MODULES_SUCCESS',
209 function processingModulesErrorCallback(e) {
212 msg: 'PROCESSING_MODULES_ERROR',
217 function requestWorkingCallback() {
225 function requestSuccessCallback() {
232 function setStatusMessage(type, msg, e){
240 function requestErrorCallback(e, resp) {
241 var errorMessages = YangUtilsService.errorMessages,
242 msg = errorMessages.method[resp.config.method] ?
243 errorMessages.method[resp.config.method][resp.status] ?
244 errorMessages.method[resp.config.method][resp.status] :
251 rawMsg: e.toString(),
255 function setCustFunct(apis) {
256 PluginHandlerService.plugAll($scope.apis, $scope);
259 function removeMountPointPath(pathArray){
260 var mpPathIndex = pathArray.length;
262 pathArray.some(function (pathElem, index) {
263 var isMPElem = pathElem.name === mountPrefix;
271 var pathCopy = pathArray.slice(0, mpPathIndex);
275 function invalidatePreview() {
276 $scope.previewValidity = false;
279 function validatePreview() {
280 $scope.previewValidity = true;
283 function isPreviewValid() {
284 return $scope.previewValidity;
288 if ($scope.isPreviewValid()) {
289 $scope.invalidatePreview();
291 $timeout(function () {
292 $scope.buildPreview();
293 $scope.validatePreview();
294 }, $scope.previewDelay);
298 function buildPreview() {
300 var reqString = $scope.selSubApi.buildApiRequestString(),
304 $scope.node.buildRequest(RequestBuilderService, requestData, $scope.node.module);
305 // update request data (remove envelope from POST request etc.)
306 requestData = YangUtilsService.prepareRequestData(
308 $scope.selectedOperation,
313 var jsonRequestData = requestData ? JSON.stringify(requestData, null, 4) : '';
315 $scope.previewValue = $scope.selApi.basePath + reqString;
316 $scope.previewValue = $scope.previewValue + '\r\n' + jsonRequestData;
318 $scope.previewValue = '';
322 function getNodeName(localeLabel, label) {
323 var localeResult = $filter('translate')(localeLabel);
324 return localeResult.indexOf(constants.LOCALE_PREFIX) === 0 ? label : localeResult;
327 function showCustFunctButton() {
328 return $scope.selCustFunct === null;
331 function showCustFunctCancelButton() {
332 return $scope.selCustFunct !== null;
335 function unsetCustomFunctionality() {
336 if ($scope.selCustFunct) {
337 CustomFunctUnsetterService.unset($scope.selCustFunct, $scope);
339 $scope.selCustFunct = null;
340 $scope.treeName = $scope.defaultTreeName;
341 $scope.selCustFunctButts = [];
344 function loadApis() {
346 $scope.allNodes = [];
347 $scope.treeApis = [];
348 $scope.augmentations = {};
350 processingModulesCallback();
351 YangUtilsService.generateNodesToApis(function (apis, allNodes, augGroups) {
353 $scope.allNodes = allNodes;
354 $scope.augmentations = augGroups;
355 console.info('got data', $scope.apis, $scope.allNodes, $scope.augmentations);
356 $scope.treeApis = YangUtilsService.generateApiTreeData(apis);
357 console.info('tree api', $scope.treeApis);
358 $scope.processingModulesSuccessCallback();
360 setCustFunct($scope.apis);
361 $scope.$broadcast('LOAD_REQ_DATA');
363 $scope.processingModulesErrorCallback(e);
367 function isMountPointSelected() {
368 return $scope.selCustFunct.label === 'YANGUI_CUST_MOUNT_POINTS';
371 function dismissStatus() {
376 $scope.node = $scope.selSubApi.node;
379 function setApiNode(indexApi, indexSubApi) {
380 $scope.selectedOperation = null;
382 if (indexApi !== undefined && indexSubApi !== undefined ) {
383 $scope.selApi = $scope.apis[indexApi];
384 $scope.selSubApi = $scope.selApi.subApis[indexSubApi];
386 $scope.apiType = $scope.selSubApi.pathArray[0].name === 'operational' ? 'operational/' : '';
387 $scope.node = $scope.selSubApi.node;
388 $scope.filterRootNode = $scope.selSubApi.node;
391 if ($scope.selSubApi && $scope.selSubApi.operations) {
392 $scope.selectedOperation = $scope.selSubApi.operations[0];
395 // TODO: uncomment this broadcast and check why does it cause adding element to list in operational portion twice
396 //$scope.$broadcast('EV_DISABLE_ADDING_LIST_ELEMENT');
398 $scope.$broadcast('EV_REFRESH_LIST_INDEX');
399 DesignUtilsService.triggerWindowResize(100);
401 $scope.selApi = null;
402 $scope.selSubApi = null;
408 * Checks if the element list should be disabled
410 function checkAddingListElement(node) {
411 return $scope.node === node && $scope.node.type === 'list' && $scope.node.refKey && $scope.node.refKey.length;
414 function loadController() {
418 $scope.previewVisible = false;
419 $scope.previewValue = '';
420 $scope.popupData = { show: false };
421 $scope.dataToFill = '';
422 $scope.apiToFill = '';
426 $rootScope.$on('$includeContentLoaded', function () {
427 DesignUtilsService.setDraggablePopups();
428 // DesignUtilsService.getHistoryPopUpWidth();
432 function executeOperation(operation, callback, reqPath) {
433 var reqString = $scope.selSubApi.buildApiRequestString(),
435 preparedRequestData = {},
438 reqString = reqPath ? reqPath.slice($scope.selApi.basePath.length, reqPath.length) : reqString;
439 var requestPath = $scope.selApi.basePath + reqString;
441 operation = YangUtilsService.prepareOperation(operation);
443 if (operation !== 'REMOVE'){
444 $scope.node.buildRequest(RequestBuilderService, requestData, $scope.node.module);
445 angular.copy(requestData, preparedRequestData);
447 preparedRequestData = YangUtilsService.prepareRequestData(
455 headers = YangUtilsService.prepareHeaders(preparedRequestData);
457 requestWorkingCallback();
459 YangUtilsRestangularService.one('restconf').customOperation(
460 operation.toLowerCase(),
467 if (operation === 'REMOVE'){
473 var props = Object.getOwnPropertyNames(data);
475 // fill each property - needed for root mountpoint node,
476 // in other cases there should be only one property anyway
477 props.forEach(function (p) {
478 $scope.node.fill(p, data[p]);
480 $scope.node.expanded = true;
483 requestSuccessCallback();
484 // TODO after first GET we have set $scope.node with data
485 // so build from the top of this function return requestData
486 if (operation === 'GET'){
489 $scope.$broadcast('YUI_ADD_TO_HISTORY',
497 if ( angular.isFunction(callback) ) {
501 if ($scope.previewVisible === true){
508 if (resp.data && resp.data.errors && resp.data.errors.error && resp.data.errors.error.length) {
509 errorMsg = ': ' + resp.data.errors.error.map(function (e) {
510 return e['error-message'];
514 requestErrorCallback(errorMsg, resp);
516 // TODO after first GET we have set $scope.node with data
517 // so build from the top of this function return requestData
518 if (operation === 'GET'){
522 'YUI_ADD_TO_HISTORY',
531 'error sending request to',
532 $scope.selSubApi.buildApiRequestString(),
544 function executeCustFunctionality(custFunct) {
545 custFunct.runCallback($scope);
546 $scope.selCustFunct = custFunct;
549 function fillNodeData(pathElem, identifier) {
550 if ($scope.selSubApi && $scope.selSubApi.storage === 'config' &&
551 $scope.selSubApi.pathArray.indexOf(pathElem) === ($scope.selSubApi.pathArray.length - 1)) {
552 PathUtilsService.fillListNode($scope.node, identifier.label, identifier.value);
556 function showPreview() {
557 $scope.previewVisible = true;
558 $scope.buildPreview();
561 function hidePreview() {
562 $scope.previewVisible = false;
565 function copyReqPathToClipboard(req){
566 var reqPath = req ? req.api.parent.basePath : $scope.selApi.basePath;
569 req.parametrizedPath ?
570 $scope.parameterizeData(req.parametrizedPath) :
571 req.api.buildApiRequestString() :
572 $scope.selSubApi.buildApiRequestString();
577 function fallback(path) {
578 window.prompt($filter('translate')('YANGUI_CLIPBOARD_ALERT_MSG'), path);
581 function buildRoot() {
582 $scope.node.buildRequest(RequestBuilderService, {}, $scope.node.module);
585 function changePathInPreview() {
589 function fillApiAndData(req, dataForView, fromSetCustApi) {
590 var path = req.parametrizedPath ? req.parametrizedPath : req.path,
591 rdata = req.receivedData,
592 sdata = dataForView ? ParsingJsonService.parseJson(dataForView) : req.sentData;
595 $scope.fillApi(path, fromSetCustApi);
597 if ($scope.node && (rdata || sdata)) {
599 $scope.fillApiData(rdata);
603 $scope.fillApiData(sdata);
608 $scope.selectedOperation = req.method;
611 function fillStandardApi(searchPath, fillPath, fromSetCustApi) {
612 fillPath = fillPath || searchPath;
614 var moduleNew = PathUtilsService.getModuleNameFromPath(searchPath),
615 moduleOld = $scope.selSubApi &&
616 $scope.selSubApi.pathArray.length > 1 ? $scope.selSubApi.pathArray[1].module : null;
620 fromSetCustApi && searchPath.indexOf(mountPrefix) === -1 &&
621 $scope.selCustFunct && $scope.selCustFunct.label === 'YANGUI_CUST_MOUNT_POINTS'
624 fromSetCustApi && searchPath.indexOf(mountPrefix) !== -1 &&
625 $scope.selCustFunct &&
626 $scope.selCustFunct.label === 'YANGUI_CUST_MOUNT_POINTS' &&
627 moduleNew !== moduleOld
630 $scope.unsetCustomFunctionality();
633 var apiIndexes = fromSetCustApi ?
634 PathUtilsService.searchNodeByPath(searchPath, $scope.treeApis, $scope.treeRows) :
635 PathUtilsService.searchNodeByPath(
636 MountPointsConnectorService.alterMpPath(searchPath),
642 $scope.setApiNode(apiIndexes.indexApi, apiIndexes.indexSubApi);
643 if ($scope.selSubApi) {
644 PathUtilsService.fillPath($scope.selSubApi.pathArray, fillPath);
649 function fillApi(path, fromSetCustApi) {
650 var parameterizedPath = $scope.parameterizeData(path),
651 fillPath = parameterizedPath;
653 if (parameterizedPath.indexOf(mountPrefix) !== -1) {
654 fillPath = parameterizedPath.replace('restconf/config', 'restconf/operational');
657 $scope.fillStandardApi(fillPath, null, fromSetCustApi);
659 if (path.indexOf(mountPrefix) !== -1 && $scope.selSubApi) {
660 $scope.selSubApi.pathArray = $scope.removeMountPointPath($scope.selSubApi.pathArray);
663 $scope.mpSynchronizer.waitFor(function () {
664 $scope.fillMPApi(parameterizedPath);
669 function selectMP() {
670 var mpCF = CustomFuncService.getMPCustFunctionality($scope.selSubApi.custFunct);
672 $scope.executeCustFunctionality(mpCF);
675 'Mountpoint custom functionality for api',
676 $scope.selSubApi.buildApiRequestString(),
681 function fillMPApi(path) {
682 var mpPath = MountPointsConnectorService.alterMpPath(path),
683 apiIndexes = PathUtilsService.searchNodeByPath(mpPath, $scope.treeApis, $scope.treeRows);
685 $scope.setApiNode(apiIndexes.indexApi, apiIndexes.indexSubApi);
686 if ($scope.selSubApi) {
687 PathUtilsService.fillPath($scope.selSubApi.pathArray, path);
692 function fillApiData(data){
693 var parametrizedData = $scope.parameterizeData(data),
696 obj = typeof parametrizedData === 'object' ?
698 ParsingJsonService.parseJson(parametrizedData);
700 if (obj !== null && typeof obj === 'object') {
701 var p = Object.keys(obj)[0];
702 $scope.node.fill(p, obj[p]);
706 function show_add_data_popup(){
707 $scope.popupData.show = true;
710 function close_popup(popObj){
714 function tabs(event, index){
715 var tabDom = $(event.target).closest('.tabs');
717 tabDom.find(' > .tab-content').children('.tab-pane')
718 .removeClass('active')
719 .eq(index).addClass('active');
721 tabDom.find('> .nav-tabs').children('li')
722 .removeClass('btn-selected')
723 .eq(index).addClass('btn-selected');
726 function initMp(mountPointStructure, mountPointTreeApis, mountPointApis, augmentations){
727 DataBackupService.storeFromScope([
736 $scope.filterRootNode = null;
738 $scope.treeApis = mountPointTreeApis;
739 $scope.apis = mountPointApis;
740 $scope.processingModulesSuccessCallback();
741 $scope.augmentations = augmentations;
742 $scope.$broadcast('REFRESH_HISTORY_REQUEST_APIS');
745 function showModalRequestWin(){
746 $scope.$broadcast('LOAD_REQ_DATA');
749 function setScopeTreeRows(e, rows){
750 $scope.treeRows = rows;
755 angular.module('app.yangui').filter('onlyConfigStmts', function (NodeUtilsService){
756 return function (nodes){
759 nodes = nodes.filter(function (n){
760 return NodeUtilsService.isOnlyOperationalNode(n);