Repository: ambari Updated Branches: refs/heads/trunk 5fea54102 -> 529ef7f70
http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/views/Topology/TopologySummary.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/views/Topology/TopologySummary.js b/contrib/views/storm/src/main/resources/scripts/views/Topology/TopologySummary.js deleted file mode 100644 index 75e941d..0000000 --- a/contrib/views/storm/src/main/resources/scripts/views/Topology/TopologySummary.js +++ /dev/null @@ -1,301 +0,0 @@ -/** -* 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. -*/ - -define(['require', - 'modules/Vent', - 'models/VTopology', - 'collection/VTopologyList', - 'utils/TableLayout', - 'utils/LangSupport', - 'bootbox', - 'utils/Utils', - 'utils/Globals', - 'hbs!tmpl/topology/topologySummary', - 'bootstrap' -], function(require, vent, mTopology, cTopologyList, TableLayout, localization, bootbox, Utils, Globals, tmpl) { - 'use strict'; - - var TopologySummaryTableLayout = Marionette.LayoutView.extend({ - - template: tmpl, - - templateHelpers: function() {}, - - events: { - // 'click [data-id="deployBtn"]': 'evDeployTopology' - }, - - ui: { - summaryDetails: '[data-id="summary"]' - }, - - regions: { - 'rTableList': '#summaryTable', - }, - - initialize: function() { - this.collection = new cTopologyList(); - vent.trigger('Breadcrumb:Hide'); - }, - - fetchSummary: function(topologyName) { - var that = this; - this.collection.fetch({ - success: function(collection, response, options) { - vent.trigger('LastUpdateRefresh'); - if (collection && collection.length) { - var arr = []; - _.each(collection.models[0].get('topologies'), function(object){ - if(!_.isUndefined(topologyName) && object.name === topologyName){ - Backbone.history.navigate('!/topology/'+object.id, {trigger:true}); - } else { - arr.push(new mTopology(object)); - } - }); - if(_.isUndefined(topologyName)){ - that.countActive = 0; - that.collection.reset(arr); - that.showSummaryDetail(); - } else { - $('.loading').hide(); - } - } - }, - error: function(collection, response, options){ - vent.trigger('LastUpdateRefresh'); - Utils.notifyError(response.statusText); - } - }) - }, - - onRender: function() { - this.showSummaryTable(this.collection); - $('.loading').hide(); - this.fetchSummary(); - this.showSummaryDetail(); - }, - - showSummaryDetail: function() { - var totalTopologies = 0, - activeTopologies = 0, - inactiveTopologies = 0; - if (this.collection && this.collection.length) { - totalTopologies = this.collection.length; - activeTopologies = this.countActive; - inactiveTopologies = this.collection.length - this.countActive; - } - var template = _.template('<label style="margin-right:10px">' + localization.tt('lbl.topologySummary') + ' </label>' + - '<span class="topology-summary-stats"><%- total%> ' + localization.tt('lbl.total') + '</span> | ' + - '<span class="topology-summary-stats"><%- active%> ' + localization.tt('lbl.active') + '</span> | ' + - '<span class="topology-summary-stats"><%- inactive%> ' + localization.tt('lbl.inactive') + '</span>'); - this.ui.summaryDetails.html(template({ - total: totalTopologies, - active: activeTopologies, - inactive: inactiveTopologies - })); - }, - - showSummaryTable: function(collection) { - this.rTableList.show(new TableLayout({ - columns: this.getColumns(), - collection: this.collection, - gridOpts: { - emptyText: localization.tt('msg.noTopologyFound') - } - })); - this.rTableList.$el.find('[data-id="r_tableList"]').attr("style","height:655px"); - }, - - getColumns: function() { - var that = this; - var cols = [{ - name: "name", - cell: "uri", - href: function(model) { - if(_.isEqual(model.get('status'),'ACTIVE')){ - that.countActive++; - } - return '#!/topology/' + model.get('id'); - }, - label: localization.tt("lbl.name"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryName") - }, { - name: "id", - cell: "string", - label: localization.tt("lbl.id"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryId") - }, { - name: "owner", - cell: "string", - label: localization.tt("lbl.owner"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryOwner") - }, { - name: "status", - cell: "string", - label: localization.tt("lbl.status"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryStatus") - }, { - name: "uptime", - cell: "string", - label: localization.tt("lbl.uptime"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryUptime") - }, { - name: "workersTotal", - cell: "string", - label: localization.tt("lbl.workers"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryWorkers") - }, { - name: "executorsTotal", - cell: "string", - label: localization.tt("lbl.executors"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryExecutors") - }, { - name: "tasksTotal", - cell: "string", - label: localization.tt("lbl.tasks"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryTasks") - }, { - name: "schedulerInfo", - cell: "string", - label: localization.tt("lbl.schedulerInfo"), - sortable: true, - editable: false, - hasTooltip: true, - tooltipText: localization.tt("msg.topologySummaryScheduler") - }]; - return cols; - }, - - evDeployTopology: function(e) { - var that = this; - - if (that.view) { - that.onDialogClosed(); - } - - require(['views/Topology/TopologyForm'], function(TopologyFormView) { - that.view = new TopologyFormView(); - that.view.render(); - - bootbox.dialog({ - message: that.view.el, - title: localization.tt('btn.deployNewTopology'), - className: "topology-modal", - buttons: { - cancel: { - label: localization.tt('btn.cancel'), - className: "btn-default", - callback: function() { - that.onDialogClosed(); - } - }, - success: { - label: localization.tt('btn.save'), - className: "btn-success", - callback: function() { - var errs = that.view.validate(); - if(_.isEmpty(errs)){ - that.submitTopology(); - } else return false; - } - } - } - }); - }); - }, - - submitTopology: function() { - Utils.notifyInfo(localization.tt("dialogMsg.topologyBeingDeployed")); - var attrs = this.view.getData(), - formData = new FormData(), - obj = {}, - url = Globals.baseURL + '/api/v1/uploadTopology', - that = this; - - if(!_.isEqual(attrs.jar.name.split('.').pop().toLowerCase(),'jar')){ - Utils.notifyError(localization.tt("dialogMsg.invalidFile")); - return false; - } - formData.append('topologyJar', attrs.jar); - obj.topologyMainClass = attrs.topologyClass; - obj.topologyMainClassArgs = []; - obj.topologyMainClassArgs.push(attrs.name); - - if(!_.isEmpty(attrs.arguments)){ - Array.prototype.push.apply(obj.topologyMainClassArgs,attrs.arguments.split(' ')); - } - - formData.append("topologyConfig", JSON.stringify(obj)); - - var successCallback = function(response){ - if(_.isString(response)){ - response = JSON.parse(response); - } - if(_.isEqual(response.status, 'failed')){ - $('.loading').hide(); - Utils.notifyError(response.error); - } else { - Utils.notifySuccess(localization.tt("dialogMsg.topologyDeployedSuccessfully")); - that.fetchSummary(attrs.name); - } - }; - - var errorCallback = function(){ - $('.loading').hide(); - Utils.notifyError(localization.tt("dialogMsg.topologyDeployFailed")); - }; - - Utils.uploadFile(url,formData,successCallback, errorCallback); - $('.loading').show(); - }, - - onDialogClosed: function() { - if (this.view) { - this.view.close(); - this.view.remove(); - this.view = null; - } - } - - }); - return TopologySummaryTableLayout; -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx b/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx new file mode 100644 index 0000000..bf66903 --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/views/TopologyDetailView.jsx @@ -0,0 +1,806 @@ +/** + 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. +*/ + +define([ + 'jsx!components/Table', + 'jsx!modules/Table/Pagination', + 'utils/Utils', + 'react', + 'react-dom', + 'collections/BaseCollection', + 'models/VTopology', + 'models/BaseModel', + 'jsx!containers/TopologyConfiguration', + 'jsx!containers/TopologyDetailGraph', + 'jsx!components/Breadcrumbs', + 'jsx!views/RebalanceView', + 'bootbox', + 'x-editable', + 'bootstrap', + 'bootstrap-switch' + ],function(Table, Pagination, Utils, React, ReactDOM, BaseCollection, VTopology, BaseModel, TopologyConfiguration, TopologyDetailGraph, Breadcrumbs, RebalanceView, bootbox, XEditable){ + 'use strict'; + + return React.createClass({ + displayName: 'TopologyDetailView', + getInitialState: function(){ + this.model = new VTopology({'id': this.props.id}); + this.spoutCollection = new BaseCollection(); + this.boltCollection = new BaseCollection(); + this.systemFlag = false; + this.windowSize = ':all-time'; + this.initializeData(); + return { + model: this.model, + graphData: {}, + logLevels: {}, + rebalanceModalOpen: false + }; + }, + componentWillMount: function(){ + $('.loader').show(); + }, + componentDidMount: function(){ + $(".boot-switch.systemSum").bootstrapSwitch({ + size: 'small', + onSwitchChange: function(event, state){ + this.systemFlag = state; + this.initializeData(); + }.bind(this) + }); + $("#slideContent").hide(); + $(".boot-switch.debug").bootstrapSwitch({ + size: 'small', + onSwitchChange: function(event, state){ + this.debugAction(state); + }.bind(this) + }); + $('[data-rel="tooltip"]').tooltip(); + $('.loader').hide(); + }, + componentWillUpdate: function(){ + $('.loader').show(); + $('#collapse-spout').off('hidden.bs.collapse'); + $('#collapse-spout').off('shown.bs.collapse'); + $('#collapse-bolt').off('hidden.bs.collapse'); + $('#collapse-bolt').off('shown.bs.collapse'); + $('#modal-rebalance').off('hidden.bs.modal'); + this.spoutCollection.getFirstPage().fullCollection.reset([]); + this.spouts = this.renderSpouts(); + this.boltCollection.getFirstPage().fullCollection.reset([]); + this.bolts = this.renderBolts(); + }, + componentDidUpdate: function(){ + $('#collapse-spout').on('hidden.bs.collapse', function () { + $("#spout-box").toggleClass("fa-compress fa-expand"); + }).on('shown.bs.collapse', function() { + $("#spout-box").toggleClass("fa-compress fa-expand"); + }); + + $('#collapse-bolt').on('hidden.bs.collapse', function () { + $("#bolt-box").toggleClass("fa-compress fa-expand"); + }).on('shown.bs.collapse', function() { + $("#bolt-box").toggleClass("fa-compress fa-expand"); + }); + $('#modal-rebalance').on('hidden.bs.modal', function (e) { + this.initializeData(); + this.setState({"rebalanceModalOpen":false}); + }.bind(this)); + if(this.state.rebalanceModalOpen){ + $('#modal-rebalance').modal("show"); + } + $('.loader').hide(); + }, + initializeData: function(){ + this.model.getData({ + id: this.model.get('id'), + window: this.windowSize, + sys: this.systemFlag, + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.model.set(model); + this.setState({"model": this.model}); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in fetching topology details."); + } + }); + this.initializeGraphData(); + this.initializeLogConfig(); + }, + initializeGraphData: function(){ + this.model.getGraphData({ + id: this.model.get('id'), + window: this.windowSize, + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + if(_.isString(model)){ + model = JSON.parse(model); + } + this.setState({graphData: model}); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in fetching topology visualization data."); + } + }); + }, + + initializeLogConfig: function() { + this.collection = new BaseCollection(); + this.model.getLogConfig({ + id: this.model.get('id'), + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.resetLogCollection(model); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in fetching log configuration data."); + } + }); + }, + resetLogCollection: function(model) { + this.collection.reset(); + this.setState({logLevels: model.namedLoggerLevels}); + var keys = _.keys(this.state.logLevels); + keys.map(function(key, index) { + var obj = this.state.logLevels[key]; + var model = new BaseModel({ + logger: key, + target_level: obj.target_level, + timeout: obj.timeout, + timeout_epoch: obj.timeout_epoch + }); + this.collection.add(model); + }.bind(this)); + + this.collection.add(new BaseModel({ + logger: 'com.your.organization.LoggerName', + target_level: 'ALL', + timeout: 30, + timeout_epoch: 0, + isAdd: true + })); + }, + + renderAccordion: function(type, header, searchField, searchCb, collection, emptyText, columns, toggleCb){ + return ( + <div className="box"> + <div className="box-header" data-toggle="collapse" data-target={"#collapse-"+type} aria-expanded="false" aria-controls={"collapse-"+type}> + <h4>{header}</h4> + <h4 className="box-control"> + <a href="javascript:void(0);" className="primary"> + <i className="fa fa-compress" id={type+"-box"} onClick={toggleCb}></i> + </a> + </h4> + </div> + <div className="box-body collapse in" id={"collapse-"+type}> + <div className="input-group col-sm-4"> + <input type="text" onKeyUp={searchCb} className="form-control" placeholder={"Search by "+searchField} /> + <span className="input-group-btn"> + <button className="btn btn-primary" type="button"><i className="fa fa-search"></i></button> + </span> + </div> + <Table className="table table-striped" collection={collection} emptyText={emptyText} columns={columns()} /> + <Pagination collection={collection} /> + </div> + </div> + ); + }, + renderSpouts: function(){ + if(this.state.model.has('spouts')){ + Utils.ArrayToCollection(this.state.model.get('spouts'), this.spoutCollection); + this.spoutCollection.searchFields = ['spoutId']; + var searchCb = function(e){ + var value = e.currentTarget.value; + this.spoutCollection.search(value); + }.bind(this); + var toggleCb = function(e){ + $("#collapse-spout").collapse('toggle'); + } + return this.renderAccordion('spout', 'Spouts', 'id', searchCb, this.spoutCollection, 'No spouts found !', this.getSpoutColumns, toggleCb); + } else { + return null; + } + }, + getSpoutColumns: function(){ + var self = this; + return [ + {name: 'spoutId', title: 'Id', tooltip:'The ID assigned to a the Component by the Topology. Click on the name to view the Component\'s page.', component: React.createClass({ + render: function(){ + var topologyId = self.state.model.has('id') ? self.state.model.get('id') : ""; + return ( <a href={"#!/topology/"+topologyId+"/component/"+this.props.model.get('spoutId')}>{this.props.model.get('spoutId')}</a>); + } + })}, + {name: 'executors', title: 'Executors', tooltip:'Executors are threads in a Worker process.'}, + {name: 'tasks', title: 'Tasks', tooltip:'A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.'}, + {name: 'emitted', title: 'Emitted', tooltip:'The number of Tuples emitted.'}, + {name: 'transferred', title: 'Transferred', tooltip:'The number of Tuples emitted that sent to one or more bolts.'}, + {name: 'completeLatency', title: 'Complete Latency (ms)', tooltip:'The average time a Tuple "tree" takes to be completely processed by the Topology. A value of 0 is expected if no acking is done.'}, + {name: 'acked', title: 'Acked', tooltip:'The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done.'}, + {name: 'failed', title: 'Failed', tooltip:'The number of Tuple "trees" that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done.'}, + {name: 'errorHost', title: 'Error Host:Port', component: React.createClass({ + render: function(){ + return (<span>{this.props.model.has('errorHost') && this.props.model.get('errorHost') !== '' ? this.props.model.get('errorHost')+':'+this.props.model.get('errorPort') : null}</span>); + } + })}, + {name: 'lastError', title: 'Last Error'}, + {name: 'errorTime', title: 'Error Time', component: React.createClass({ + render: function(){ + if(this.props.model.get('errorTime') != 0) { + var d = new Date(this.props.model.get('errorTime')), + date = d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); + return (<span>{date}</span>); + } else return (<span></span>); + } + })} + ]; + }, + renderBolts: function(){ + if(this.state.model.has('bolts')){ + Utils.ArrayToCollection(this.state.model.get('bolts'), this.boltCollection); + this.boltCollection.searchFields = ['boltId']; + var searchCb = function(e){ + var value = e.currentTarget.value; + this.boltCollection.search(value); + }.bind(this); + var toggleCb = function(e){ + $("#collapse-bolt").collapse('toggle'); + } + return this.renderAccordion('bolt', 'Bolts', 'id', searchCb, this.boltCollection, 'No bolts found !', this.getBoltColumns, toggleCb); + } else { + return null; + } + }, + getBoltColumns: function(){ + var self = this; + return [ + {name: 'boltId', title: 'Id', tooltip:'The ID assigned to a the Component by the Topology. Click on the name to view the Component\'s page.', component: React.createClass({ + render: function(){ + var topologyId = self.state.model.has('id') ? self.state.model.get('id') : ""; + return ( <a href={"#!/topology/"+topologyId+"/component/"+this.props.model.get('boltId')}>{this.props.model.get('boltId')}</a>); + } + })}, + {name: 'executors', title: 'Executors', tooltip:'Executors are threads in a Worker process.'}, + {name: 'tasks', title: 'Tasks', tooltip:'A Task is an instance of a Bolt or Spout. The number of Tasks is almost always equal to the number of Executors.'}, + {name: 'emitted', title: 'Emitted', tooltip:'The number of Tuples emitted.'}, + {name: 'transferred', title: 'Transferred', tooltip:'The number of Tuples emitted that sent to one or more bolts.'}, + {name: 'capacity', title: 'Capacity (last 10m)', tooltip:"If this is around 1.0, the corresponding Bolt is running as fast as it can, so you may want to increase the Bolt's parallelism. This is (number executed * average execute latency) / measurement time."}, + {name: 'executeLatency', title: 'Execute Latency (ms)', tooltip:'The average time a Tuple spends in the execute method. The execute method may complete without sending an Ack for the tuple.'}, + {name: 'executed', title: 'Executed', tooltip:'The number of incoming Tuples processed.'}, + {name: 'processLatency', title: 'Process Latency (ms)', tooltip:'The average time it takes to Ack a Tuple after it is first received. Bolts that join, aggregate or batch may not Ack a tuple until a number of other Tuples have been received.'}, + {name: 'acked', title: 'Acked', tooltip:'The number of Tuples acknowledged by this Bolt.'}, + {name: 'failed', title: 'Failed', tooltip:'The number of tuples Failed by this Bolt.'}, + {name: 'errorHost', title: 'Error Host:Port', component: React.createClass({ + render: function(){ + return (<span>{this.props.model.has('errorHost') && this.props.model.get('errorHost') !== '' ? this.props.model.get('errorHost')+':'+this.props.model.get('errorPort') : null}</span>); + } + })}, + {name: 'lastError', title: 'Last Error'}, + {name: 'errorTime', title: 'Error Time', component: React.createClass({ + render: function(){ + if(this.props.model.get('errorTime') != 0) { + var d = new Date(this.props.model.get('errorTime')), + date = d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); + return (<span>{date}</span>); + } else return (<span></span>); + } + })} + ]; + }, + renderWindowOptions: function(){ + if(this.state.model.has('topologyStats')){ + return this.state.model.get('topologyStats').map(function(object, i){ + return ( <option key={i} value={object.window}>{object.windowPretty}</option> ); + }); + } else { + return null; + } + }, + handleWindowChange: function(e){ + this.windowSize = e.currentTarget.value; + this.initializeData(); + }, + getLinks: function() { + var links = [ + {link: '#!/dashboard', title: 'Dashboard'}, + {link: '#!/topology', title: 'Topology Listing'}, + {link: 'javascript:void(0);', title: this.state.model.has('name') ? this.state.model.get('name') : ""} + ]; + return links; + }, + + addLogLevel: function(e) { + var self = this; + var id = e.currentTarget.getAttribute('data-name'); + var namedLoggerLevels = {}; + var targetLevel = $(e.currentTarget).parent().siblings().find('.target-level').val(), + timeout = $(e.currentTarget).parent().siblings().find('.timeout').html(), + logger = $(e.currentTarget).parent().siblings().find('.logger').html(); + + namedLoggerLevels[logger] = { + target_level: targetLevel, + reset_level: 'INFO', + timeout: parseInt(timeout, 10) + }; + + var dataObj = { + namedLoggerLevels: namedLoggerLevels + } + + this.model.saveLogConfig({ + id: this.model.get('id'), + data: JSON.stringify(dataObj), + contentType: "application/json", + success: function(model, response, options){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.resetLogCollection(model); + Utils.notifySuccess("Log configuration added successfully."); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in saving log configuration data."); + } + + }); + }, + applyLogLevel: function(e) { + var self = this; + var id = e.currentTarget.getAttribute('data-name'); + var namedLoggerLevels = {}; + var targetLevel = $(e.currentTarget).parents('td').siblings().find('.target-level').val(), + timeout = $(e.currentTarget).parents('td').siblings().find('.timeout').html(), + logger = $(e.currentTarget).parents('td').siblings().find('.logger').html(); + + namedLoggerLevels[logger] = { + target_level: targetLevel, + reset_level: 'INFO', + timeout: parseInt(timeout, 10) + }; + + var dataObj = { + namedLoggerLevels: namedLoggerLevels + } + + this.model.saveLogConfig({ + id: this.model.get('id'), + data: JSON.stringify(dataObj), + contentType: "application/json", + success: function(model, response, options){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.resetLogCollection(model); + Utils.notifySuccess("Log configuration applied successfully."); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in applying log configuration data."); + } + }); + }, + clearLogLevel: function(e) { + var self = this; + var id = e.currentTarget.getAttribute('data-name'); + var namedLoggerLevels = {}; + var logger = $(e.currentTarget).parents('td').siblings().find('.logger').html(); + + namedLoggerLevels[logger] = { + target_level: null, + reset_level: 'INFO', + timeout: 0 + }; + + var dataObj = { + namedLoggerLevels: namedLoggerLevels + } + + this.model.saveLogConfig({ + id: this.model.get('id'), + data: JSON.stringify(dataObj), + contentType: "application/json", + success: function(model, response, options){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.resetLogCollection(model); + Utils.notifySuccess("Log configuration cleared successfully."); + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in clearing log configuration data."); + } + }); + }, + getColumns: function(){ + var self = this; + return [ + {name: 'logger', title: 'Logger', component: React.createClass({ + render: function(){ + if(this.props.model.get('isAdd')) + return (<a href="javascript:void(0)" className="x-editable logger">{this.props.model.get('logger')}</a>); + else return (<a href="javascript:void(0)" className="logger">{this.props.model.get('logger')}</a>); + }, + componentDidMount: function() { + $(".x-editable").editable({ + mode: 'inline' + }); + }}) + }, + {name: 'target_level', title: 'Level', component: React.createClass({ + render: function() { + return ( + <select className="form-control target-level" defaultValue={this.props.model.get('target_level')}> + <option value="ALL">ALL</option> + <option value="TRACE">TRACE</option> + <option value="DEBUG">DEBUG</option> + <option value="INFO">INFO</option> + <option value="WARN">WARN</option> + <option value="ERROR">ERROR</option> + <option value="FATAL">FATAL</option> + <option value="OFF">OFF</option> + </select> + ); + } + })}, + {name: 'timeout', title: 'Timeout', component: React.createClass({ + render: function(){ + return (<a href="javascript:void(0)" className="x-editable timeout">{this.props.model.get('timeout')}</a>); + }, + componentDidMount: function() { + $(".x-editable").editable({ + mode: 'inline' + }); + }}) + }, + {name: 'timeout_epoch', title: 'Expires At', component: React.createClass({ + render: function(){ + if(this.props.model.get('timeout_epoch') != 0) { + var d = new Date(this.props.model.get('timeout_epoch')), + date = d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); + return (<span>{date}</span>); + } else return (<span></span>); + + } + }) + }, + {name: 'action', title: 'Action', component: React.createClass({ + render: function(){ + if(this.props.model.get('isAdd')) + return( + <a href="javascript:void(0)" data-name={this.props.model.get('logger')} className="btn btn-primary btn-xs" onClick={self.addLogLevel}><i className="fa fa-plus"></i></a> + ) + else + return ( + <span> + <a href="javascript:void(0)" data-name={this.props.model.get('logger')} className="btn btn-success btn-xs" onClick={self.applyLogLevel}><i className="fa fa-check"></i></a> + <a href="javascript:void(0)" data-name={this.props.model.get('logger')} className="btn btn-danger btn-xs" onClick={self.clearLogLevel}><i className="fa fa-times"></i></a> + </span> + ); + } + })} + ]; + }, + toggleSlide: function() { + $("#slideContent").slideToggle(); + }, + + renderStatsRow: function(){ + var statsArr = this.state.model.get('topologyStats'); + if(statsArr){ + return statsArr.map(function(stats, i){ + return ( + <tr key={i}> + <td>{stats.windowPretty}</td> + <td>{stats.emitted}</td> + <td>{stats.transferred}</td> + <td>{stats.completeLatency}</td> + <td>{stats.acked}</td> + <td>{stats.failed}</td> + </tr> + ); + }); + } + }, + render: function() { + var status = this.state.model.has('status') ? this.state.model.get('status') : null; + var workersTotal = this.state.model.has('workersTotal') ? this.state.model.get('workersTotal').toString() : '0'; + if(this.state.model.get('debug')){ + $(".boot-switch.debug").bootstrapSwitch('state', true, true); + } else { + $(".boot-switch.debug").bootstrapSwitch('state', false, true); + } + return ( + <div> + <Breadcrumbs links={this.getLinks()} /> + <div className="row"> + <div className="col-sm-12"> + <div className="box filter"> + <div className="box-body form-horizontal"> + <div className="form-group no-margin"> + <label className="col-sm-1 control-label">Window</label> + <div className="col-sm-2"> + <select className="form-control" onChange={this.handleWindowChange} value={this.windowSize}> + {this.renderWindowOptions()} + </select> + </div> + <label className="col-sm-2 control-label">System Summary</label> + <div className="col-sm-2"> + <input className="boot-switch systemSum" type="checkbox" /> + </div> + <label className="col-sm-1 control-label">Debug</label> + <div className="col-sm-1"> + <input className="boot-switch debug" type="checkbox"/> + </div> + <div className="col-sm-3 text-right"> + <div className="btn-group" role="group"> + <button type="button" className="btn btn-primary" onClick={this.handleTopologyActivation} title="Activate" data-rel="tooltip" disabled={status === 'ACTIVE' ? "disabled" : null}> + <i className="fa fa-play"></i> + </button> + <button type="button" className="btn btn-primary" onClick={this.handleTopologyDeactivation} title="Deactivate" data-rel="tooltip" disabled={status === 'INACTIVE' ? "disabled" : null}> + <i className="fa fa-stop"></i> + </button> + <button type="button" className="btn btn-primary" onClick={this.handleTopologyRebalancing} title="Rebalance" data-rel="tooltip" disabled={status === 'REBALANCING' ? "disabled" : null}> + <i className="fa fa-balance-scale"></i> + </button> + <button type="button" className="btn btn-primary" onClick={this.handleTopologyKilling} title="Kill" data-rel="tooltip" disabled={status === 'KILLED' ? "disabled" : null}> + <i className="fa fa-ban"></i> + </button> + <button type="button" className="btn btn-primary" onClick={this.toggleSlide} title="Change Log Level" data-rel="tooltip"> + <i className="fa fa-file-o"></i> + </button> + </div> + </div> + </div> + <div className="row" id="slideContent"> + <div className="col-sm-12"> + <hr/> + <h4 className="col-sm-offset-5">Change Log Level</h4> + <p>Modify the logger levels for topology. Note that applying a setting restarts the timer in the workers. To configure the root logger, use the name ROOT.</p> + <Table className="table no-margin" collection={this.collection} columns={this.getColumns()}/> + </div> + </div> + </div> + </div> + </div> + </div> + <div className="row"> + <div className="col-sm-4"> + <div className="summary-tile"> + <div className="summary-title">Topology Summary</div> + <div className="summary-body"> + <p><strong>ID: </strong>{this.state.model.get('id')}</p> + <p><strong>Owner: </strong>{this.state.model.get('owner')}</p> + <p><strong>Status: </strong>{this.state.model.get('status')}</p> + <p><strong>Uptime: </strong>{this.state.model.get('uptime')}</p> + <p><strong>Workers: </strong>{this.state.model.get('workersTotal')}</p> + <p><strong>Executors: </strong>{this.state.model.get('executorsTotal')}</p> + <p><strong>Tasks: </strong>{this.state.model.get('tasksTotal')}</p> + <p><strong>Memory: </strong>{this.state.model.get('assignedTotalMem')}</p> + </div> + </div> + </div> + <div className="col-sm-8"> + <div className="stats-tile"> + <div className="stats-title">Topology Stats</div> + <div className="stats-body"> + <table className="table table-enlarge"> + <thead> + <tr> + <th><span data-rel="tooltip" title="The past period of time for which the statistics apply.">Window</span></th> + <th><span data-rel="tooltip" title="The number of Tuples emitted.">Emitted</span></th> + <th><span data-rel="tooltip" title="The number of Tuples emitted that sent to one or more bolts.">Transferred</span></th> + <th><span data-rel="tooltip" title='The average time a Tuple "tree" takes to be completely processed by the Topology. A value of 0 is expected if no acking is done.'>Complete Latency (ms)</span></th> + <th><span data-rel="tooltip" title='The number of Tuple "trees" successfully processed. A value of 0 is expected if no acking is done.'>Acked</span></th> + <th><span data-rel="tooltip" title='The number of Tuple "trees" that were explicitly failed or timed out before acking was completed. A value of 0 is expected if no acking is done.'>Failed</span></th> + </tr> + </thead> + <tbody> + {this.renderStatsRow()} + </tbody> + </table> + </div> + </div> + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + <TopologyDetailGraph model={this.state.model} graphData={this.state.graphData}/> + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + {this.spouts} + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + {this.bolts} + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + <TopologyConfiguration configArr={this.state.model.get('configuration')}/> + </div> + </div> + {this.state.rebalanceModalOpen ? <RebalanceView modalId="modal-rebalance" topologyId={this.state.model.get('id')} topologyExecutors={workersTotal} spouts={this.state.model.get('spouts')} bolts={this.state.model.get('bolts')}/> : null} + </div> + ); + }, + handleTopologyActivation: function(e){ + if(this.model.get('status') !== 'ACTIVE'){ + var msg = "Do you really want to activate this topology ?"; + var successCb = function(){ + this.model.activateTopology({ + id: this.model.get('id'), + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.initializeData(); + Utils.notifySuccess("Topology activated successfully.") + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in activating topology."); + } + }); + }.bind(this); + Utils.ConfirmDialog(msg, '', successCb); + } + }, + handleTopologyDeactivation: function(e){ + if(this.model.get('status') !== 'INACTIVE'){ + var msg = "Do you really want to deactivate this topology ?"; + var successCb = function(){ + this.model.deactivateTopology({ + id: this.model.get('id'), + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.initializeData(); + Utils.notifySuccess("Topology deactivated successfully.") + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in deactivating topology."); + } + }); + }.bind(this); + Utils.ConfirmDialog(msg, '', successCb); + } + }, + handleTopologyRebalancing: function(e){ + if(this.model.get('status') !== 'REBALANCING'){ + this.setState({"rebalanceModalOpen":true}); + } + }, + handleTopologyKilling: function(e){ + if(this.model.get('status') !== 'KILLED'){ + bootbox.prompt({ + title: 'Are you sure you want to kill this topology ? If yes, please, specify wait time in seconds.', + value: "30", + buttons: { + confirm: { + label: 'Yes', + className: "btn-success", + }, + cancel: { + label: 'No', + className: "btn-default", + } + }, + callback: function(result) { + if(result != null){ + this.model.killTopology({ + id: this.model.get('id'), + waitTime: result, + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.initializeData(); + Utils.notifySuccess("Topology killed successfully.") + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in killing topology."); + } + }); + } + }.bind(this) + }); + } + }, + debugAction: function(toEnableFlag){ + if(toEnableFlag){ + bootbox.prompt({ + title: 'Do you really want to debug this topology ? If yes, please, specify sampling percentage.', + value: "10", + buttons: { + confirm: { + label: 'Yes', + className: "btn-success", + }, + cancel: { + label: 'No', + className: "btn-default", + } + }, + callback: function(result) { + if(result != null){ + this.model.debugTopology({ + id: this.model.get('id'), + debugType: 'enable', + percent: result, + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.initializeData(); + Utils.notifySuccess("Debugging enabled successfully.") + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in enabling debugging."); + } + }); + } else { + $(".boot-switch.debug").bootstrapSwitch('toggleState', true) + } + }.bind(this) + }); + } else { + var title = "Do you really want to stop debugging this topology ?"; + var successCb = function(){ + this.model.debugTopology({ + id: this.model.get('id'), + debugType: 'disable', + percent: '0', + success: function(model, response){ + if(response.error){ + Utils.notifyError(response.error); + } else { + this.initializeData(); + Utils.notifySuccess("Debugging disabled successfully.") + } + }.bind(this), + error: function(model, response, options){ + Utils.notifyError("Error occured in disabling debugging."); + } + }); + }.bind(this); + var cancelCb = function(){ + $(".boot-switch.debug").bootstrapSwitch('toggleState', true) + }.bind(this); + Utils.ConfirmDialog(' ', title, successCb, cancelCb); + } + }, + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/views/TopologyListingView.jsx ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/views/TopologyListingView.jsx b/contrib/views/storm/src/main/resources/scripts/views/TopologyListingView.jsx new file mode 100644 index 0000000..25441fa --- /dev/null +++ b/contrib/views/storm/src/main/resources/scripts/views/TopologyListingView.jsx @@ -0,0 +1,65 @@ +/** + 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. +*/ + +define([ + 'jsx!components/Table', + 'react', + 'react-dom', + 'jsx!containers/TopologyListing', + 'jsx!components/Breadcrumbs' + ],function(Table, React, ReactDOM, TopologyListing, Breadcrumbs){ + 'use strict'; + + return React.createClass({ + displayName: 'TopologyListingView', + getInitialState: function(){ + return null; + }, + componentWillMount: function(){ + $('.loader').show(); + }, + componentDidMount: function(){ + $('.loader').hide(); + }, + componentWillUpdate: function(){ + $('.loader').show(); + }, + componentDidUpdate: function(){ + $('.loader').hide(); + }, + render: function() { + return ( + <div> + <Breadcrumbs links={this.getLinks()} /> + <div className="row"> + <div className="col-sm-12"> + <TopologyListing /> + </div> + </div> + </div> + ); + }, + getLinks: function() { + var links = [ + {link: '#!/dashboard', title: 'Dashboard'}, + {link: 'javascript:void(0);', title: 'Topology Listing'} + ]; + return links; + } + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/scripts/views/site/Header.js ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/scripts/views/site/Header.js b/contrib/views/storm/src/main/resources/scripts/views/site/Header.js deleted file mode 100644 index 137f75f..0000000 --- a/contrib/views/storm/src/main/resources/scripts/views/site/Header.js +++ /dev/null @@ -1,99 +0,0 @@ -/** -* 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. -*/ - -define(['require', - 'modules/Vent', - 'utils/LangSupport', - 'hbs!tmpl/site/header'], function(require, vent, localization, headerTmpl){ - 'use strict'; - - var HeaderView = Marionette.LayoutView.extend({ - _viewNmae: 'Header', - - template: headerTmpl, - - templateHelpers: function() {}, - - regions: { - - }, - - ui: { - toplogyLink: '[data-id="topology"]', - clusterLink: '[data-id="cluster"]' - }, - - events: { - 'click [data-id="topology"]': 'showTopologySection', - 'click [data-id="cluster"]': 'showClusterSection', - 'click #refresh' : 'evRefresh' - }, - - initialize: function (options) { - this.clusterTabFlag = false; - this.bindEvent(); - }, - - bindEvent: function() { - var that = this; - vent.on('Breadcrumb:Show', function(name){ - that.$('.breadcrumb').removeClass('displayNone'); - that.$('#breadcrumbName').html(name); - }); - vent.on('Breadcrumb:Hide', function(){ - that.$('.breadcrumb').addClass('displayNone'); - }); - vent.on('LastUpdateRefresh', function(flag){ - if(flag) - that.$('.last-refreshed').css("margin-top","0px"); - else - that.$('.last-refreshed').css("margin-top","35px"); - that.$('#refreshTime').html(new Date().toLocaleString()); - }); - }, - - onRender: function () {}, - - showTopologySection: function () { - if(!this.ui.toplogyLink.parent().hasClass('active')){ - this.ui.clusterLink.parent().removeClass('active'); - this.ui.toplogyLink.parent().addClass('active'); - vent.trigger('Region:showTopologySection'); - } - }, - - showClusterSection: function () { - if(!this.ui.clusterLink.parent().hasClass('active')){ - this.ui.toplogyLink.parent().removeClass('active'); - this.ui.clusterLink.parent().addClass('active'); - vent.trigger('Region:showClusterSection'); - } - }, - - evRefresh: function(){ - if(this.ui.toplogyLink.parent().hasClass('active')){ - vent.trigger('Region:showTopologySection'); - } else { - vent.trigger('Region:showClusterSection'); - } - } - - }); - - return HeaderView; -}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/styles/default.css ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/styles/default.css b/contrib/views/storm/src/main/resources/styles/default.css deleted file mode 100644 index 8f8c431..0000000 --- a/contrib/views/storm/src/main/resources/styles/default.css +++ /dev/null @@ -1,328 +0,0 @@ -/** - * CSS Goes here - */ - -/* Generic */ -/*body { - color:#555; -}*/ -select { - padding: 3px 6px; - border: 2px #53c749 solid; - background-color: #fff; -} - -a:hover, a:focus { - text-decoration: none; -} - -fieldset { - border: 1px solid #CCC; - margin-bottom: 20px; -} - -legend { - font-size: 13px; - padding: 0 7px; -} - -[data-error]{ - color: red; -} - -.loading{ - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: url('../images/loading.gif') no-repeat center center; - background-size: 4%; - background-color: rgba(255,255,255,0.7); - z-index: 99; -} - -/* Bootsrap Extended */ -.table-borderless > thead > tr > th, -.table-borderless > tbody > tr > th, -.table-borderless > tfoot > tr > th, -.table-borderless > thead > tr > td, -.table-borderless > tbody > tr > td, -.table-borderless > tfoot > tr > td { - border:none; -} - -.backgrid .ascending .sort-caret { - vertical-align: baseline; - border-top: 0; - border-right: 4px solid transparent; - border-bottom: 4px solid; - border-left: 4px solid transparent; -} - -.backgrid .descending .sort-caret { - vertical-align: super; - border-top: 4px solid; - border-right: 4px solid transparent; - border-bottom: 0; - border-left: 4px solid transparent; -} - -.rebalance-modal .modal-body { - height: 470px; - overflow: auto; -} - -/*.tab-content>.tab-pane { - padding: 0 20px; -}*/ -.row-margin-bottom { - margin-bottom: 20px; -} -.sview-tabs .nav-tabs { - border-bottom: 2px #53c749 solid; - margin-bottom: 20px; -} -.sview-tabs .nav-tabs>li { - margin-bottom:0; - padding:10px 0; -} -.sview-tabs .nav-tabs>li>a { - color:#aaa; - font-size: 20px; - line-height:0.6; - border:none; - border-radius:0; - border-left:1px #BBB solid; -} -.sview-tabs .nav>li>a:hover { - background-color: transparent; - cursor: pointer; -} -.sview-tabs .nav-tabs>li:first-child>a { - border-left:none !important; -} -.sview-tabs .nav-tabs>li.active>a { - color:#333; - font-weight:bold; - border:none; - border-left:1px #BBB solid; -} -.topology-summary-stats { - color:#53c749; - margin-left: 5px; - margin-right: 5px; -} -.ui-widget-header { - border: 1px solid green; - background: green 50% 50% repeat-x; -} - -.modal-header { - color:#53c749; -} - -#topology .table-hover > thead > tr > th { - background-color: grey; -} - -#topology .table-hover > thead > tr > th > div > a{ - color: white; -} - -h3.topology-title { -color: #53c749; -margin-top: 0; -margin-bottom: 0; -} - -#topology .table-hover > tbody > tr:hover { - background-color: #C4ECC1; -} -.topology-tabs table tr.recent > td { - background-color: #3FC846; - color: #fff; - cursor: pointer; -} - -.topology-summary { - border: 2px #888 solid; - padding-left: 15px; - padding-left: 10px; -} -.topology-summary h4 { - color: #777; - font-weight: bold; - margin-bottom: 25px; -} -.topology-summary .table > tbody > tr > th, -.topology-summary .table > tbody > tr > td { - padding-top: 3px; - padding-bottom: 3px; -} -.topology-summary .table > tbody > tr > th { - font-weight: normal; - color: #999; - text-align: right; -} -.topology-summary .table > tbody > tr > td { - color:#53c749; -} - -.topology-graph { - border: 2px #53c749 solid; -} - -.statistics { - background-color: #F3F3F3; -} -.statistics h3 { - margin-top: 20px; - margin-bottom: 20px; -} -.topology-time-frame label { - font-weight: normal; -} - -.statistics-accordion .panel { - border-radius:0; - border: 2px #53c749 solid; -} -.statistics-accordion .panel-default > .panel-heading { - border-radius:0; - background:#fff; - color:#777; -} -.statistics-accordion .panel-heading + .panel-collapse > .panel-body { - border-top: 2px #53c749 solid; -} -.statistics-row { - border-bottom: 1px #53c749 solid; - margin-left: 20px; -} -.statistics-row:last-child { -border-bottom: 0; -} -.statistics-row.child { - padding-left: 30px; -} -.statistics-row h5 { - font-weight: bold; -} -.statistics .table > thead > tr > th, -.statistics .table > tbody > tr > td { - padding: 4px; -} -.statistics .table > thead > tr > th { - background-color: #f9f9f9; -} - -/* Clusters */ -.cluster-summary { - border: 2px #53c749 solid; - padding-left: 20px; - padding-right: 20px; -} -.cluster-summary h4 { - color: #777; - font-weight: bold; -} -.cluster-table > thead > tr > th, -.cluster-table > tbody > tr > td { - padding: 4px; -} -.cluster-table > thead > tr > th { - color: #000; -} -#topologyDetail .table > thead > tr > th > div > a { - color: black; - text-align: left; -} -.displayNone { - display: none; -} -[data-id="r_tableList"] > .table > thead > tr > th > div > a { - color: #000; -} - -/** - * Bootstrap Notification - */ -.notifications { - position: fixed; - z-index: 9999; -} - -/* Positioning */ -.notifications.top-right { - right: 10px; - top: 25px; -} - -.notifications.top-left { - left: 10px; - top: 25px; -} - -.notifications.bottom-left { - left: 10px; - bottom: 25px; -} - -.notifications.bottom-right { - right: 10px; - bottom: 25px; -} - -/* Notification Element */ -.notifications > div { - position: relative; - margin: 5px 0px; -} - -.error-notification { - position: absolute; - top: 0; - right: 5px; -} - -.breadcrumb { - line-height: 35px; - margin-left: 25px; - font-size: 12px; - color: #666; -} -.breadcrumb .seperator { - margin-left: 5px; - margin-right: 5px; -} -.statistics-container { - border: 1px solid #ddd; -} -.table-header { - border-left: 10px #53c749 solid; -} -th.sortable > div > a { - text-decoration: none; - white-space: nowrap; - cursor: pointer; -} -table tr.recent > td { - background-color: #3FC846; - color: #fff; -} -.last-refreshed { - float: right; - font-size: 12px; - margin-right: 5px; - margin-top: 35px; - color: #8B8787; -} -.refresh-icon { - padding-left: 10px; - font-size: 1.5em; - margin-left: 7px; - color: #5cb85c; - border-left: 1px #BBB solid; - cursor: pointer; -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/styles/style.css ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/styles/style.css b/contrib/views/storm/src/main/resources/styles/style.css new file mode 100644 index 0000000..e4f5be2 --- /dev/null +++ b/contrib/views/storm/src/main/resources/styles/style.css @@ -0,0 +1,497 @@ +/** + 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. +*/ +/* + Theme: Apache Storm + Author: Sanket +*/ + +*:focus { + outline: none !important; +} + +body { + font-family: 'Lato', sans-serif; + color: #4b4b4b; +} + +/* Bootstrap Extended */ +.no-margin { + margin: 0px; +} + +.row-margin-bottom { + margin-bottom: 20px; +} + +.table-borderless>tbody>tr>td, +.table-borderless>tbody>tr>th, +.table-borderless>tfoot>tr>td, +.table-borderless>tfoot>tr>th, +.table-borderless>thead>tr>td, +.table-borderless>thead>tr>th { + border-top: none; +} +.table-enlarge > thead > tr > th, +.table-enlarge > tbody > tr > th, +.table-enlarge > tfoot > tr > th, +.table-enlarge > thead > tr > td, +.table-enlarge > tbody > tr > td, +.table-enlarge > tfoot > tr > td { + padding: 11px; +} +#breadcrumb { + margin-top: 15px; + list-style: none; + display: inline-block; + padding: 0px; +} +#breadcrumb .icon { + font-size: 14px; +} +#breadcrumb li { + float: left; +} +#breadcrumb li a { + color: #FFF; + display: block; + background: #27a9e1; + text-decoration: none; + position: relative; + height: 30px; + line-height: 30px; + padding: 0 10px 0 5px; + text-align: center; + margin-right: 23px; +} +#breadcrumb li:nth-child(even) a { + background-color: #1b75bb; +} +#breadcrumb li:nth-child(even) a:before { + border-color: #1b75bb; + border-left-color: transparent; +} +#breadcrumb li:nth-child(even) a:after { + border-left-color: #1b75bb; +} +#breadcrumb li:first-child a { + padding-left: 15px; + -moz-border-radius: 4px 0 0 4px; + -webkit-border-radius: 4px; + border-radius: 4px 0 0 4px; +} +#breadcrumb li:first-child a:before { + border: none; +} +#breadcrumb li:last-child a { + padding-right: 15px; + -moz-border-radius: 0 4px 4px 0; + -webkit-border-radius: 0; + border-radius: 0 4px 4px 0; +} +#breadcrumb li:last-child a:after { + border: none; +} +#breadcrumb li a:before, #breadcrumb li a:after { + content: ""; + position: absolute; + top: 0; + border: 0 solid #27a9e1; + border-width: 15px 10px; + width: 0; + height: 0; +} +#breadcrumb li a:before { + left: -20px; + border-left-color: transparent; +} +#breadcrumb li a:after { + left: 100%; + border-color: transparent; + border-left-color: #27a9e1; +} +#breadcrumb li a:hover { + background-color: #1bbb60; +} +#breadcrumb li a:hover:before { + border-color: #1bbb60; + border-left-color: transparent; +} +#breadcrumb li a:hover:after { + border-left-color: #1bbb60; +} + +/* Boxes */ +.box { + position: relative; + margin-bottom: 15px; + border: 1px #bcbcbc solid; + border-bottom-width: 3px; + border-radius: 5px; +} +.box .box-header:before, +.box .box-header:after { + content: " "; + display: table; +} +.box .box-header:after { + clear: both; +} +.box .box-header { + background-color: #f3f6f9; + padding: 0 10px; + border-bottom: 1px #bcbcbc solid; + border-radius: 4px 4px 0px 0px; +} +.box .box-header h4 { + float: left; + margin: 0px; + font-size: 16px; + font-weight: 700; + line-height: 40px; + letter-spacing: 1px; +} +.box .box-header .box-control { + float: right; +} +.box .box-header .box-control a { + display: inline-block; + width: 20px; + height: 20px; + font-size: 12px; + line-height: 20px; + text-align: center; + margin: 10px 2px; + border-radius: 50%; + background-color: #4b4b4b; + color: rgba(255,255,255,0.75); +} +/*.box .box-header .box-control a i { + visibility: hidden; +} +.box .box-header .box-control:hover a i { + visibility: visible; +}*/ +.box .box-header .box-control a.primary {background-color: #1b75bb;} +.box .box-header .box-control a.success {background-color: #1bbb60;} +.box .box-header .box-control a.info {background-color: #27a9e1;} +.box .box-header .box-control a.warning {background-color: #fbaf3f;} +.box .box-header .box-control a.danger {background-color: #ff5816;} +.box .box-header .box-control a.secondary {background-color: #df206a;} + +.box .box-body { + padding: 10px; +} +.box .box-body.paddless { + padding: 0px; +} + +.control-search { + position: relative; +} +.control-search input[type="text"] { + width: 250px; + margin-top: 5px; + padding: 4px 24px 4px 4px; + background-color: transparent; + border: none; + border-bottom: 1px #BCBCBC solid; +} +.control-search i.fa-search { + position: absolute; + right: 6px; + top: 12px; + color: #999; +} + +.box.filter { + border-color: #27a9e1; +} +.box.info { + border-color: #27a9e1; +} +.box.info .box-header { + background-color: #E9F8FF; + border-color: #27a9e1; +} +.box.warning { + border-color: #fbaf3f; +} +.box.warning .box-header { + background-color: #FFF6E9; + border-color: #fbaf3f; +} + +/*Tiles*/ +.tile { + display: block; + margin-bottom: 15px; + color: #fff; + border-radius: 2px; +} +.tile .tile-header { + letter-spacing: 2px; + padding: 8px 12px; + line-height: 1.5; + text-transform: uppercase; + font-size: 11px; + border-top-right-radius: 2px; + border-top-left-radius: 2px; +} +.tile .tile-body { + overflow: hidden; + padding: 12px; +} +.tile .tile-body i.fa { + font-size: 30px; + opacity: .4; +} +.tile .tile-body .count { + float: right; + font-size: 30px; + line-height: 30px; + font-weight: 300; +} +.tile.primary { + background: #1b75bb; +} +.tile.primary > .tile-header { + background-color: #085C9D; +} +.tile.warning { + background: #fbaf3f; +} +.tile.warning > .tile-header { + background-color: #ED940E; +} +.tile.success { + background: #1bbb60; +} +.tile.success > .tile-header { + background-color: #00A347; +} +.tile.danger { + background: #ff5816; +} +.tile.danger > .tile-header { + background-color: #D13B00; +} + +.summary-tile { + display: block; + margin-bottom: 15px; + color: #fff; + border-radius: 5px; + background-color: #1B76BB; +} +.summary-tile .summary-title { + letter-spacing: 2px; + padding: 8px 12px; + line-height: 1.5; + text-transform: uppercase; + border-top-right-radius: 5px; + border-top-left-radius: 5px; + background-color: #085C9D; +} +.summary-tile .summary-body { + overflow: hidden; + padding: 12px; +} +.summary-tile .summary-body a{ + color: #fff; + text-decoration: underline; +} +.summary-tile .summary-body strong { + display: inline-block; + width: 100px; + margin-right: 10px; + text-align: right; +} + +.stats-tile { + display: block; + margin-bottom: 15px; + color: #333; + border-radius: 5px; + background-color: #EEEEEE; +} +.stats-tile .stats-title { + letter-spacing: 2px; + padding: 8px 12px; + line-height: 1.5; + text-transform: uppercase; + border-top-right-radius: 5px; + border-top-left-radius: 5px; + background-color: #C0C0C0; +} +.stats-tile .stats-body { + overflow: hidden; + padding: 12px; +} + +/* Detail Page */ +.graph-bg { + background-image: linear-gradient(to right, rgb(0, 0, 0) -10px, transparent 1px), linear-gradient(rgb(0, 0, 0) -10px, transparent 1px); + background-size: 10px 10px; + min-height: 300px; +} +.summary-panel { + font-size: 90%; + padding: 10px; + background: #f9f9f9; + border: 1px solid #ccc; + border-bottom-width: 2px; + border-left-width: 2px; + box-shadow: -1px 1px 5px rgba(0,0,0,0.25); +} +.circle { + float: left; + margin-right: 15px; +} + +/* +REACT + */ +#supervisorCount, +#slotsCount { + position: 'relative'; + display: 'inline-block' +} +#supervisorCount > svg > g > text, +#slotsCount > svg > g > text { + font-size: 27px; + fill: white; +} +.supervisor-table svg > g > text { + font-size: 12px; + fill: black; +} +#supervisorCount > svg > g > text.percent, +#slotsCount > svg > g > text.percent { + font-size: 18px; +} +#supervisorCount > svg > g > text.graphVal, +#slotsCount > svg > g > text.graphVal { + font-weight: 300; +} +/* D3 */ +.d3-tip { + z-index: 99; + line-height: 1; + font-weight: bold; + padding: 5px; + background: rgba(0, 0, 0, 0.8); + color: #fff; + border-radius: 2px; + font-size: 12px; +} +.d3-tip .summary { + padding: 3px; +} + +/* Creates a small triangle extender for the tooltip */ +.d3-tip:after { + box-sizing: border-box; + display: inline; + font-size: 16px; + width: 100%; + line-height: 1; + color: rgba(0, 0, 0, 0.8); + content: "\25BC"; + position: absolute; + text-align: center; +} + +/* Style northward tooltips differently */ +.d3-tip.n:after { + margin: -4px 0 0 0; + top: 100%; + left: 0; +} +path.link { + fill: none; + stroke: grey; + cursor: default; +} + +path.link.dragline { + pointer-events: none; +} + +path.link.hidden { + stroke-width: 0; +} + +circle.node { + stroke-width: 1.5px; + cursor: pointer; +} + +circle.node.reflexive { + stroke: #000 !important; + stroke-width: 2.5px; +} +text.id { + text-anchor: middle; + font-weight: bold; +} +.d3-tip ul { + padding:0; + margin:0; + list-style: none; +}⨠+.d3-tip ul li { + font-size: 12px; + line-height: 20px; +} +marker { + fill: grey; +} +.table-summary { + font-size: 12px; + font-weight: 700; + -webkit-font-smoothing: antialiased; +} +.summary-badge { + font-weight: bold; + padding: 1px 4px; + margin: 1px; + border: 1px solid #d8d8d8; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +[data-toggle="collapse"]{ + cursor: pointer; +} +#ex1Slider { + margin-left: 13px; + margin-right: 13px; +} +#modal-rebalance .modal-body{ + max-height: 450px; + overflow-y: auto; +} +.loader { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: url('../images/loader.gif') rgba(255,255,255,0.75) no-repeat center center; + z-index: 9; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/cluster/clusterSummary.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/cluster/clusterSummary.html b/contrib/views/storm/src/main/resources/templates/cluster/clusterSummary.html deleted file mode 100644 index 91d3341..0000000 --- a/contrib/views/storm/src/main/resources/templates/cluster/clusterSummary.html +++ /dev/null @@ -1,83 +0,0 @@ -<!-- -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. Kerberos, LDAP, Custom. Binary/Htt ---> -<div class="row row-margin-bottom"> - <div class="col-md-6" data-id="clusterSummaryTable"></div> - <div class="col-md-12"> - <div class="cluster-summary"> - <h4>{{tt "h.clusterSummary"}}</h4> - <div class="row" id="clusterSummaryTable"></div> - </div> - </div> -</div> - -<div class="row row-margin-bottom"> - <div class="col-md-12" data-id="nbsSummary"> - <div class="panel-group statistics-accordion" role="tablist" aria-multiselectable="true"> - <div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingOne"> - <h6 class="panel-title"> - <a data-toggle="collapse" href="#collapseNimbSum" aria-expanded="true" aria-controls="collapseNimbSum" class=""> - <i class="fa fa-minus-square"></i> {{tt "h.nimbusSummary"}}</a> - </h6> - </div> - <div id="collapseNimbSum" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true"> - <div class="panel-body"> - <div class="row" id="nbsSummaryTable"> </div> - </div> - </div> - </div> - </div> - </div> -</div> - -<div class="row row-margin-bottom"> - <div class="col-md-12" data-id="sprSummary"> - <div class="panel-group statistics-accordion" role="tablist" aria-multiselectable="true"> - <div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingTwo"> - <h6 class="panel-title"> - <a data-toggle="collapse" href="#collapseSubSum" aria-expanded="true" aria-controls="collapseSubSum"> - <i class="fa fa-minus-square"></i> {{tt "h.supervisorSummary"}}</a> - </h6> - </div> - <div id="collapseSubSum" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne"> - <div class="panel-body"> - <div class="row" id="sprSummaryTable"> <div class="row"> </div> </div> - </div> - </div> - </div> - </div> - </div> -</div> - -<div class="row row-margin-bottom"> - <div class="col-md-12" data-id="nbsConfig"> - <div class="panel-group statistics-accordion" role="tablist" aria-multiselectable="true"> - <div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingThree"> - <h6 class="panel-title"> - <a data-toggle="collapse" href="#collapseNbs" aria-expanded="true" aria-controls="collapseNbs"> - <i class="fa fa-plus-square"></i> {{tt "h.nimbusConfiguration"}}</a> - </h6> - </div> - <div id="collapseNbs" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne"> - <div class="panel-body"> <div class="row" id="nbsConfigTable"> </div> </div> - </div> - </div> - </div> - </div> -</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/site/header.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/site/header.html b/contrib/views/storm/src/main/resources/templates/site/header.html deleted file mode 100644 index 501c259..0000000 --- a/contrib/views/storm/src/main/resources/templates/site/header.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- -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. Kerberos, LDAP, Custom. Binary/Htt ---> -<div class="sview-tabs"> - <ul class="nav nav-tabs" role="tablist"> - <li role="presentation" class="active"><a role="tab" data-toggle="tab" data-id="topology">{{tt 'h.topologies'}}</a></li> - <li role="presentation"><a role="tab" data-toggle="tab" data-id="cluster">{{tt 'h.cluster'}}</a></li> - <span class="breadcrumb displayNone"><a href="#!/topology">{{tt 'h.topologies'}}</a> <i class="fa fa-angle-double-right seperator"></i><span id="breadcrumbName"></span></span> - <span class="last-refreshed">Last refreshed @ - <span id="refreshTime"></span> - <span class="refresh-icon" id="refresh" data-toggle="tooltip" title="Refresh Now"> - <i class="fa fa-refresh"></i> - </span> - </span> - </ul> -</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/spout/spoutItemView.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/spout/spoutItemView.html b/contrib/views/storm/src/main/resources/templates/spout/spoutItemView.html deleted file mode 100644 index 539fa18..0000000 --- a/contrib/views/storm/src/main/resources/templates/spout/spoutItemView.html +++ /dev/null @@ -1,46 +0,0 @@ -<!-- -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. Kerberos, LDAP, Custom. Binary/Htt ---> -<div> - <div class="row row-margin-bottom"> - <div class="col-md-12"> - <div class="statistics-container"> - <div data-id="SpoutsSummaryTable"></div> - - <div class="row statistics-row"> - <div class="col-md-12"> - <h5>{{tt 'lbl.outputStats'}}</h5> - <div data-id="OpstSummaryTable"></div> - </div> - </div> - - <div class="row statistics-row"> - <div class="col-md-12"> - <h5>{{tt 'lbl.executors'}}</h5> - <div data-id="ExtrSummaryTable"></div> - </div> - </div> - - <div class="row statistics-row"> - <div class="col-md-12"> - <h5>{{tt 'lbl.errors'}}</h5> - <div data-id="ErrorSummaryTable"></div> - </div> - </div> - </div> - </div> - </div> -</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/topology/rebalanceForm.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/topology/rebalanceForm.html b/contrib/views/storm/src/main/resources/templates/topology/rebalanceForm.html deleted file mode 100644 index 0fbd6c2..0000000 --- a/contrib/views/storm/src/main/resources/templates/topology/rebalanceForm.html +++ /dev/null @@ -1,26 +0,0 @@ -<form class="form-horizontal"> - <fieldset> - <legend>Worker</legend> - <div class="" data-fields="workers"></div> - </fieldset> - {{#if showParallelism}} - <fieldset> - <legend>Parallelism</legend> - {{#if spoutFlag}} - {{#each spoutData}} - <div class="" data-fields="{{this}}"></div> - {{/each}} - - {{/if}} - {{#if boltFlag}} - {{#each boltData}} - <div class="" data-fields="{{this}}"></div> - {{/each}} - {{/if}} - </fieldset> - {{/if}} - <fieldset> - <legend>Wait Time</legend> - <div class="" data-fields="waitTime"></div> - </fieldset> -</form> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/topology/topologyDetail.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/topology/topologyDetail.html b/contrib/views/storm/src/main/resources/templates/topology/topologyDetail.html deleted file mode 100644 index d530b6f..0000000 --- a/contrib/views/storm/src/main/resources/templates/topology/topologyDetail.html +++ /dev/null @@ -1,108 +0,0 @@ -<!-- -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. Kerberos, LDAP, Custom. Binary/Htt ---> -<div class="row row-margin-bottom"> - <div class="col-md-3"><h3 class="topology-title"></h3></div> - <div class="col-md-3 topology-time-frame"> - <label> {{tt 'lbl.selectTimeFrame'}} : </label> - <select id="tFrame"></select> - </div> - <div class="col-md-2"> - <form class="form-inline"> - <div class="checkbox"><label><input id="sysBolt" type="checkbox"> {{tt 'lbl.showSystemBolt'}} </label></div> - </form> - </div> - <div class="col-md-4"> - <div class="btn-group-sm pull-right"> - <button id="btnActivate" class="btn btn-success btn-sm">{{tt 'btn.activate'}} </button> - <button id="btnDeactivate" class="btn btn-success btn-sm">{{tt 'btn.deactivate'}} </button> - <button id="btnRebalance" class="btn btn-success btn-sm">{{tt 'btn.rebalance'}} </button> - <button id="btnKill" class="btn btn-success btn-sm">{{tt 'btn.kill'}} </button> - </div> - </div> -</div> - -<div class="row row-margin-bottom"> - <div id="topologyDetail" class="col-md-12"></div> -</div> - -<div class="row row-margin-bottom"> - <div class="col-md-9"> - <div id="graph" class="topology-graph"></div> - </div> - <div class="col-md-3"> - <div class="topology-summary"> - <h4 align="center">{{tt 'lbl.topologySummary'}} </h4> - <div id="topo-summary"></div> - </div> - </div> -</div> -<div class="row"> - <div class="col-md-12 statistics"> - <!--h3>Statistics <button class="pull-right btn btn-success btn-sm">Open All</button></h3--> - <h3>{{tt 'lbl.statistics'}}</h3> - <div class="panel-group statistics-accordion" role="tablist" aria-multiselectable="true"> - <!-- 1st Accordion Begin --> - <div class="panel panel-default"> - <div class="panel-heading" role="tab"> - <h6 class="panel-title"> - <a class="collapsed" data-toggle="collapse" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> - <i class="fa fa-plus-square"></i> {{tt 'lbl.spouts'}}</a> - </h6> - </div> - <div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne"> - <div class="panel-body" id="SpoutsTable"></div> - </div> - </div> - <!-- 1st Accordion End --> - - <!-- 2nd Accordion Begin --> - <div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingTwo"> - <h6 class="panel-title"> - <a class="collapsed" data-toggle="collapse" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"><span class="fa fa-plus-square"></span> {{tt 'lbl.bolts'}}</a> - </h6> - </div> - <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo"> - <div class="panel-body"> - <div class="row statistics-row"> - <div id="BoltsSummaryTable"></div> - </div> - </div> - </div> - </div> - <!-- 2nd Accordion End --> - - <!-- 3rd Accordion Begin --> - <div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingThree"> - <h6 class="panel-title"> - <a class="collapsed" data-toggle="collapse" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree"><span class="fa fa-plus-square"></span> {{tt 'lbl.topologyConfig'}}</a> - </h6> - </div> - <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree"> - <div class="panel-body"> - <div class="row statistics-row"> - <div id="TopologyConfigTable"></div> - </div> - </div> - </div> - </div> - <!-- 3rd Accordion End --> - - </div> - </div> -</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/topology/topologyForm.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/topology/topologyForm.html b/contrib/views/storm/src/main/resources/templates/topology/topologyForm.html deleted file mode 100644 index b3d6811..0000000 --- a/contrib/views/storm/src/main/resources/templates/topology/topologyForm.html +++ /dev/null @@ -1,6 +0,0 @@ -<form class="form-horizontal"> - <div class="" data-fields="name"></div> - <div class="" data-fields="jar"></div> - <div class="" data-fields="topologyClass"></div> - <div class="" data-fields="arguments"></div> -</form> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/templates/topology/topologySummary.html ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/templates/topology/topologySummary.html b/contrib/views/storm/src/main/resources/templates/topology/topologySummary.html deleted file mode 100644 index b9fdb6f..0000000 --- a/contrib/views/storm/src/main/resources/templates/topology/topologySummary.html +++ /dev/null @@ -1,23 +0,0 @@ -<!-- -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. Kerberos, LDAP, Custom. Binary/Htt ---> -<div class="row row-margin-bottom"> - <div class="col-md-6" data-id="summary"></div> - <!-- <div class="col-md-6"> - <button class="btn btn-success btn-sm pull-right" data-id="deployBtn"> {{tt 'btn.deployNewTopology'}} </button> - </div> --> -</div> -<div class="row" id="summaryTable"></div> http://git-wip-us.apache.org/repos/asf/ambari/blob/529ef7f7/contrib/views/storm/src/main/resources/view.xml ---------------------------------------------------------------------- diff --git a/contrib/views/storm/src/main/resources/view.xml b/contrib/views/storm/src/main/resources/view.xml index 36cc32b..cbcf4ff 100644 --- a/contrib/views/storm/src/main/resources/view.xml +++ b/contrib/views/storm/src/main/resources/view.xml @@ -20,4 +20,13 @@ limitations under the License. Kerberos, LDAP, Custom. Binary/Htt <version>0.1.0</version> <build>${env.BUILD_NUMBER}</build> <description>Ambari view for Apache Storm</description> -</view> + <auto-instance> + <name>STORM_CLUSTER_INSTANCE</name> + <label>Storm View</label> + <description>Storm View (auto-created)</description> + <stack-id>HDP-2.*</stack-id> + <services> + <service>STORM</service> + </services> + </auto-instance> +</view> \ No newline at end of file