http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js index ed743f4..02682a4 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js @@ -27,6 +27,8 @@ import {CytoscapeRenderer} from '../domain/cytoscape-flow-renderer'; import {FindNodeMixin} from '../domain/findnode-mixin'; import { validator, buildValidations } from 'ember-cp-validations'; import WorkflowPathUtil from '../domain/workflow-path-util'; +import {ActionTypeResolver} from '../domain/action-type-resolver'; +import CommonUtils from "../utils/common-utils"; const Validations = buildValidations({ 'dataNodes': { /* For Cytoscape */ @@ -71,6 +73,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { dataNodes: [], /* For cytoscape */ hoveredAction: null, workflowImporter:WorkflowImporter.create({}), + actionTypeResolver: ActionTypeResolver.create({}), propertyExtractor : Ember.inject.service('property-extractor'), clipboardService : Ember.inject.service('workflow-clipboard'), workspaceManager : Ember.inject.service('workspace-manager'), @@ -86,6 +89,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { killNode : {}, isWorkflowImporting: false, isImportingSuccess: true, + isAssetPublishing: false, + isPublishingSuccess: true, shouldPersist : false, useCytoscape: Constants.useCytoscape, cyOverflow: {}, @@ -93,10 +98,15 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { isStackTraceVisible: false, isStackTraceAvailable: false, stackTrace:"", + showingStreamImport:false, + fileInfo:Ember.Object.create(), + isDraft: false, + saveJobService : Ember.inject.service('save-job'), initialize : function(){ var id = 'cy-' + Math.ceil(Math.random() * 1000); this.set('cyId', id); this.sendAction('register', this.get('tabInfo'), this); + CommonUtils.setTestContext(this); }.on('init'), elementsInserted :function(){ if (this.useCytoscape){ @@ -104,7 +114,6 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }else{ this.flowRenderer=JSPlumbRenderer.create({}); } - this.setConentWidth(); this.set('workflow',Workflow.create({})); if(this.get("xmlAppPath")){ @@ -121,17 +130,18 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { if(Ember.isBlank(this.get('workflow.name'))){ this.set('workflow.name', Ember.copy(this.get('tabInfo.name'))); } - }.on('didInsertElement'), restoreWorkflow(){ if (!this.get("isNew")){ - var draftWorkflow=this.getDraftWorkflow(); - if (draftWorkflow){ - this.resetDesigner(); - this.set("workflow",draftWorkflow); - this.rerender(); - this.doValidation(); - } + this.getDraftWorkflow().promise.then(function(draftWorkflow){ + if (draftWorkflow){ + this.resetDesigner(); + this.set("workflow",draftWorkflow); + this.rerender(); + this.doValidation(); + } + }.bind(this)).catch(function(data){ + }); } }, observeXmlAppPath : Ember.observer('xmlAppPath', function(){ @@ -291,36 +301,30 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { this.set("isWorkflowImporting", true); this.set("workflowFilePath", filePath); this.resetDesigner(); - this.set("isWorkflowImporting", true); + //this.set("isWorkflowImporting", true); var workflowXmlDefered=this.getWorkflowFromHdfs(filePath); workflowXmlDefered.promise.then(function(data){ this.importWorkflowFromString(data); this.set("isWorkflowImporting", false); }.bind(this)).catch(function(data){ - var stackTraceMsg = self.getStackTrace(data.responseText); - if(stackTraceMsg.length){ - self.set("isStackTraceVisible", true); - self.set("stackTrace", stackTraceMsg); - self.set("isStackTraceAvailable", true); - } else { - self.set("isStackTraceVisible", false); - self.set("isStackTraceAvailable", false); - } - self.set("isWorkflowImporting", false); - self.set("isImportingSuccess", false); + console.error(data); + var stackTraceMsg = self.getStackTrace(data.responseText); + self.set("errorMsg", "There is some problem while importing.Please try again."); + self.showingErrorMsgInDesigner(data); }); }, importWorkflowFromString(data){ - var workflow=this.get("workflowImporter").importWorkflow(data); + var wfObject=this.get("workflowImporter").importWorkflow(data); if(this.get('workflow')){ this.resetDesigner(); - this.set("workflow",workflow); + this.set("workflow",wfObject.workflow); this.initAndRenderWorkflow(); this.rerender(); this.doValidation(); + this.set("errors", wfObject.errors); }else{ this.workflow.initialize(); - this.set("workflow",workflow); + this.set("workflow",wfObject.workflow); this.initAndRenderWorkflow(); this.$('#wf_title').focus(); } @@ -343,8 +347,94 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }); return deferred; }, + importActionSettingsFromString(actionSettings) { + var x2js = new X2JS(); + var actionNode = this.flowRenderer.currentCyNode.data().node; + var actionJobHandler = this.actionTypeResolver.getActionJobHandler(actionNode.actionType); + actionJobHandler.handleImport(actionNode, x2js.xml_str2json(actionSettings)[actionNode.actionType]); + this.flowRenderer.hideOverlayNodeActions(); + }, + importActionNodeFromString(actionNodeXmlString) { + var x2js = new X2JS(); + var actionNodeXml = x2js.xml_str2json(actionNodeXmlString); + var actionNodeType = Object.keys(actionNodeXml)[0]; + var currentTransition = this.get("currentTransition"); + this.createSnapshot(); + var actionNode = this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode, currentTransition.sourceNodeId, currentTransition.targetNode.id),actionNodeType); + this.rerender(); + this.doValidation(); + this.scrollToNewPosition(); + var actionJobHandler = this.actionTypeResolver.getActionJobHandler(actionNodeType); + actionJobHandler.handleImport(actionNode, actionNodeXml[actionNodeType]); + }, + publishAsset(filePath, actionNodeXml, wfDynamicProps) { + var url = Ember.ENV.API_URL + "/publishAsset?uploadPath="+filePath; + wfDynamicProps.forEach(function(property){ + url = url + "&config." + property.name + "=" + property.value; + }); + var deferred = Ember.RSVP.defer(); + Ember.$.ajax({ + url: url, + method: "POST", + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function (xhr) { + xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + xhr.setRequestHeader("X-Requested-By", "Ambari"); + }, + data: actionNodeXml, + }).done(function(data){ + deferred.resolve(data); + }).fail(function(data){ + deferred.reject(data); + }); + return deferred; + }, + getRandomDataToDynamicProps(dynamicProperties) { + var wfDynamicProps = []; + var wfParams = this.get('workflow.parameters'); + dynamicProperties.forEach(function(property) { + if (property!=="${nameNode}" && property!==Constants.rmDefaultValue) { + var propName = property.trim().substring(2, property.length-1); + var propValue; + if (wfParams && wfParams.configuration && wfParams.configuration.property) { + var param = wfParams.configuration.property.findBy('name', propName); + if (!(param && param.value)) { + propValue = param.value; + } + } + var prop = Ember.Object.create({ + name: propName, + value: propValue ? propValue : Math.random().toString(36).slice(2) + }); + wfDynamicProps.push(prop); + } + }); + return wfDynamicProps; + }, + exportActionNodeXml() { + var self = this; + self.set("isAssetPublishing", true); + var workflowGenerator = WorkflowGenerator.create({workflow:this.get("workflow"), workflowContext:this.get('workflowContext')}); + var actionNodeXml = workflowGenerator.getActionNodeXml(this.flowRenderer.currentCyNode.data().name, this.flowRenderer.currentCyNode.data().node.actionType); + var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(actionNodeXml); + + var exportActionNodeXmlDefered=this.publishAsset(this.get('exportActionNodeFilePath'), actionNodeXml, this.getRandomDataToDynamicProps(dynamicProperties)); + exportActionNodeXmlDefered.promise.then(function(data){ + self.set("isAssetPublishing", false); + self.set("isPublishingSuccess", true); + self.set("successMsg", "Asset is successfully published."); + }.bind(this)).catch(function(data){ + self.set("errorMsg", "There is some problem while publishing asset. Please try again."); + self.showingErrorMsgInDesigner(data); + self.set("isImportingSuccess", true); + }); + + console.log("Action Node", actionNodeXml); + }, resetDesigner(){ this.set("isImportingSuccess", true); + this.set("isPublishingSuccess", true); this.set("xmlAppPath", null); this.set('errors',[]); this.set('validationErrors',[]); @@ -374,8 +464,8 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { dataType: "text", cache:false, success: function(data) { - var workflow=this.get("workflowImporter").importWorkflow(data); - deferred.resolve(workflow); + var wfObject=this.get("workflowImporter").importWorkflow(data); + deferred.resolve(wfObject.workflow); }.bind(this), failure : function(data){ deferred.reject(data); @@ -383,19 +473,95 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }); return deferred; }, + saveAsDraft(){ + var self = this, url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("workflowFilePath") + "&overwrite=" + this.get("overwritePath"); + Ember.$.ajax({ + url: url, + method: "POST", + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function(request) { + request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + request.setRequestHeader("X-Requested-By", "workflow-designer"); + }, + data: self.persistWorkflowAsDraft(), + success: function(response) { + //deferred.resolve(response); + }.bind(this), + error: function(response) { + //deferred.reject(response); + }.bind(this) + }); + }, persistWorkInProgress(){ - var json=JSON.stringify(this.get("workflow")); + var json=this.getWorkflowAsJson(); this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json); }, + getWorkflowAsJson(){ + try{ + var json=JSON.stringify(this.get("workflow")), self = this; + //this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json); + return json; + }catch(err){ + console.error(err); + this.isCyclic(this.get("workflow")); + } + }, + isCyclic (obj) { + var seenObjects = []; + function detect (obj) { + if (typeof obj === 'object') { + if (seenObjects.indexOf(obj) !== -1) { + console.log("object already seen",obj); + return true; + } + seenObjects.push(obj); + for (var key in obj) { + if (obj.hasOwnProperty(key) && detect(obj[key])) { + console.log("object already seen",key); + return true; + } + } + } + return false; + } + return detect(obj); + }, + persistWorkflowAsDraft(){ + + }, + getDraftWorkflowData(path){ + var deferred = Ember.RSVP.defer(); + //var path = encodeURIComponent("/user/ambari-qa/examples/demo/draft"); + var self = this, url = Ember.ENV.API_URL + "/readWorkflowDraft?workflowXmlPath=" + path; + Ember.$.ajax({ + url: url, + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function(request) { + request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + request.setRequestHeader("X-Requested-By", "workflow-designer"); + }, + success: function(response) { + deferred.resolve(response); + }.bind(this), + error: function(response) { + deferred.reject(response); + }.bind(this) + }); + return deferred; + }, getDraftWorkflow(){ + var deferred = Ember.RSVP.defer(); var drafWorkflowJson = this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id')); var workflowImporter=WorkflowJsonImporter.create({}); var workflow=workflowImporter.importWorkflow(drafWorkflowJson); - return workflow; + deferred.resolve(workflow); + return deferred; }, createSnapshot() { this.set('undoAvailable', false); - this.set('workflowSnapshot', JSON.stringify(this.get("workflow"))); + this.set('workflowSnapshot', this.getWorkflowAsJson()); }, showUndo (type){ this.set('undoAvailable', true); @@ -462,20 +628,26 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { scrollTop: scroll+200 }, 1000); }, - openSaveWorkflow (){ + openSaveWorkflow (isWfPathSet){ this.get('workflowContext').clearErrors(); var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"), workflowContext:this.get('workflowContext')}); var workflowXml=workflowGenerator.process(); if(this.get('workflowContext').hasErrors()){ this.set('errors',this.get('workflowContext').getErrors()); + this.set("jobXmlJSONStr", this.persistWorkflowAsDraft()); + this.set("isDraft", true); }else{ + this.set("jobXmlJSONStr", ""); var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(workflowXml); var configForSubmit={props:dynamicProperties,xml:workflowXml,params:this.get('workflow.parameters')}; this.set("workflowSubmitConfigs",configForSubmit); + this.set("isDraft", false); + } + if(isWfPathSet) { this.set("showingSaveWorkflow",true); } - }, + }, openJobConfig (){ this.get('workflowContext').clearErrors(); var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"), @@ -490,7 +662,96 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { this.set("showingWorkflowConfigProps",true); } }, + showingErrorMsgInDesigner(data){ + var self = this, stackTraceMsg = self.getStackTrace(data.responseText); + if(stackTraceMsg.length){ + self.set("isStackTraceVisible", true); + self.set("stackTrace", stackTraceMsg); + self.set("isStackTraceAvailable", true); + } else { + self.set("isStackTraceVisible", false); + self.set("isStackTraceAvailable", false); + } + self.set("isWorkflowImporting", false); + self.set("isImportingSuccess", false); + this.set("isAssetPublishing", false); + this.set("isPublishingSuccess", false); + }, + isDraftExists(path){ + var deferred = Ember.RSVP.defer(), url, self = this; + if(!path){ + path = this.get("workflowFilePath"); + } + url = Ember.ENV.API_URL + "/readWorkflowDetail?workflowXmlPath=" + path; + Ember.$.ajax({ + url: url, + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function(request) { + request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + request.setRequestHeader("X-Requested-By", "workflow-designer"); + }, + success: function(response) { + deferred.resolve(response); + }.bind(this), + error: function(response) { + deferred.reject(response); + }.bind(this) + }); + return deferred; + + }, + importWorkflowFromFile(dataStr){ + this.resetDesigner(); + this.importWorkflowFromString(dataStr); + this.send("hideStreamImport"); + }, actions:{ + importWorkflowStream(dataStr){ + this.importWorkflowFromFile(dataStr); + }, + saveFileinfo(path, overWritePath){ + this.get("fileInfo").set("path", path); + this.get("fileInfo").set("overWritePath", overWritePath); + }, + showStreamImport() { + this.set("showingStreamImport", true); + }, + hideStreamImport() { + this.set("showingStreamImport", false); + }, + fileLoaded(file){ + var self = this; + function importWorkflowFromFile(dataStr){ + self.importWorkflowFromFile(dataStr); + } + var reader = new FileReader(); + reader.addEventListener("load", function (event) { + importWorkflowFromFile(event.target.result); + }); + reader.readAsText(file); + }, + importActionSettings(file){ + var self = this; + var reader = new FileReader(); + reader.addEventListener("load", function (event) { + var actionSettings = event.target.result; + var x2js = new X2JS(); + var actionNode = self.flowRenderer.currentCyNode.data().node; + var actionJobHandler = self.actionTypeResolver.getActionJobHandler(actionNode.actionType); + actionJobHandler.handleImport(actionNode, x2js.xml_str2json(actionSettings)[actionNode.actionType]); + self.flowRenderer.hideOverlayNodeActions(); + }); + reader.readAsText(file); + }, + importActionNodeLocalFS(file){ + var self = this; + var reader = new FileReader(); + reader.addEventListener("load", function (event) { + self.importActionNodeFromString(event.target.result); + }); + reader.readAsText(file); + }, showStackTrace(){ this.set("isStackTraceVisible", true); }, @@ -515,7 +776,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { showVersionSettings(value){ this.set('showVersionSettings', value); }, - showingParameterSettings(value){ + showingParameterSettings(value){ if(this.get('workflow.parameters') !== null){ this.set('parameters', Ember.copy(this.get('workflow.parameters'))); }else{ @@ -616,7 +877,7 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { if(trans.targetNode.id !== transition.okToNode.id){ trans.targetNode = transition.okToNode; this.showUndo('transition'); - } + } } }, this); }, @@ -624,9 +885,29 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { this.set('dryrun', false); this.openJobConfig(); }, - saveWorkflow(){ + saveWorkflow(action){ + if(this.get("fileInfo").get("path") && action === "save"){ + this.openSaveWorkflow(); + var url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath"); + var self = this, workflowData; + + if(this.get('isDraft')){ + url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath");; + workflowData = this.get("jobXmlJSONStr"); + } else { + url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("fileInfo").get("path") + "&overwrite=" + this.get("fileInfo").get("overWritePath");; + workflowData = this.get("workflowSubmitConfigs").xml; + } + + this.get("saveJobService").saveWorkflow(url, workflowData).promise.then(function(data){ + }.bind(this)).catch(function(data){ + self.set("errorMsg", "There is some problem while saving workflow.Please try again."); + self.showingErrorMsgInDesigner(data); + }); + } else { + this.openSaveWorkflow(true); + } this.set('dryrun', false); - this.openSaveWorkflow(); }, previewWorkflow(){ this.set("showingPreview",false); @@ -671,14 +952,85 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { }); }, closeFileBrowser(){ + var self = this, path = this.get('workflowFilePath'); this.set("showingFileBrowser",false); - if(this.get('workflowFilePath')){ - this.importWorkflow(this.get('workflowFilePath')); + if(path){ + this.isDraftExists().promise.then(function(data){ + var draftData = JSON.parse(data); + if(draftData.draftExists && draftData.isDraftCurrent){ + self.getDraftWorkflowData(path).promise.then(function(data){ + var drafWorkflowJson = self.get('workspaceManager').restoreWorkInProgress(data); + var workflowImporter=WorkflowJsonImporter.create({}); + var workflow=workflowImporter.importWorkflow(drafWorkflowJson); + + self.resetDesigner(); + self.set("workflow",workflow); + self.rerender(); + self.doValidation(); + + }.bind(this)).catch(function(data){ + + }); + + //deferred.resolve(workflow); + } else { + self.importWorkflow(path); + } + }.bind(this)).catch(function(data){ + //self.importWorkflow(path); + console.error(data); + }); } }, showFileBrowser(){ this.set('showingFileBrowser', true); }, + closeActionSettingsFileBrowser() { + var self = this; + this.set("showingActionSettingsFileBrowser", false); + if(this.get('actionSettingsFilePath')){ + var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionSettingsFilePath')); + actionSettingsXmlDefered.promise.then(function(data){ + this.importActionSettingsFromString(data); + }.bind(this)).catch(function(data){ + console.error(data); + var stackTraceMsg = self.getStackTrace(data.responseText); + self.set("errorMsg", "There is some problem while importing.Please try again."); + self.showingErrorMsgInDesigner(data); + }); + } + }, + showActionSettingsFileBrowser() { + this.set('showingActionSettingsFileBrowser', true); + }, + closeImportActionNodeFileBrowser() { + var self = this; + this.set("showingImportActionNodeFileBrowser", false); + if(this.get('actionNodeFilePath')){ + var actionSettingsXmlDefered=this.getWorkflowFromHdfs(this.get('actionNodeFilePath')); + actionSettingsXmlDefered.promise.then(function(data){ + this.importActionNodeFromString(data); + }.bind(this)).catch(function(data){ + console.error(data); + var stackTraceMsg = self.getStackTrace(data.responseText); + self.set("errorMsg", "There is some problem while importing.Please try again."); + self.showingErrorMsgInDesigner(data); + }); + } + }, + showImportActionNodeFileBrowser() { + this.set('showingImportActionNodeFileBrowser', true); + }, + closeExportActionNodeFileBrowser() { + var self = this; + this.set("showingExportActionNodeFileBrowser", false); + if(this.get('exportActionNodeFilePath')){ + self.exportActionNodeXml(); + } + }, + showExportActionNodeFileBrowser() { + this.set('showingExportActionNodeFileBrowser', true); + }, createNewWorkflow(){ this.resetDesigner(); this.rerender(); @@ -768,6 +1120,13 @@ export default Ember.Component.extend(FindNodeMixin, Validations, { dryRunWorkflow(){ this.set('dryrun', true); this.openJobConfig(); + }, + scheduleWorkflow(){ + if(!this.get('workflowFilePath')){ + console.error("Workflow doesnot exists"); + return; + } + this.sendAction('openTab', 'coord', this.get('workflowFilePath')); } } });
http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js index 232df16..c9be41a 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js @@ -59,7 +59,8 @@ export default Ember.Component.extend({ var self=this; var $elem=this.$('input[name="selectedPath"]'); //$elem.val($elem.val()+"/"); - + var folderHint="<enter folder here>"; + this.set("selectedPath",this.get("selectedPath")+"/"+folderHint); setTimeout(function(){ $elem[0].selectionStart = $elem[0].selectionEnd = self.get("selectedPath").length-folderHint.length; },10); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js new file mode 100644 index 0000000..c9aa3c4 --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/import-from-stream.js @@ -0,0 +1,67 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Ember from 'ember'; +import Constants from '../utils/constants'; +import { validator, buildValidations } from 'ember-cp-validations'; + +const Validations = buildValidations({ + 'workflowStream': validator('presence', { + presence : true + }), + 'configMap': { + validators: [ + validator('job-params-validator', { + dependentKeys: ['[email protected]', 'showErrorMessage'] + }) + ] + } +}); + + +export default Ember.Component.extend(Validations, { + workflowStream : "", + displayName : Ember.computed('type', function(){ + if(this.get('type') === 'wf'){ + return "Workflow"; + }else if(this.get('type') === 'coord'){ + return "Coordinator"; + }else{ + return "Bundle"; + } + }), + initialize :function(){ + + }.on('init'), + rendered : function(){ + this.$("#configureJob").modal("show"); + }.on('didInsertElement'), + + getParsedErrorResponse (response){ + + }, + actions: { + save(){ + this.$("#configureJob").modal("hide"); + this.sendAction("importWorkflowStream", this.$('.CodeMirror')[0].CodeMirror.getValue()); + }, + close(){ + this.$("#configureJob").modal("hide"); + this.sendAction("hideStreamImport"); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js index 4fa2666..8b685f0 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js @@ -142,7 +142,7 @@ export default Ember.Component.extend(Validations, { } this.set("alertDetails", data.details); this.set("alertMessage", data.message); - if(data.stackTrace.length){ + if(data.stackTrace && data.stackTrace.length){ this.set("stackTrace", data.stackTrace); this.set("isStackTraceAvailable", true); } else { http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js index 0e5fd36..32f5ef4 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js @@ -49,16 +49,21 @@ export default Ember.Component.extend({ } }), displayType : Ember.computed('model.jobType', function() { - if(this.get('jobType') === 'wf'){ + if(this.get('model.jobType') === 'wf'){ return "Workflow"; - }else if(this.get('jobType') === 'coords'){ + }else if(this.get('model.jobType') === 'coords'){ return "Coordinator"; } - else if(this.get('jobType') === 'bundles'){ + else if(this.get('model.jobType') === 'bundles'){ return "Bundle"; } return "Workflow"; }), + configurationProperties : Ember.computed('model', function(){ + var x2js = new X2JS(); + var configurationObj = x2js.xml_str2json(this.get('model.conf')); + return configurationObj.configuration.property; + }), initialize : function(){ if(this.get('currentTab')){ this.$('.nav-tabs a[href="'+this.get('currentTab').attr("href")+'"]').click(); @@ -66,11 +71,6 @@ export default Ember.Component.extend({ this.set('model.actionDetails', this.get('model.actions')[0]); } } - - var x2js = new X2JS(); - var configurationObj = x2js.xml_str2json(this.get('model.conf')); - this.set('model.configurationProperties', configurationObj.configuration.property); - this.$('.nav-tabs').on('shown.bs.tab', function(event){ this.sendAction('onTabChange', this.$(event.target)); }.bind(this)); @@ -229,7 +229,8 @@ export default Ember.Component.extend({ this.set('model.actionInfo', actionInfo); }, renderDag(xmlString){ - var workflow = this.get("workflowImporter").importWorkflow(xmlString); + var wfObject = this.get("workflowImporter").importWorkflow(xmlString); + var workflow = wfObject.workflow; console.log("Workflow Object..", workflow); var dataNodes=this.getCyDataNodes(workflow); var cy = cytoscape({ @@ -321,8 +322,8 @@ export default Ember.Component.extend({ }); }, actions : { - back (){ - this.sendAction('back'); + back (jobType, jobId){ + this.sendAction('back', jobType, jobId); }, close : function(){ this.sendAction('close'); @@ -332,7 +333,7 @@ export default Ember.Component.extend({ }, getJobDefinition : function () { Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=definition&timezone=GMT',function(response){ - this.set('model.jobDefinition', (new XMLSerializer()).serializeToString(response).trim()); + this.set('jobDefinition', (new XMLSerializer()).serializeToString(response).trim()); }.bind(this)).fail(function(error){ this.set('error',error); }.bind(this)); @@ -400,6 +401,9 @@ export default Ember.Component.extend({ }, showCoord : function(coordId){ this.sendAction('showCoord', coordId); + }, + editWorkflow(path){ + this.sendAction('editWorkflow', path); } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js index 297244a..2a5fc22 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-row.js @@ -19,6 +19,10 @@ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'tr', + targetParentId: Ember.computed('job', function() { + var parentID = this.get('job').parentId; + return parentID.split("@")[0]; + }), onRender : function(){ this.$('#actions').hide(); }.on('didInsertElement'), http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js index ae453a0..bac2124 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js @@ -33,7 +33,6 @@ export default Ember.Component.extend({ } }.on('willDestroyElement'), addProperty (){ - alert(this.get("validations")); this.get('configuration.property').pushObject({name:this.get('propertyName'),value:this.get('propertyValue')}); //if(this.get("doNotInitialize")){ this.set('propertyName', ""); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js index 31f9df8..7e956a6 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js @@ -1,3 +1,4 @@ + /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -17,4 +18,10 @@ import Ember from 'ember'; export default Ember.Component.extend({ + elementsInserted :function(){ + var self = this; + this.$('#previewModal').on('shown.bs.modal', function (e) { + self.$('.CodeMirror')[0].CodeMirror.refresh(); + }); + }.on('didInsertElement'), }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js index b41f743..8514cb0 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js @@ -38,6 +38,7 @@ export default Ember.Component.extend(Validations, { alertDetails : "", filePath : "", showErrorMessage: false, + saveJobService : Ember.inject.service('save-job'), displayName : Ember.computed('type', function(){ if(this.get('type') === 'wf'){ return "Workflow"; @@ -69,7 +70,7 @@ export default Ember.Component.extend(Validations, { } this.set("alertDetails", data.details); this.set("alertMessage", data.message); - if(data.stackTrace.length){ + if(data.stackTrace && data.stackTrace.length){ this.set("stackTrace", data.stackTrace); this.set("isStackTraceAvailable", true); } else { @@ -77,36 +78,34 @@ export default Ember.Component.extend(Validations, { } }, saveJob(){ - var url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath"); - Ember.$.ajax({ - url: url, - method: "POST", - dataType: "text", - contentType: "text/plain;charset=utf-8", - beforeSend: function(request) { - request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); - request.setRequestHeader("X-Requested-By", "workflow-designer"); - }, - data: this.get("jobXml"), - success: function(response) { - //var result=JSON.parse(response); - this.showNotification({ + var url, workflowData; + if(this.get('isDraft')){ + url = Ember.ENV.API_URL + "/saveWorkflowDraft?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath"); + workflowData = this.get("jobXmlJSONStr"); + } else { + url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath"); + workflowData = this.get("jobXml"); + } + + var self = this; + this.get("saveJobService").saveWorkflow(url, workflowData).promise.then(function(response){ + self.showNotification({ "type": "success", "message": "Workflow have been saved" }); - this.set("savingInProgress",false); - }.bind(this), - error: function(response) { + self.set("savingInProgress",false); + self.sendAction("saveFileinfo", this.get("filePath"), this.get("overwritePath")); + }.bind(this)).catch(function(response){ console.log(response); - this.set("savingInProgress",false); - this.set("isStackTraceVisible",true); - this.showNotification({ + self.set("savingInProgress",false); + self.set("isStackTraceVisible",true); + self.showNotification({ "type": "error", - "message": "Error occurred while saving "+ this.get('displayName').toLowerCase(), - "details": this.getParsedErrorResponse(response), - "stackTrace": this.getStackTrace(response.responseText) + "message": "Error occurred while saving "+ self.get('displayName').toLowerCase(), + "details": self.getParsedErrorResponse(response), + "stackTrace": self.getStackTrace(response.responseText) }); - }.bind(this) + self.sendAction("saveFileinfo", self.get("filePath"), self.get("overwritePath")); }); }, getStackTrace(data){ http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js index 420d3b0..f9226f4 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/search-create-new-bar.js @@ -98,6 +98,7 @@ export default Ember.Component.extend(Ember.Evented,{ } strs.push('Name:'+ searchTerm); strs.push('User:'+ searchTerm); + strs.push('Job id:'+ searchTerm); var newLength = strs.length; var matches, substrRegex; matches = []; @@ -115,19 +116,20 @@ export default Ember.Component.extend(Ember.Evented,{ typeaheadjs: { name: 'source', source: substringMatcher(source), - highlight : true, - limit : 10 + highlight : true } }); this.get('tags').forEach(function(value){ this.$('#search-field').tagsinput('add', value); }.bind(this)); this.$('#search-field').tagsinput('refresh'); + this.$('#search-field').on('itemAdded itemRemoved',function(){ var searchTerms = this.$('#search-field').tagsinput('items'); var filter = searchTerms.map(function(value){ + var eachTag = value.split(":"); - return eachTag[0].toLowerCase()+"="+eachTag[1]; + return self.mapSearchItems(eachTag[0])+"="+eachTag[1]; }); if(filter.length > 0){ this.filter.tags = filter.join(";"); @@ -144,7 +146,14 @@ export default Ember.Component.extend(Ember.Evented,{ } }.bind(this)); }.on('didInsertElement'), - + mapSearchItems(key){ + key = key.replace(" ", "_").toLowerCase(); + var keys = {"job_id":"id"}; + if(keys[key]){ + return keys[key]; + } + return key; + }, filterByDate(date, dateType){ var queryParam; if(dateType === 'start'){ http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js index 7fc1c94..55f86af 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js @@ -30,6 +30,14 @@ export default Ember.Component.extend({ pasteNode(){ this.$(this.get('element')).popover('hide'); this.sendAction("pasteNode"); + }, + importActionNodeLocalFS(file) { + this.$(this.get('element')).popover('hide'); + this.sendAction("importActionNodeLocalFS", file); + }, + showImportActionNodeFileBrowser() { + this.$(this.get('element')).popover('hide'); + this.sendAction("showImportActionNodeFileBrowser"); } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js new file mode 100644 index 0000000..31dd392 --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-icon.js @@ -0,0 +1,21 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: 'span' +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js new file mode 100644 index 0000000..9760ddb --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/dashboardtab.js @@ -0,0 +1,81 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Ember from 'ember'; + +export default Ember.Controller.extend({ + actions: { + launchDesign: function () { + this.transitionToRoute('design'); + }, + doRefresh : function(){ + this.get('target.router').refresh(); + }, + onJobAction: function (params, deferred) { + if (Ember.ENV.API_FAILED) { + return { error: "Remote API Failed." }; + } + var url = [Ember.ENV.API_URL, + "/v2/job/", params.id, "?action=", params.action,'&user.name=oozie' + ].join(""); + var jobActionParams = { + url: url, + method: 'PUT', + beforeSend: function (xhr) { + xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + xhr.setRequestHeader("X-Requested-By", "Ambari"); + if(params.action.indexOf('rerun') > -1){ + xhr.setRequestHeader("Content-Type","application/xml"); + } + } + }; + if(params.action.indexOf('rerun') > -1){ + jobActionParams.data = params.conf; + } + Ember.$.ajax(jobActionParams).done(function(){ + deferred.resolve(); + }).fail(function(){ + deferred.reject(); + }); + }, + onBulkAction : function(params, deferred){ + if (Ember.ENV.API_FAILED) { + return { error: "Remote API Failed." }; + } + var url = [Ember.ENV.API_URL, + "/v2/jobs?jobtype=", params.jobType, + "&offset=", params.start, + "&len=", params.len, + "&filter=", params.filter, + "&action=", params.action, + "&user.name=oozie" + ].join(""); + Ember.$.ajax({ + url: url, + method: 'PUT', + beforeSend: function (xhr) { + xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000)); + xhr.setRequestHeader("X-Requested-By", "Ambari"); + } + }).done(function(response){ + deferred.resolve(response); + }).fail(function(response){ + deferred.reject(response); + }); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js new file mode 100644 index 0000000..18559cc --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design/jobtab.js @@ -0,0 +1,59 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import Ember from 'ember'; + +export default Ember.Controller.extend({ + dashboardContext: Ember.inject.service(), + fromBundleId: null, + fromCoordId: null, + actions : { + close : function(){ + this.sendAction('onCloseJobDetails'); + }, + showWorkflow : function(workflowId){ + this.get('dashboardContext').setCurrentCoordName(this.get('model.coordJobName')); + this.transitionToRoute('design.jobtab', { + queryParams: { + jobType: 'wf', + id: workflowId, + fromBundleId: this.get('fromBundleId'), + fromCoordId: this.get('model.coordJobId') + } + }); + }, + showCoord : function(coordJobId){ + this.get('dashboardContext').setCurrentBundleName(this.get('model.bundleJobName')); + this.transitionToRoute('design.jobtab', { + queryParams: { + jobType: 'coords', + id: coordJobId, + fromBundleId: this.get('model.bundleJobId') + } + }); + }, + back : function (jobType, jobId){ + this.transitionToRoute('design.jobtab', { + queryParams: { + jobType: jobType, + id: jobId, + fromBundleId : (jobType === 'coords') ? this.get('fromBundleId') : null, + fromCoordId : null + } + }); + }, + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js index 2c90be4..5a95b84 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/job.js @@ -17,8 +17,9 @@ import Ember from 'ember'; export default Ember.Controller.extend({ - from : null, - fromType : null, + dashboardContext: Ember.inject.service(), + fromBundleId: null, + fromCoordId: null, actions : { close : function(){ this.sendAction('onCloseJobDetails'); @@ -27,32 +28,33 @@ export default Ember.Controller.extend({ this.get('target.router').refresh(); }, showWorkflow : function(workflowId){ - this.transitionToRoute('job', { + this.get('dashboardContext').setCurrentCoordName(this.get('model.coordJobName')); + this.transitionToRoute('design.jobtab', { queryParams: { jobType: 'wf', id: workflowId, - from : this.get('model.coordJobId'), - fromType : this.get('model.jobType') + fromBundleId: this.get('fromBundleId'), + fromCoordId: this.get('model.coordJobId') } }); }, showCoord : function(coordJobId){ - this.transitionToRoute('job', { + this.get('dashboardContext').setCurrentBundleName(this.get('model.bundleJobName')); + this.transitionToRoute('design.jobtab', { queryParams: { jobType: 'coords', id: coordJobId, - from : this.get('model.bundleJobId'), - fromType : this.get('model.jobType') + fromBundleId: this.get('model.bundleJobId') } }); }, - back : function (){ - this.transitionToRoute('job', { + back : function (jobType, jobId){ + this.transitionToRoute('design.jobtab', { queryParams: { - jobType: this.get('fromType'), - id: this.get('from'), - from : null, - fromType : null + jobType: jobType, + id: jobId, + fromBundleId : (jobType === 'coords') ? this.get('fromBundleId') : null, + fromCoordId : null } }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js index 957d1c0..7dc05a9 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js @@ -22,7 +22,7 @@ var BundleGenerator= Ember.Object.extend({ var xmlJson={"bundle-app":{}}; console.log(this.bundle); var bundleApp=xmlJson["bundle-app"]; - bundleApp._xmlns = "uri:oozie:bundle:0.1"; + bundleApp._xmlns = "uri:oozie:bundle:"+this.bundle.schemaVersions.bundleVersion; bundleApp._name = this.bundle.name; if(!Ember.isEmpty(this.bundle.kickOffTime.value)){ bundleApp["control"] = {}; http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js index aa96221..2714ca1 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js @@ -16,14 +16,18 @@ */ import Ember from 'ember'; import { Bundle } from '../bundle/bundle'; +import SchemaVersions from '../schema-versions'; +import CommonUtils from "../../utils/common-utils"; var BundleXmlImporter= Ember.Object.extend({ x2js : new X2JS(), - importBundle (xml){ + schemaVersions : null, + importBundle (xml, errors){ var bundleJson = this.get("x2js").xml_str2json(xml); - return this.processBundleXML(bundleJson); + return this.processBundleXML(bundleJson, errors); }, processBundleXML(bundleJson){ + var errors=Ember.A([]); var bundle = Bundle.create({ name : '', kickOffTime : { @@ -31,17 +35,25 @@ var BundleXmlImporter= Ember.Object.extend({ displayValue : '', type : 'date' }, - coordinators : Ember.A([]) + coordinators : Ember.A([]), + schemaVersions : this.get("schemaVersions") }); var bundleApp=bundleJson["bundle-app"]; bundle.name = bundleApp._name; + var bundleVersion=CommonUtils.extractSchemaVersion(bundleApp._xmlns); + var maxBundleVersion = Math.max.apply(Math, bundle.schemaVersions.getBundleVersions()); + if (bundleVersion < maxBundleVersion) { + bundle.schemaVersions.setCurrentBundleVersion(bundleVersion); + } else { + errors.push({message: "Unsupported bundle version - " + bundleVersion}); + } if(bundleApp.control && bundleApp.control["kick-off-time"]) { bundle.kickOffTime = this.extractDateField(bundleApp["control"]["kick-off-time"]); }else{ } this.processCoordinatorsJson(bundleApp, bundle); - return bundle; + return {bundle: bundle, errors: errors}; }, processCoordinatorsJson(bundleApp, bundle){ if (bundleApp.coordinator){ http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js index a657706..cbefa99 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js @@ -33,7 +33,7 @@ var CoordinatorGenerator= Ember.Object.extend({ coordinatorApp._start = this.coordinator.start.value; coordinatorApp._end = this.coordinator.end.value; coordinatorApp._timezone = this.coordinator.timezone; - coordinatorApp._xmlns = "uri:oozie:coordinator:0.4"; + coordinatorApp._xmlns = "uri:oozie:coordinator:"+this.coordinator.schemaVersions.coordinatorVersion; this.generateDataSets(coordinatorApp); if(this.coordinator.dataInputType === 'simple'){ this.generateInputEvents(coordinatorApp); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js index fca90b3..76da535 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js @@ -16,12 +16,15 @@ */ import Ember from 'ember'; import { Coordinator } from '../coordinator/coordinator'; +import SchemaVersions from '../schema-versions'; +import CommonUtils from "../../utils/common-utils"; var CoordinatorXmlImporter= Ember.Object.extend({ x2js : new X2JS(), - importCoordinator (xml){ + schemaVersions: null, + importCoordinator (xml, errors){ var coordinatorJson = this.get("x2js").xml_str2json(xml); - return this.processCoordinatorXML(coordinatorJson); + return this.processCoordinatorXML(coordinatorJson, errors); }, createNewCoordinator(){ return Coordinator.create({ @@ -55,13 +58,22 @@ var CoordinatorXmlImporter= Ember.Object.extend({ property : Ember.A([]) } }, - controls : Ember.A([]) + controls : Ember.A([]), + schemaVersions : this.get("schemaVersions") }); }, processCoordinatorXML(coordinatorJson){ + var errors=Ember.A([]); var coordinatorApp = coordinatorJson["coordinator-app"]; var coordinator = this.createNewCoordinator(); coordinator.name = coordinatorApp._name; + var coordinatorVersion=CommonUtils.extractSchemaVersion(coordinatorApp._xmlns); + var maxCoordinatorVersion = Math.max.apply(Math, coordinator.schemaVersions.getCoordinatorVersions()); + if (coordinatorVersion < maxCoordinatorVersion) { + coordinator.schemaVersions.setCurrentCoordinatorVersion(coordinatorVersion); + } else { + errors.push({message: "Unsupported coordinator version - " + coordinatorVersion}); + } var frequency = coordinatorApp._frequency; if(frequency.startsWith('${coord:')){ coordinator.frequency.type = frequency.substring(frequency.indexOf(':')+1, frequency.indexOf('(')); @@ -77,7 +89,7 @@ var CoordinatorXmlImporter= Ember.Object.extend({ if(coordinatorApp['input-events'] && coordinatorApp['input-events']['data-in']){ coordinator.dataInputType = 'simple'; this.extractInputEvents(coordinatorApp, coordinator); - }else{ + }else if(coordinatorApp['input-events']){ coordinator.dataInputType = 'logical'; coordinator.supportsConditionalDataInput = true; this.extractLogicalInputEvents(coordinatorApp, coordinator); @@ -86,7 +98,7 @@ var CoordinatorXmlImporter= Ember.Object.extend({ this.extractAction(coordinatorApp, coordinator); this.extractParameters(coordinatorApp, coordinator); this.extractControls(coordinatorApp, coordinator); - return coordinator; + return {coordinator: coordinator, errors: errors}; }, extractDateField(value){ var dateField = {}; http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js index 086916f..d1150c3 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js @@ -79,7 +79,7 @@ var CytoscapeRenderer= Ember.Object.extend({ return 'roundrectangle'; case 'fork' : case 'join' : - return 'rectangle'; + return 'roundrectangle'; case 'decision' : return 'diamond'; default : @@ -199,6 +199,8 @@ var CytoscapeRenderer= Ember.Object.extend({ if (node.data().type === 'action') { this.get("context").$(".overlay-copy-icon").show(); this.get("context").$(".overlay-cut-icon").show(); + this.get("context").$(".overlay-hdfs-import-icon").show(); + this.get("context").$(".overlay-hdfs-export-icon").show(); if(this.get('context').get('clipboard')){ this.get("context").$(".overlay-paste-icon").show(); } @@ -317,6 +319,15 @@ var CytoscapeRenderer= Ember.Object.extend({ this._initCY(settings); callback(); }, + + fitWorkflow() { + this.cy.fit(); + }, + + hideOverlayNodeActions() { + this.get("context").$('.overlay-node-actions').hide(); + }, + reset(){ }, http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js index 2962e71..d4d8f50 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js @@ -65,7 +65,7 @@ var MappingMixin= Ember.Mixin.create({ var domain={}; if (json._xmlns){ var version=CommonUtils.extractSchemaVersion(json._xmlns); - this.schemaVersions.setActionVersion(actionNode.actionType,version); + //this.schemaVersions.setActionVersion(actionNode.actionType,version); } actionNode.set("domain",domain); mappings.forEach(function(mapping){ http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js index 9562ae8..0a5083f 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/schema-versions.js @@ -18,35 +18,133 @@ import Ember from 'ember'; export default Ember.Object.extend({ actionVersions: Ember.Map.create(), currentActionVersion:Ember.Map.create(), + workflowVersions: [], + workflowVersion: null, + bundleVersions: [], + bundleVersion: null, + coordinatorVersions: [], + coordinatorVersion: null, clone : {}, + actionSchemaMap:{ + "hive":["0.6","0.5","0.4","0.3","0.2","0.1"], + "hive2":["0.2","0.1"], + "sqoop":["0.3","0.2","0.1"], + "shell":["0.3","0.2","0.1"], + "spark":["0.2","0.1"], + "distcp":["0.2","0.1"], + "email":["0.2","0.1"] + }, createCopy(){ this.clone.workflowVersion = this.workflowVersion; this.clone.currentActionVersion = this.currentActionVersion.copy(); + this.clone.coordinatorVersion = this.coordinatorVersion; + this.clone.bundleVersion = this.bundleVersion; }, rollBack(){ this.workflowVersion = this.clone.workflowVersion; this.currentActionVersion = this.clone.currentActionVersion.copy(); }, + importAdminConfigs(){ + var url = Ember.ENV.API_URL + "/v1/admin/configuration"; + var deferred = Ember.RSVP.defer(); + Ember.$.ajax({ + url: url, + method: "GET", + dataType: "text", + contentType: "text/plain;charset=utf-8", + beforeSend: function(request) { + request.setRequestHeader("X-Requested-By", "workflow-designer"); + }, + success: function(response) { + deferred.resolve(response); + }.bind(this), + error: function(response) { + deferred.reject(response); + }.bind(this) + }); + return deferred; + }, + setWfSchemaVersions(configSettings) { + this.workflowVersions = []; + var wfSchemaVersions = configSettings["oozie.service.SchemaService.wf.schemas"].trim().split(","); + wfSchemaVersions = wfSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort(); + wfSchemaVersions.forEach(function(wfSchemaVersion) { + var wfSchema = wfSchemaVersion.split("-"); + var wfSchemaName = wfSchema[0]; + var wfSchemaType = wfSchema[1]; + var wfSchemaVersionNumber = wfSchema[2].replace(".xsd", ""); + if (wfSchemaType === "action") { + if (this.actionVersions.get(wfSchemaName)) { + this.actionVersions.get(wfSchemaName).push(wfSchemaVersionNumber); + this.currentActionVersion.set(wfSchemaName, wfSchemaVersionNumber); + } else { + this.actionVersions.set(wfSchemaName, [wfSchemaVersionNumber]); + this.currentActionVersion.set(wfSchemaName, wfSchemaVersionNumber); + } + } else if (wfSchemaType === "workflow") { + this.workflowVersions.push(wfSchemaVersionNumber); + this.workflowVersion = wfSchemaVersionNumber; + } + }.bind(this)); + }, + setCoordSchemaVersions(configSettings) { + this.coordinatorVersions = []; + var coordSchemaVersions = configSettings["oozie.service.SchemaService.coord.schemas"].trim().split(","); + coordSchemaVersions = coordSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort(); + coordSchemaVersions.forEach(function(coordSchemaVersion) { + var coordSchema = coordSchemaVersion.split("-"); + var coordSchemaType = coordSchema[1]; + var coordSchemaVersionNumber = coordSchema[2].replace(".xsd", ""); + if (coordSchemaType === "coordinator") { + this.coordinatorVersions.push(coordSchemaVersionNumber); + this.coordinatorVersion = coordSchemaVersionNumber; + } + }.bind(this)); + }, + setBundleSchemaVersions(configSettings) { + this.bundleVersions = []; + var bundleSchemaVersions = configSettings["oozie.service.SchemaService.bundle.schemas"].trim().split(","); + bundleSchemaVersions = bundleSchemaVersions.map(Function.prototype.call, String.prototype.trim).sort(); + bundleSchemaVersions.forEach(function(bundleSchemaVersion) { + var bundleSchema = bundleSchemaVersion.split("-"); + var bundleSchemaType = bundleSchema[1]; + var bundleSchemaVersionNumber = bundleSchema[2].replace(".xsd", ""); + if (bundleSchemaType === "bundle") { + this.bundleVersions.push(bundleSchemaVersionNumber); + this.bundleVersion = bundleSchemaVersionNumber; + } + }.bind(this)); + }, init(){ - this.workflowVersion = "0.5"; - this.workflowVersions = ["0.5","0.4.5","0.4","0.3","0.2.5","0.2","0.1"]; - this.actionVersions.set("hive",["0.6","0.5","0.4","0.3","0.2","0.1"]); - this.actionVersions.set("hive2",["0.2","0.1"]); - this.actionVersions.set("pig",["0.3","0.2","0.1"]); - this.actionVersions.set("sqoop",["0.3","0.2","0.1"]); - this.actionVersions.set("shell",["0.3","0.2","0.1"]); - this.actionVersions.set("spark",["0.2","0.1"]); - this.actionVersions.set("distcp",["0.2","0.1"]); - this.actionVersions.set("email",["0.2","0.1"]); - - this.currentActionVersion.set("hive","0.6"); - this.currentActionVersion.set("hive2","0.2"); - this.currentActionVersion.set("pig","0.3"); - this.currentActionVersion.set("sqoop","0.3"); - this.currentActionVersion.set("shell","0.3"); - this.currentActionVersion.set("spark","0.2"); - this.currentActionVersion.set("distcp","0.2"); - this.currentActionVersion.set("email","0.2"); + var importAdminConfigsDefered=this.importAdminConfigs(); + importAdminConfigsDefered.promise.then(function(data){ + var configSettings = JSON.parse(data); + if (!(configSettings instanceof Object)) { + configSettings = JSON.parse(configSettings); + } + this.setWfSchemaVersions(configSettings); + this.setCoordSchemaVersions(configSettings); + this.setBundleSchemaVersions(configSettings); + this.setDefaultActionVersions(); + }.bind(this)).catch(function(){ + this.setWorkflowVersions(["0.5","0.4.5","0.4","0.3","0.2.5","0.2","0.1"]); + this.setCurrentWorkflowVersion("0.5"); + this.setCoordinatorVersions(["0.4","0.3", "0.2","0.1"]); + this.setCurrentCoordinatorVersion("0.4"); + this.setBundleVersions(["0.2","0.1"]); + this.setCurrentBundleVersion("0.2"); + this.setDefaultActionVersions(); + console.error("There is some problem while importing schema versions. defaulting to known versions."); + }.bind(this)); + }, + setDefaultActionVersions(){ + var self=this; + Object.keys(this.actionSchemaMap).forEach(function(key) { + if (!self.actionVersions.get(key)){ + self.actionVersions.set(key,self.actionSchemaMap[key]); + self.currentActionVersion.set(key,self.actionSchemaMap[key][0]); + } + }); }, getActionVersions(type){ return this.actionVersions.get(type); @@ -60,11 +158,38 @@ export default Ember.Object.extend({ getWorkflowVersions(){ return this.workflowVersions; }, + getCurrentCoordinatorVersion(){ + return this.coordinatorVersion; + }, + getCoordinatorVersions(){ + return this.coordinatorVersions; + }, + getCurrentBundleVersion(){ + return this.bundleVersion; + }, + getBundleVersions(){ + return this.bundleVersions; + }, setActionVersion(type, version){ this.currentActionVersion.set(type, version); }, setCurrentWorkflowVersion(version){ - return this.workflowVersion = version; + this.workflowVersion = version; + }, + setCurrentCoordinatorVersion(version){ + this.coordinatorVersion = version; + }, + setCurrentBundleVersion(version){ + this.bundleVersion = version; + }, + setWorkflowVersions(versions){ + this.workflowVersions = versions; + }, + setCoordinatorVersions(versions){ + this.coordinatorVersions = versions; + }, + setBundleVersions(versions){ + this.bundleVersions = versions; } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js index 7415544..d001f38 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js @@ -24,11 +24,12 @@ var WorkflowImporter= Ember.Object.extend({ x2js : new X2JS(), importWorkflow(workflowXml){ var workflow=Workflow.create({}); + var errors=[]; workflow.initialize(); this.workflowMapper=WorkflowXmlMapper.create({schemaVersions:workflow.schemaVersions}); - return this.processWorkflowXml(workflowXml,workflow); + return this.processWorkflowXml(workflowXml,workflow, errors); }, - processWorkflowXml(workflowXml,workflow){ + processWorkflowXml(workflowXml,workflow, errors){ var workflowJson= this.get("x2js").xml_str2json(workflowXml); if (!workflowJson["workflow-app"]){ throw "Invalid workflow"; @@ -36,6 +37,8 @@ var WorkflowImporter= Ember.Object.extend({ var workflowAppJson=workflowJson["workflow-app"]; var workflowVersion=CommonUtils.extractSchemaVersion(workflowAppJson._xmlns); workflow.schemaVersions.setCurrentWorkflowVersion(workflowVersion); + this.processWorkflowActionVersions(workflowAppJson, workflow, errors); + if (workflowAppJson.info && workflowAppJson.info.__prefix==="sla") { workflow.slaEnabled=true; this.workflowMapper.handleSLAImport(workflow,workflowAppJson.info); @@ -46,7 +49,33 @@ var WorkflowImporter= Ember.Object.extend({ this.setupTransitions(workflowAppJson,nodeMap); workflow.set("startNode",nodeMap.get("start").node); this.populateKillNodes(workflow,nodeMap); - return workflow; + return {workflow: workflow, errors: errors}; + }, + processWorkflowActionVersions(workflowAppJson, workflow, errors) { + var importedWfActionVersions = Ember.Map.create(); + var actions=workflowAppJson.action.length?workflowAppJson.action:[workflowAppJson.action]; + actions.forEach(function(wfAction) { + var wfActionType = Object.keys(wfAction)[0]; + var wfActionXmlns = wfAction[wfActionType]._xmlns; + if (!wfActionXmlns) { + return; + } + var wfActionVersion = CommonUtils.extractSchemaVersion(wfActionXmlns); + if (importedWfActionVersions.get(wfActionType)) { + importedWfActionVersions.get(wfActionType).push(wfActionVersion); + } else { + importedWfActionVersions.set(wfActionType, [wfActionVersion]); + } + }); + + importedWfActionVersions._keys.forEach(function(wfActionType){ + var maxImportedActionVersion = Math.max.apply(Math, importedWfActionVersions.get(wfActionType)) + if (workflow.schemaVersions.getActionVersion(wfActionType) < maxImportedActionVersion) { + errors.push({message: "Unsupported " + wfActionType + " version - " + maxImportedActionVersion}); + } else { + workflow.schemaVersions.setActionVersion(wfActionType, maxImportedActionVersion.toString()); + } + }); }, processActionNode(nodeMap,action){ var actionMapper=this.get("workflowMapper").getNodeHandler("action"); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js index 7049fde..012e7ac 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js @@ -58,6 +58,21 @@ var WorkflowGenerator= Ember.Object.extend({ var xmlAsStr = this.get("x2js").json2xml_str(reordered); return xmlAsStr; }, + + getActionNodeXml(actionNodeName, actionNodeType) { + var workflowObj={"workflow-app":{}}; + this.visitNode(workflowObj, this.workflow.startNode); + var workflowActions = workflowObj["workflow-app"].action; + var actionNodes = workflowActions.filter(function (workflowActionNode) { + return workflowActionNode._name === actionNodeName; + }); + if (actionNodes.length>0) { + var actionNode = {}; + actionNode[actionNodeType] = actionNodes[0][actionNodeType]; + return this.get("x2js").json2xml_str(actionNode); + } + return ""; + }, slaInfoExists(workflowApp){ if (workflowApp.info){ return true; http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/router.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/router.js b/contrib/views/wfmanager/src/main/resources/ui/app/router.js index 1fcd633..f494f6f 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/router.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/router.js @@ -24,7 +24,10 @@ const Router = Ember.Router.extend({ Router.map(function () { this.route('dashboard'); - this.route('design'); + this.route('design', function() { + this.route('dashboardtab'); + this.route('jobtab'); + }); this.route('designtest'); this.route('job'); this.route('connection-error'); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js index 949d39a..84cbd28 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js @@ -31,8 +31,8 @@ export default Ember.Route.extend({ queryParams : { id : params.id, jobType : params.type, - from: null, - fromType: null + fromBundleId: null, + fromCoordId: null } }); }, http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js index 5ed2619..10f745a 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js @@ -17,11 +17,24 @@ import Ember from 'ember'; -export default Ember.Route.extend({ +export default Ember.Route.extend(Ember.Evented, { beforeModel: function(transition){ this.set("xmlAppPath", transition.queryParams.appPath); this.controllerFor('design').set("xmlAppPath", transition.queryParams.appPath); + }, + actions : { + editWorkflow(path){ + this.trigger('openNewTab', path); + }, + showDashboard(){ + this.controller.set('dashboardShown', true); + this.transitionTo('design.dashboardtab'); + }, + hideDashboard(){ + this.controller.set('dashboardShown', false); + this.transitionTo('design'); + } } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js new file mode 100644 index 0000000..ddb19af --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/dashboardtab.js @@ -0,0 +1,154 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Ember from 'ember'; + +export default Ember.Route.extend({ + history: Ember.inject.service(), + errorMessage : "Error", + queryParams: { + jobType: { refreshModel: true }, + start: { refreshModel: true }, + filter: { refreshModel: true } + }, + actions: { + onShowJobDetails : function(params){ + this.transitionTo('design.jobtab',{ + queryParams : { + id : params.id, + jobType : params.type, + fromBundleId: null, + fromCoordId: null + } + }); + }, + loading: function ( /*transition, originRoute*/ ) { + Ember.$("#loading").css("display", "block"); + var app = this.controllerFor('application'); + if (app.get('currentRouteName') !== "dashboard") { + return true; + } + return false; + }, + error: function() { + + }, + doSearch (params){ + this.get('history').setSearchParams(params); + Ember.$("#loading").css("display", "block"); + this.search(params); + } + }, + fetchJobs (url){ + var deferred = Ember.RSVP.defer(); + Ember.$.get(url).done(function(res){ + deferred.resolve(res); + }).fail(function(){ + deferred.reject(); + }); + return deferred.promise; + }, + setPageResultLen(){ + /* + setting the no of jobs to be displayed to multiple of 5 + */ + var relHeight = parseInt(Ember.$(window).width()/100); + return relHeight - relHeight%5; + }, + search(params){ + params = params || {}; + var type = params.type || "wf", + start = Number(params.start || 1), + //len = Number(params.len || Ember.ENV.PAGE_SIZE), + len = this.setPageResultLen(), + index = 0, + filter = params.filter || "", + API_URL = Ember.ENV.API_URL, + url = [API_URL, + "/v2/jobs?jobtype=", type, + "&offset=", start, + "&len=", len, + "&filter=", filter + ].join(""), + page = (start - 1) / len + 1; + return this.fetchJobs(url).catch(function(){ + this.controllerFor('dashboard').set('model',{error : "Remote API Failed"}); + Ember.$("#loading").css("display", "none"); + }.bind(this)).then(function (res) { + if(!res){ + return; + } + if (typeof res === "string") { + res = JSON.parse(res); + } + res.jobs = []; + + if (res.workflows) { + res.areWfs = true; + res.type = "wf"; + res.workflows.forEach(function (job) { + job.type = "wf"; + res.jobs.push(job); + }); + } + if (res.coordinatorjobs) { + res.areCoords = true; + res.type = "coords"; + res.coordinatorjobs.forEach(function (job) { + job.type = "coordinatorjobs"; + job.id = job.coordJobId; + job.appName = job.coordJobName; + res.jobs.push(job); + }); + } + if (res.bundlejobs) { + res.areBundles = true; + res.type = "bundles"; + res.bundlejobs.forEach(function (job) { + job.type = "bundlejobs"; + job.id = job.bundleJobId; + job.appName = job.bundleJobName; + res.jobs.push(job); + }); + } + res.pageSize = len; + res.pages = []; + + while (index++ < (res.total / len)) { + res.pages.push({ index: index, active: page === index }); + } + + res.jobTypeValue = type; + res.filterValue = filter; + res.pageSize = len; + res.totalValue = res.total; + res.page = page; + res.start = start; + res.end = (start + res.jobs.length - 1); + res.time = new Date().getTime(); + this.controllerFor('design.dashboardtab').set('model', res); + Ember.$("#loading").css("display", "none"); + return res; + }.bind(this)); + }, + afterModel: function (model) { + Ember.$("#loading").css("display", "none"); + }, + model: function (params) { + + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js new file mode 100644 index 0000000..7d0fa92 --- /dev/null +++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design/jobtab.js @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from 'ember'; + +export default Ember.Route.extend({ + history: Ember.inject.service(), + queryParams: { + jobType: { refreshModel: true }, + id: { refreshModel: true }, + fromBundleId: {refreshModel: true}, + fromCoordId: {refreshModel: true} + }, + fromBundleId: null, + fromCoordId: null, + getJobInfo (url){ + var deferred = Ember.RSVP.defer(); + Ember.$.get(url).done(function(res){ + deferred.resolve(res); + }).fail(function(){ + deferred.reject(); + }); + return deferred.promise; + }, + model : function(params){ + return this.getJobInfo(Ember.ENV.API_URL+'/v2/job/'+params.id+'?show=info&timezone=GMT&offset=1&len='+Ember.ENV.PAGE_SIZE).catch(function(){ + return {error : "Remote API Failed"}; + }).then(function(response){ + if (typeof response === "string") { + response = JSON.parse(response); + } + response.jobType = params.jobType; + return response; + }); + }, + afterModel : function (model, transition){ + if(transition.queryParams.fromBundleId){ + this.set('fromBundleId', transition.queryParams.fromBundleId); + }else{ + this.set('fromBundleId', null); + } + if(transition.queryParams.fromCoordId){ + this.set('fromCoordId', transition.queryParams.fromCoordId); + }else{ + this.set('fromCoordId', null); + } + }, + actions : { + didTransition (){ + if (this.get('fromBundleId')) { + this.controller.set('fromBundleId', this.get('fromBundleId')); + } + if (this.get('fromCoordId')) { + this.controller.set('fromCoordId',this.get('fromCoordId')); + } + }, + onTabChange : function(tab){ + this.set('currentTab', tab); + this.controller.set('currentTab',tab); + }, + backToSearch : function(){ + var params = this.get('history').getSearchParams(); + if(null != params){ + this.transitionTo('design.dashboardtab', { + queryParams: { + jobType: params.type, + start: params.start, + end: params.end, + filter: params.filter + } + }); + }else{ + this.transitionTo('design.dashboardtab'); + } + }, + doRefresh : function(){ + this.refresh(); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/9bc0b996/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js ---------------------------------------------------------------------- diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js index 0fbbaa2..23609e9 100644 --- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js +++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/index.js @@ -19,6 +19,6 @@ import Ember from 'ember'; export default Ember.Route.extend({ beforeModel() { - this.transitionTo('dashboard'); + this.transitionTo('design'); } });
