Browse Source

AMBARI-4456. Jobs: implement the Apps page/table. (alexantonenko)

Alex Antonenko 11 years ago
parent
commit
4a1eaf22db

+ 2 - 1
ambari-web/app/config.js

@@ -69,7 +69,8 @@ App.supports = {
   deleteHost: true,
   autoRollbackHA: false,
   appTimelineServer: false,
-  storm: false
+  storm: false,
+  jobs: false
 };
 
 if (App.enableExperimental) {

+ 1 - 0
ambari-web/app/controllers.js

@@ -108,6 +108,7 @@ require('controllers/main/charts/heatmap_metrics/heatmap_metric_hbase_regions');
 require('controllers/main/charts/heatmap_metrics/heatmap_metric_hbase_memstoresize');
 require('controllers/main/charts/heatmap');
 require('controllers/main/apps_controller');
+require('controllers/main/jobs_controller');
 require('controllers/main/apps/item_controller');
 require('controllers/main/mirroring_controller');
 require('controllers/main/mirroring/edit_dataset_controller');

+ 65 - 0
ambari-web/app/controllers/main/jobs_controller.js

@@ -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.
+ */
+
+var App = require('app');
+
+App.MainJobsController = App.MainAppsController.extend({
+
+  name:'mainJobsController',
+
+  content: [],
+
+  loaded : false,
+  loading : false,
+
+  clearFilters: function () {
+    var obj=this.get("filterObject");
+    obj.set("id","");
+    obj.set("user","");
+    obj.set("startTime","");
+    obj.set("endTime","");
+  },
+
+  //Filter object
+
+  filterObject : Ember.Object.create({
+    id:"",
+    user:"",
+    startTime:"",
+    endTime:"",
+
+
+    allFilterActivated:false,
+    filteredDisplayRecords:null,
+
+    viewType:"all",
+    viewTypeClickEvent:false
+
+  }),
+
+  columnsName: Ember.ArrayController.create({
+    content: [
+      { name: Em.I18n.t('jobs.column.id'), index: 0 },
+      { name: Em.I18n.t('jobs.column.user'), index: 1 },
+      { name: Em.I18n.t('jobs.column.start.time'), index: 2 },
+      { name: Em.I18n.t('jobs.column.end.time'), index: 3 },
+      { name: Em.I18n.t('jobs.column.duration'), index: 4 }
+    ]
+  })
+
+})

+ 2 - 2
ambari-web/app/controllers/main/mirroring/jobs_controller.js

@@ -18,8 +18,8 @@
 
 var App = require('app');
 
-App.MainJobsController = Em.Controller.extend({
-  name: 'mainJobsController',
+App.MainDatasetJobsController = Em.Controller.extend({
+  name: 'mainDatasetJobsController',
 
   isLoaded: function () {
     return App.router.get('mainMirroringController.isLoaded');

+ 11 - 0
ambari-web/app/messages.js

@@ -1698,6 +1698,17 @@ Em.I18n.translations = {
   'tableView.filters.paginationInfo': '{0} - {1} of {2}',
   'tableView.filters.clearAllFilters': 'clear filters',
 
+  'jobs.type':'Jobs Type',
+  'jobs.type.hive':'Hive',
+  'jobs.show.up.to':'Show up to',
+  'jobs.filtered.jobs':'{0} of {1} jobs showing',
+  'jobs.filtered.clear':'clear filters',
+  'jobs.column.id':'Id',
+  'jobs.column.user':'User',
+  'jobs.column.start.time':'Start Time',
+  'jobs.column.end.time':'End Time',
+  'jobs.column.duration':'Duration',
+
   'apps.table.column.appId':'App ID',
   'apps.table.column.runDate': 'Run Date',
   'apps.avgTable.avg': 'Avg',

+ 21 - 12
ambari-web/app/routes/main.js

@@ -96,19 +96,28 @@ module.exports = Em.Route.extend({
       router.transitionTo(event.context);
     }
   }),
-    apps: Em.Route.extend({
-      route: '/apps',
-      connectOutlets: function (router) {
-        if (App.get('isHadoop2Stack')) {
-          Em.run.next(function () {
-            router.transitionTo('main.dashboard');
-          });
-        } else {
-          router.get('mainAppsController').loadRuns();
-          router.get('mainController').connectOutlet('mainApps');
-        }
+
+  apps: Em.Route.extend({
+    route: '/apps',
+    connectOutlets: function (router) {
+      if (App.get('isHadoop2Stack')) {
+        Em.run.next(function () {
+          router.transitionTo('main.dashboard');
+        });
+      } else {
+        router.get('mainAppsController').loadRuns();
+        router.get('mainController').connectOutlet('mainApps');
       }
-    }),
+    }
+  }),
+
+  jobs: Em.Route.extend({
+    route: '/jobs',
+    connectOutlets: function (router) {
+      router.get('mainJobsController').loadRuns();
+      router.get('mainController').connectOutlet('mainJobs');
+    }
+  }),
 
   mirroring: Em.Route.extend({
     route: '/mirroring',

+ 16 - 1
ambari-web/app/styles/apps.less

@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-#apps{
+#apps, #jobs{
 
   td .red {
     color: red;
@@ -35,6 +35,21 @@
     }
   }
 
+  .jobs-type {
+    float: right;
+    margin-top: -24px;
+  }
+  
+  #filtered-jobs{
+    float: left;
+    margin-top: 8px;
+  }
+
+  .jobs_head{
+    height: 30px;
+  }
+
+
   #filter_buttons a.selected{
     cursor: default;
   }

+ 69 - 0
ambari-web/app/templates/main/jobs.hbs

@@ -0,0 +1,69 @@
+{{!
+* 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.
+}}
+
+<div id="apps">
+
+    <div class="jobs_head">
+      <div>{{t menu.item.jobs}}</div>
+      <div class="jobs-type">
+       {{t jobs.type}} :
+       <button class="btn single-btn-group">
+        {{t jobs.type.hive}}
+       </button>
+      </div>
+    </div>
+
+    <table class="table table-striped runsList">
+        <thead>
+        {{#view view.wrapSorting}}
+          {{#each controller.columnsName}}
+            {{#view view.parentView.sortingColumns contentBinding="this"}}
+              {{name}}
+            {{/view}}
+          {{/each}}
+        {{/view}}
+        <tr>
+            <th>{{view view.jobsIdFilterView}}</th>
+            <th>{{view view.userFilterView}}</th>
+            <th>{{view view.startTimeFilterView}}</th>
+            <th>{{view view.endTimeFilterView}}</th>
+            <th></th>
+        </tr>
+        </thead>
+        <tbody>
+        {{#if  view.emptyData}}
+            <tr>
+                <td class="no-data" {{bindAttr colspan="controller.columnsName.content.length"}}>{{t apps.filters.nothingToShow}}</td>
+            </tr>
+        {{else}}
+          {{#each run in content}}
+            {{view view.containerRow runBinding="run" currentViewBinding="view.appTableRow"}}
+          {{/each}}
+        {{/if}}
+        </tbody>
+    </table>
+
+    <div class="page-bar">
+        <div id="filtered-jobs">
+          {{view.filteredJobs}} - <a href="javascript:void(null);" {{action clearFilters target="controller"}}>{{t jobs.filtered.clear}}</a>
+        </div>
+        <div class="items-on-page">
+            <label>{{t jobs.show.up.to}}: {{view view.showNumberOfJobs selectionBinding="controller.filterObject.iDisplayLength"}}</label>
+        </div>
+    </div>
+</div>

+ 1 - 0
ambari-web/app/views.js

@@ -211,6 +211,7 @@ require('views/main/charts/heatmap/heatmap_rack');
 require('views/main/charts/heatmap/heatmap_host');
 require('views/main/charts/heatmap/heatmap_host_detail');
 require('views/main/apps_view');
+require('views/main/jobs_view');
 require('views/main/apps/item_view');
 require('views/main/apps/item/bar_view');
 require('views/main/apps/item/dag_view');

+ 97 - 0
ambari-web/app/views/main/jobs_view.js

@@ -0,0 +1,97 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+var filters = require('views/common/filter_view');
+
+App.MainJobsView = App.MainAppsView.extend({
+  templateName: require('templates/main/jobs'),
+
+  showNumberOfJobs: Em.Select.extend({
+    selected: '10',
+    content: ['10', '25', '50', '100', "250", "500"]
+  }),
+
+  filteredJobs: function () {
+    return Em.I18n.t('jobs.filtered.jobs').format(0,0);
+  }.property(),
+
+  /**
+   * Filter-field for Jobs ID.
+   * Based on <code>filters</code> library
+   */
+  jobsIdFilterView: filters.createTextView({
+    valueBinding: "controller.filterObject.id"
+  }),
+
+  /**
+   * Filter-list for User.
+   * Based on <code>filters</code> library
+   */
+  userFilterView: filters.createComponentView({
+    /**
+     * Inner FilterView. Used just to render component. Value bind to <code>mainview.value</code> property
+     * Base methods was implemented in <code>filters.componentFieldView</code>
+     */
+    filterView: filters.componentFieldView.extend({
+      templateName:require('templates/main/apps/user_filter'),
+
+      usersBinding: 'controller.users',
+
+      allComponentsChecked:false,
+      toggleAllComponents:function () {
+        var checked = this.get('allComponentsChecked');
+        this.get('users').setEach('checked', checked);
+      }.observes('allComponentsChecked'),
+
+      clearFilter:function() {
+        this.set('allComponentsChecked', false);
+        this.get('users').setEach('checked', false);
+        this._super();
+      },
+
+      applyFilter:function() {
+        this._super();
+        var chosenUsers = this.get('users').filterProperty('checked', true).mapProperty('name');
+        this.set('value', chosenUsers.toString());
+      }
+    }),
+
+    valueBinding: 'controller.filterObject.user'
+  }),
+
+  /**
+   * Filter-field for Start Time.
+   * Based on <code>filters</code> library
+   */
+  startTimeFilterView: filters.createSelectView({
+    fieldType: 'input-medium',
+    valueBinding: "controller.filterObject.startTime",
+    content: ['Any', 'Past 1 hour',  'Past 1 Day', 'Past 2 Days', 'Past 7 Days', 'Past 14 Days', 'Past 30 Days', 'Custom']
+  }),
+
+  /**
+   * Filter-field for Start Time.
+   * Based on <code>filters</code> library
+   */
+  endTimeFilterView: filters.createSelectView({
+    fieldType: 'input-medium',
+    valueBinding: "controller.filterObject.endTime",
+    content: ['Any', 'Custom']
+  })
+})

+ 2 - 0
ambari-web/app/views/main/menu.js

@@ -39,6 +39,8 @@ App.MainMenuView = Em.CollectionView.extend({
 
     if (!App.get('isHadoop2Stack')) {
       result.push({ label:Em.I18n.t('menu.item.jobs'), routing:'apps'});
+    }else if (App.supports.jobs) {
+      result.push({ label:Em.I18n.t('menu.item.jobs'), routing:'jobs'});
     }
 
     if (App.get('isAdmin')) {

+ 1 - 1
ambari-web/app/views/main/mirroring/jobs_view.js

@@ -20,7 +20,7 @@ var App = require('app');
 var filters = require('views/common/filter_view');
 var sort = require('views/common/sort_view');
 
-App.MainJobsView = App.TableView.extend({
+App.MainDatasetJobsView = App.TableView.extend({
   templateName: require('templates/main/mirroring/jobs'),
   content: function () {
     return this.get('controller.jobs');