You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/01/19 23:25:53 UTC

tez git commit: TEZ-3049. Tez UI 2: Add column selector (sree)

Repository: tez
Updated Branches:
  refs/heads/TEZ-2980 c613d4833 -> 5c726547d


TEZ-3049. Tez UI 2: Add column selector (sree)


Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/5c726547
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/5c726547
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/5c726547

Branch: refs/heads/TEZ-2980
Commit: 5c726547d8e960454a9898793607a7bc40f715c6
Parents: c613d48
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Wed Jan 20 03:55:24 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Wed Jan 20 03:55:24 2016 +0530

----------------------------------------------------------------------
 TEZ-2980-CHANGES.txt                            |   1 +
 .../webapp/app/components/column-selector.js    | 105 +++++++++++++++++++
 .../webapp/app/components/table-controls.js     |  29 +++++
 .../main/webapp/app/controllers/table-page.js   |  60 +++++++++++
 .../src/main/webapp/app/routes/application.js   |  26 +++++
 tez-ui2/src/main/webapp/app/styles/app.less     |   2 +
 .../main/webapp/app/styles/column-selector.less |  65 ++++++++++++
 tez-ui2/src/main/webapp/app/styles/shared.less  |   4 +-
 .../main/webapp/app/styles/table-controls.less  |  28 +++++
 .../src/main/webapp/app/templates/app/dags.hbs  |  16 +--
 .../main/webapp/app/templates/application.hbs   |   2 +
 .../templates/components/column-selector.hbs    |  48 +++++++++
 .../app/templates/components/table-controls.hbs |  19 ++++
 .../main/webapp/app/templates/dag/attempts.hbs  |   4 +-
 .../src/main/webapp/app/templates/dag/tasks.hbs |   4 +-
 .../main/webapp/app/templates/dag/vertices.hbs  |   4 +-
 tez-ui2/src/main/webapp/app/templates/dags.hbs  |   4 +-
 .../main/webapp/app/templates/simple-modal.hbs  |  33 ++++++
 .../main/webapp/app/templates/task/attempts.hbs |  16 +--
 .../webapp/app/templates/vertex/attempts.hbs    |  16 +--
 .../main/webapp/app/templates/vertex/tasks.hbs  |  16 +--
 tez-ui2/src/main/webapp/app/utils/misc.js       |  22 ++++
 tez-ui2/src/main/webapp/ember-cli-build.js      |   1 +
 .../components/column-selector-test.js          |  87 +++++++++++++++
 .../components/table-controls-test.js           |  43 ++++++++
 .../tests/unit/controllers/abstract-test.js     |   3 +-
 .../webapp/tests/unit/controllers/app-test.js   |   3 +-
 .../tests/unit/controllers/app/configs-test.js  |   3 +-
 .../tests/unit/controllers/app/dags-test.js     |   3 +-
 .../tests/unit/controllers/app/index-test.js    |   3 +-
 .../tests/unit/controllers/attempt-test.js      |   3 +-
 .../unit/controllers/attempt/counters-test.js   |   3 +-
 .../unit/controllers/attempt/index-test.js      |   3 +-
 .../unit/controllers/counters-page-test.js      |   4 +-
 .../webapp/tests/unit/controllers/dag-test.js   |   3 +-
 .../tests/unit/controllers/dag/attempts-test.js |   3 +-
 .../tests/unit/controllers/dag/counters-test.js |   3 +-
 .../tests/unit/controllers/dag/index-test.js    |   3 +-
 .../tests/unit/controllers/dag/tasks-test.js    |   3 +-
 .../tests/unit/controllers/dag/vertices-test.js |   3 +-
 .../webapp/tests/unit/controllers/dags-test.js  |   3 +
 .../webapp/tests/unit/controllers/page-test.js  |   6 +-
 .../tests/unit/controllers/table-page-test.js   |   3 +-
 .../webapp/tests/unit/controllers/task-test.js  |   3 +-
 .../unit/controllers/task/attempts-test.js      |   3 +-
 .../unit/controllers/task/counters-test.js      |   3 +-
 .../tests/unit/controllers/task/index-test.js   |   3 +-
 .../tests/unit/controllers/vertex-test.js       |   3 +-
 .../unit/controllers/vertex/attempts-test.js    |   3 +-
 .../unit/controllers/vertex/counters-test.js    |   3 +-
 .../tests/unit/controllers/vertex/index-test.js |   3 +-
 .../tests/unit/controllers/vertex/tasks-test.js |   5 +-
 .../main/webapp/tests/unit/utils/misc-test.js   |  26 +++++
 53 files changed, 706 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/TEZ-2980-CHANGES.txt
----------------------------------------------------------------------
diff --git a/TEZ-2980-CHANGES.txt b/TEZ-2980-CHANGES.txt
index c1fd7ae..f92341a 100644
--- a/TEZ-2980-CHANGES.txt
+++ b/TEZ-2980-CHANGES.txt
@@ -21,3 +21,4 @@ ALL CHANGES:
   TEZ-3048. Tez UI 2: Make PhantomJS a local dependency for build tests
   TEZ-3042. Tez UI 2: Create Counters pages
   TEZ-3043. Tez UI 2: Create configurations page
+  TEZ-3049. Tez UI 2: Add column selector

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/components/column-selector.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/column-selector.js b/tez-ui2/src/main/webapp/app/components/column-selector.js
new file mode 100644
index 0000000..9c9d4d2
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/components/column-selector.js
@@ -0,0 +1,105 @@
+/**
+ * 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 isIOCounter from '../utils/misc';
+
+export default Ember.Component.extend({
+
+  classNames: ['column-selector'],
+
+  searchText: "",
+  selectAll: false,
+
+  content: null,
+
+  options: Ember.computed("content.columns", "content.visibleColumnIDs", function () {
+    var group,
+        highlight = false,
+        visibleColumnIDs = this.get('content.visibleColumnIDs') || {};
+
+    return this.get('content.columns').map(function (config) {
+      var css = '';
+
+      highlight = highlight ^ (config.get("counterGroupName") !== group);
+      group = config.counterGroupName;
+
+      if(highlight) {
+        css += ' highlight';
+      }
+      if(group && isIOCounter(group)) {
+        css += ' per-io';
+      }
+
+      return Ember.Object.create({
+        id: config.get("id"),
+        displayText: config.get("headerTitle"),
+        css: css,
+        selected: visibleColumnIDs[config.id]
+      });
+    });
+  }),
+
+  filteredOptions: Ember.computed("options", "searchText", function () {
+    var options = this.get('options'),
+        searchText = this.get('searchText');
+
+    if (!searchText) {
+      return options;
+    }
+
+    return options.filter(function (option) {
+      return option.get('displayText').match(searchText);
+    });
+  }),
+
+  selectedColumnIDs: Ember.computed("options", function () {
+    var columnIds = {};
+
+    this.get('options').forEach(function (option) {
+      columnIds[option.get("id")] = option.get('selected');
+    });
+
+    return columnIds;
+  }),
+
+  _selectObserver: Ember.observer('filteredOptions.@each.selected', function () {
+    var selectedCount = 0;
+    this.get('filteredOptions').forEach(function (option) {
+      if(Ember.get(option, 'selected')) {
+        selectedCount++;
+      }
+    });
+    this.set('selectAll', selectedCount > 0 && selectedCount === this.get('filteredOptions.length'));
+  }),
+
+  actions: {
+    selectAll: function (checked) {
+      this.get('filteredOptions').forEach(function (option) {
+        Ember.set(option, 'selected', checked);
+      });
+    },
+    closeModal: function () {
+      this.get("targetObject").send("closeModal");
+    },
+    ok: function () {
+      this.get("targetObject").send("columnsSelected", this.get("selectedColumnIDs"));
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/components/table-controls.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/table-controls.js b/tez-ui2/src/main/webapp/app/components/table-controls.js
new file mode 100644
index 0000000..9923711
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/components/table-controls.js
@@ -0,0 +1,29 @@
+/**
+ * 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({
+  classNames: ['table-controls'],
+
+  actions: {
+    cogClicked: function () {
+      this.get('targetObject.targetObject').send('openColumnSelector');
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/controllers/table-page.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/table-page.js b/tez-ui2/src/main/webapp/app/controllers/table-page.js
index 1f2fe57..09ae8ab 100644
--- a/tez-ui2/src/main/webapp/app/controllers/table-page.js
+++ b/tez-ui2/src/main/webapp/app/controllers/table-page.js
@@ -1,3 +1,4 @@
+/*global more*/
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -20,6 +21,9 @@ import Ember from 'ember';
 
 import PageController from './page';
 import TableDefinition from 'em-table/utils/table-definition';
+import isIOCounter from '../utils/misc';
+
+var MoreObject = more.Object;
 
 export default PageController.extend({
   queryParams: ["rowCount", "searchText", "sortColumnId", "sortOrder", "pageNo"],
@@ -29,6 +33,12 @@ export default PageController.extend({
   sortOrder: "",
   pageNo: 1,
 
+  headerComponentNames: ['em-table-search-ui', 'table-controls', 'em-table-pagination-ui'],
+
+  visibleColumnIDs: {},
+  columnSelectorTitle: 'Column Selector',
+  columnSelectorMessage: "",
+
   definition: Ember.computed(function () {
     return TableDefinition.create({
       rowCount: this.get("rowCount"),
@@ -39,6 +49,29 @@ export default PageController.extend({
     });
   }),
 
+  storageID: Ember.computed("name", function () {
+    return this.get("name") + ":visibleColumnIDs";
+  }),
+
+  initVisibleColumns: Ember.on("init", Ember.observer("columns", function () { //To reset on entity change
+    var visibleColumnIDs = this.get("localStorage").get(this.get("storageID")) || {};
+
+    this.get('columns').forEach(function (config) {
+      if(visibleColumnIDs[config.id] !== false) {
+        visibleColumnIDs[config.id] = true;
+      }
+    });
+
+    this.set('visibleColumnIDs', visibleColumnIDs);
+  })),
+
+  visibleColumns: Ember.computed('visibleColumnIDs', 'columns', function() {
+    var visibleColumnIDs = this.visibleColumnIDs;
+    return this.get('columns').filter(function (column) {
+      return visibleColumnIDs[column.get("id")];
+    });
+  }),
+
   actions: {
     searchChanged: function (searchText) {
       this.set("searchText", searchText);
@@ -56,5 +89,32 @@ export default PageController.extend({
     pageChanged: function (pageNum) {
       this.set("pageNo", pageNum);
     },
+
+    // Column selection actions
+    openColumnSelector: function () {
+      this.send("openModal", "column-selector", {
+        title: this.get('columnSelectorTitle'),
+        targetObject: this,
+        content: {
+          message: this.get('columnSelectorMessage'),
+          columns: this.get('columns'),
+          visibleColumnIDs: this.get('visibleColumnIDs')
+        }
+      });
+    },
+    columnsSelected: function (visibleColumnIDs) {
+      var columnIDs = {};
+
+      MoreObject.forEach(visibleColumnIDs, function (key, value) {
+        if(!isIOCounter(key)) {
+          columnIDs[key] = value;
+        }
+      });
+
+      if(!MoreObject.equals(columnIDs, this.get("visibleColumnIDs"))) {
+        this.get("localStorage").set(this.get("storageID"), columnIDs);
+        this.set('visibleColumnIDs', columnIDs);
+      }
+    }
   }
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/routes/application.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/routes/application.js b/tez-ui2/src/main/webapp/app/routes/application.js
index 8da6a31..998cce4 100644
--- a/tez-ui2/src/main/webapp/app/routes/application.js
+++ b/tez-ui2/src/main/webapp/app/routes/application.js
@@ -35,6 +35,32 @@ export default Ember.Route.extend({
     },
     bubbleBreadcrumbs: function (breadcrumbs) {
       this.set("controller.breadcrumbs", breadcrumbs);
+    },
+
+    // Modal window actions
+    openModal: function (componentName, options) {
+      options = options || {};
+      this.render(options.modalName || "simple-modal", {
+        into: 'application',
+        outlet: 'modal',
+        model: {
+          title: options.title,
+          componentName: componentName,
+          content: options.content,
+          targetObject: options.targetObject
+        }
+      });
+      Ember.run.later(function () {
+        Ember.$(".simple-modal").modal();
+      });
+    },
+    destroyModal: function () {
+      Ember.run.later(this, function () {
+        this.disconnectOutlet({
+          outlet: 'modal',
+          parentView: 'application'
+        });
+      });
     }
   }
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/styles/app.less
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/styles/app.less b/tez-ui2/src/main/webapp/app/styles/app.less
index bdf9480..d697ba7 100644
--- a/tez-ui2/src/main/webapp/app/styles/app.less
+++ b/tez-ui2/src/main/webapp/app/styles/app.less
@@ -25,3 +25,5 @@
 
 @import "page-layout";
 @import "details-page";
+@import "table-controls";
+@import "column-selector";

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/styles/column-selector.less
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/styles/column-selector.less b/tez-ui2/src/main/webapp/app/styles/column-selector.less
new file mode 100644
index 0000000..2e39995
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/styles/column-selector.less
@@ -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.
+ */
+
+.column-selector {
+  .message {
+    text-align: right;
+    font-size: 10px;
+  }
+
+  .selection-list {
+    border-bottom: 1px solid @border-color;
+
+    .highlight {
+      background-color: @bg-lite;
+    }
+    .select-option, .search-option {
+      border-top: 1px dotted @border-color;
+      padding: 5px 15px;
+
+      .checkbox {
+        display: inline-block;
+
+        margin-right: 10px;
+        float: left;
+        vertical-align: middle;
+      }
+    }
+    .search-option {
+      border: none;
+
+      .form-group {
+        display: inline-block;
+
+        width: 100%;
+        margin: 0px;
+      }
+
+      .select-all {
+        display: inline-block;
+
+        height: 15px;
+        margin-top: 3px;
+      }
+    }
+  }
+}
+.form-actions {
+  padding: 10px;
+  text-align: right;
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/styles/shared.less
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/styles/shared.less b/tez-ui2/src/main/webapp/app/styles/shared.less
index db79db4..0dc70f7 100644
--- a/tez-ui2/src/main/webapp/app/styles/shared.less
+++ b/tez-ui2/src/main/webapp/app/styles/shared.less
@@ -27,8 +27,8 @@ b {
 
 .left-delim {
   border-left: 1px solid @border-color;
-  margin-left: 5px;
-  padding-left: 5px;
+  margin-left: 10px;
+  padding-left: 10px;
 }
 
 .align-checknradio {

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/styles/table-controls.less
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/styles/table-controls.less b/tez-ui2/src/main/webapp/app/styles/table-controls.less
new file mode 100644
index 0000000..aa9f9e6
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/styles/table-controls.less
@@ -0,0 +1,28 @@
+/**
+ * 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 "shared";
+
+.table-controls {
+  .left-delim;
+
+  cursor: pointer;
+
+  float: right;
+  font-size: 24px;
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/app/dags.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/app/dags.hbs b/tez-ui2/src/main/webapp/app/templates/app/dags.hbs
index cdb28aa..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/app/dags.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/app/dags.hbs
@@ -18,15 +18,17 @@
 
 {{#if loaded}}
   {{em-table
-  columns=columns
-  rows=model
+    columns=visibleColumns
+    rows=model
 
-  definition=definition
+    headerComponentNames=headerComponentNames
 
-  searchAction="searchChanged"
-  sortAction="sortChanged"
-  rowAction="rowsChanged"
-  pageAction="pageChanged"
+    definition=definition
+
+    searchAction="searchChanged"
+    sortAction="sortChanged"
+    rowAction="rowsChanged"
+    pageAction="pageChanged"
   }}
 {{else}}
   {{partial "partials/loading-anim"}}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/application.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/application.hbs b/tez-ui2/src/main/webapp/app/templates/application.hbs
index 5d1df11..16a0329 100644
--- a/tez-ui2/src/main/webapp/app/templates/application.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/application.hbs
@@ -62,3 +62,5 @@
     </div>
   </div>
 </div>
+
+{{outlet "modal"}}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/components/column-selector.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/column-selector.hbs b/tez-ui2/src/main/webapp/app/templates/components/column-selector.hbs
new file mode 100644
index 0000000..d9be633
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/templates/components/column-selector.hbs
@@ -0,0 +1,48 @@
+{{!
+ * 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 class="message">
+  {{{content.message}}}
+</div>
+<div class="selection-list">
+  <div class="search-option highlight">
+    <div class="form-group">
+      {{input class="form-control" placeholder="Filter..." value=searchText}}
+    </div>
+    <div class="select-all">
+      <input type="checkbox"
+             checked={{selectAll}}
+             onclick={{action "selectAll" value="target.checked"}} />
+      &nbsp;Select All
+    </div>
+  </div>
+  {{#if filteredOptions.length}}
+    {{#each filteredOptions as |option|}}
+      <div class="select-option {{option.css}}">
+        {{input type="checkbox" classNames='checkbox' checked=option.selected}}
+        {{option.displayText}}
+      </div>
+    {{/each}}
+  {{else}}
+    <h4>&nbsp;No options available...</h4>
+  {{/if}}
+</div>
+<div class="form-actions">
+  <button type="button" class="btn btn-primary" {{action "ok"}} data-dismiss="modal" aria-label="Close">Ok</button>
+  <button type="button" class="btn" data-dismiss="modal" aria-label="Close">Cancel</button>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/components/table-controls.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/components/table-controls.hbs b/tez-ui2/src/main/webapp/app/templates/components/table-controls.hbs
new file mode 100644
index 0000000..b70d19d
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/templates/components/table-controls.hbs
@@ -0,0 +1,19 @@
+{{!
+ * 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.
+}}
+
+<i class='fa fa-cog' {{action 'cogClicked'}}></i>

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/dag/attempts.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dag/attempts.hbs b/tez-ui2/src/main/webapp/app/templates/dag/attempts.hbs
index 932db09..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/dag/attempts.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dag/attempts.hbs
@@ -18,9 +18,11 @@
 
 {{#if loaded}}
   {{em-table
-    columns=columns
+    columns=visibleColumns
     rows=model
 
+    headerComponentNames=headerComponentNames
+
     definition=definition
 
     searchAction="searchChanged"

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/dag/tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dag/tasks.hbs b/tez-ui2/src/main/webapp/app/templates/dag/tasks.hbs
index 932db09..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/dag/tasks.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dag/tasks.hbs
@@ -18,9 +18,11 @@
 
 {{#if loaded}}
   {{em-table
-    columns=columns
+    columns=visibleColumns
     rows=model
 
+    headerComponentNames=headerComponentNames
+
     definition=definition
 
     searchAction="searchChanged"

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/dag/vertices.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dag/vertices.hbs b/tez-ui2/src/main/webapp/app/templates/dag/vertices.hbs
index 932db09..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/dag/vertices.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dag/vertices.hbs
@@ -18,9 +18,11 @@
 
 {{#if loaded}}
   {{em-table
-    columns=columns
+    columns=visibleColumns
     rows=model
 
+    headerComponentNames=headerComponentNames
+
     definition=definition
 
     searchAction="searchChanged"

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/dags.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/dags.hbs b/tez-ui2/src/main/webapp/app/templates/dags.hbs
index ddbc72a..1fd0eef 100644
--- a/tez-ui2/src/main/webapp/app/templates/dags.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/dags.hbs
@@ -18,10 +18,12 @@
 
 {{#if loaded}}
   {{em-table
-    columns=columns
+    columns=visibleColumns
     rows=model
     rowCount=rowCount
 
+    headerComponentNames=headerComponentNames
+
     enableSearch=false
     enableSort=false
 

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/simple-modal.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/simple-modal.hbs b/tez-ui2/src/main/webapp/app/templates/simple-modal.hbs
new file mode 100644
index 0000000..59b3aaa
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/templates/simple-modal.hbs
@@ -0,0 +1,33 @@
+{{!
+ * 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 class="modal fade simple-modal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span>
+        </button>
+        <h4 class="modal-title">{{model.title}}</h4>
+      </div>
+      {{#if model.componentName}}
+        {{component model.componentName content=model.content targetObject=model.targetObject}}
+      {{/if}}
+    </div>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/task/attempts.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/task/attempts.hbs b/tez-ui2/src/main/webapp/app/templates/task/attempts.hbs
index cdb28aa..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/task/attempts.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/task/attempts.hbs
@@ -18,15 +18,17 @@
 
 {{#if loaded}}
   {{em-table
-  columns=columns
-  rows=model
+    columns=visibleColumns
+    rows=model
 
-  definition=definition
+    headerComponentNames=headerComponentNames
 
-  searchAction="searchChanged"
-  sortAction="sortChanged"
-  rowAction="rowsChanged"
-  pageAction="pageChanged"
+    definition=definition
+
+    searchAction="searchChanged"
+    sortAction="sortChanged"
+    rowAction="rowsChanged"
+    pageAction="pageChanged"
   }}
 {{else}}
   {{partial "partials/loading-anim"}}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/vertex/attempts.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/vertex/attempts.hbs b/tez-ui2/src/main/webapp/app/templates/vertex/attempts.hbs
index cdb28aa..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/vertex/attempts.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/vertex/attempts.hbs
@@ -18,15 +18,17 @@
 
 {{#if loaded}}
   {{em-table
-  columns=columns
-  rows=model
+    columns=visibleColumns
+    rows=model
 
-  definition=definition
+    headerComponentNames=headerComponentNames
 
-  searchAction="searchChanged"
-  sortAction="sortChanged"
-  rowAction="rowsChanged"
-  pageAction="pageChanged"
+    definition=definition
+
+    searchAction="searchChanged"
+    sortAction="sortChanged"
+    rowAction="rowsChanged"
+    pageAction="pageChanged"
   }}
 {{else}}
   {{partial "partials/loading-anim"}}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/templates/vertex/tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/templates/vertex/tasks.hbs b/tez-ui2/src/main/webapp/app/templates/vertex/tasks.hbs
index cdb28aa..6d8d4c3 100644
--- a/tez-ui2/src/main/webapp/app/templates/vertex/tasks.hbs
+++ b/tez-ui2/src/main/webapp/app/templates/vertex/tasks.hbs
@@ -18,15 +18,17 @@
 
 {{#if loaded}}
   {{em-table
-  columns=columns
-  rows=model
+    columns=visibleColumns
+    rows=model
 
-  definition=definition
+    headerComponentNames=headerComponentNames
 
-  searchAction="searchChanged"
-  sortAction="sortChanged"
-  rowAction="rowsChanged"
-  pageAction="pageChanged"
+    definition=definition
+
+    searchAction="searchChanged"
+    sortAction="sortChanged"
+    rowAction="rowsChanged"
+    pageAction="pageChanged"
   }}
 {{else}}
   {{partial "partials/loading-anim"}}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/app/utils/misc.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/utils/misc.js b/tez-ui2/src/main/webapp/app/utils/misc.js
new file mode 100644
index 0000000..5e2ecf1
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/utils/misc.js
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+
+export default function isIOCounter(name) {
+  name = name.split('/')[0];
+  return name.match('_INPUT_') || name.match('_OUTPUT_');
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/ember-cli-build.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/ember-cli-build.js b/tez-ui2/src/main/webapp/ember-cli-build.js
index ac5eea9..dee919b 100644
--- a/tez-ui2/src/main/webapp/ember-cli-build.js
+++ b/tez-ui2/src/main/webapp/ember-cli-build.js
@@ -33,6 +33,7 @@ module.exports = function(defaults) {
      destDir: '/config'
   });
 
+  app.import('bower_components/bootstrap/dist/js/bootstrap.js');
   app.import('bower_components/jquery-ui/jquery-ui.js');
   app.import('bower_components/jquery-ui/ui/tooltip.js');
 

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/integration/components/column-selector-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/column-selector-test.js b/tez-ui2/src/main/webapp/tests/integration/components/column-selector-test.js
new file mode 100644
index 0000000..0034059
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/integration/components/column-selector-test.js
@@ -0,0 +1,87 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('column-selector', 'Integration | Component | column selector', {
+  integration: true
+});
+
+test('Basic creation test', function(assert) {
+
+  this.set("content", {
+    columns: [Ember.Object.create({
+      headerTitle: "Test Column"
+    })]
+  });
+  this.render(hbs`{{column-selector content=content}}`);
+
+  assert.equal(this.$(".select-option ").text().trim(), 'Test Column');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#column-selector content=content}}
+      template block text
+    {{/column-selector}}
+  `);
+
+  assert.equal(this.$(".select-option ").text().trim(), 'Test Column');
+});
+
+test('visibleColumnIDs test', function(assert) {
+
+  this.setProperties({
+    content: {
+      visibleColumnIDs: {
+        testID: true,
+      },
+      columns: [Ember.Object.create({
+        id: "testID",
+        headerTitle: "Test Column"
+      })]
+    }
+  });
+
+  this.render(hbs`{{column-selector content=content}}`);
+
+  assert.equal(this.$(".select-option").text().trim(), 'Test Column');
+  assert.equal(this.$(".select-option input")[0].checked, true);
+});
+
+test('searchText test', function(assert) {
+
+  this.setProperties({
+    searchText: "nothing",
+    content: {
+      visibleColumnIDs: {
+        testID: true,
+      },
+      columns: [Ember.Object.create({
+        id: "testID",
+        headerTitle: "Test Column"
+      })]
+    }
+  });
+
+  this.render(hbs`{{column-selector content=content searchText=searchText}}`);
+
+  assert.equal(this.$(".select-option").text().trim(), '');
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/integration/components/table-controls-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/integration/components/table-controls-test.js b/tez-ui2/src/main/webapp/tests/integration/components/table-controls-test.js
new file mode 100644
index 0000000..79170ee
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/integration/components/table-controls-test.js
@@ -0,0 +1,43 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('table-controls', 'Integration | Component | table controls', {
+  integration: true
+});
+
+test('Basic creation test', function(assert) {
+
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{table-controls}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#table-controls}}
+      template block text
+    {{/table-controls}}
+  `);
+
+  assert.equal(this.$().text().trim(), '');
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/abstract-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/abstract-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/abstract-test.js
index 640e1e5..9cde1e7 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/abstract-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/abstract-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:abstract', 'Unit | Controller | abstract', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller.name);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/app-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/app-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/app-test.js
index 304321e..2fc7276 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/app-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/app-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag', 'Unit | Controller | dag', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/app/configs-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/app/configs-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/app/configs-test.js
index c04e5c2..4661e8c 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/app/configs-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/app/configs-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:app/configs', 'Unit | Controller | app/configs', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/app/dags-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/app/dags-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/app/dags-test.js
index c3e5c2b..c60fbb5 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/app/dags-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/app/dags-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:app/dags', 'Unit | Controller | app/dags', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/app/index-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/app/index-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/app/index-test.js
index 641a415..9bd6604 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/app/index-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/app/index-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:app/index', 'Unit | Controller | app/index', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/attempt-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt-test.js
index 9408204..da451f7 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:attempt', 'Unit | Controller | attempt', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/counters-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/counters-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/counters-test.js
index 9b94804..8226f36 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/counters-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/counters-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:attempt/counters', 'Unit | Controller | attempt/counters',
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/index-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/index-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/index-test.js
index 00e2c9e..3733692 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/index-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/attempt/index-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:attempt/index', 'Unit | Controller | attempt/index', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/counters-page-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/counters-page-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/counters-page-test.js
index 44a888e..6faad2d 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/counters-page-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/counters-page-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:counters-page', 'Unit | Controller | counters page', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);
@@ -38,6 +39,7 @@ test('Basic creation test', function(assert) {
 test('counters test', function(assert) {
   let controller = this.subject({
     send: Ember.K,
+    initVisibleColumns: Ember.K,
     model: {
       counterGroups: [{
         counterGroupName: "a.b.foo",

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag-test.js
index 304321e..2fc7276 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag', 'Unit | Controller | dag', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag/attempts-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/attempts-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/attempts-test.js
index 11bb0fa..3fa8ff7 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/attempts-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/attempts-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag/attempts', 'Unit | Controller | dag/attempts', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag/counters-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/counters-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/counters-test.js
index a90df3c..7e72b95 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/counters-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/counters-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag/counters', 'Unit | Controller | dag/counters', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag/index-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/index-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/index-test.js
index 0b64e86..176b9e7 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/index-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/index-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag/index', 'Unit | Controller | dag/index', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag/tasks-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/tasks-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/tasks-test.js
index 073e3d3..eace870 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/tasks-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/tasks-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag/tasks', 'Unit | Controller | dag/tasks', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dag/vertices-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/vertices-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/vertices-test.js
index fc75935..f54b1a8 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dag/vertices-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dag/vertices-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:dag/vertices', 'Unit | Controller | dag/vertices', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/dags-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/dags-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/dags-test.js
index ddf6c44..944f813 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/dags-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/dags-test.js
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+import Ember from 'ember';
+
 import { moduleFor, test } from 'ember-qunit';
 
 moduleFor('controller:dags', 'Unit | Controller | dags', {
@@ -27,6 +29,7 @@ test('Basic creation test', function(assert) {
   assert.expect(2 + 2);
 
   let controller = this.subject({
+    initVisibleColumns: Ember.K,
     send: function (name, query) {
       assert.equal(name, "setBreadcrumbs");
       assert.ok(query);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/page-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/page-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/page-test.js
index ffbdd60..75a8a54 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/page-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/page-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:page', 'Unit | Controller | page', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);
@@ -38,7 +39,8 @@ test('Basic creation test', function(assert) {
 
 test('loaded test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.notOk(controller.get("loaded"));

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/table-page-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/table-page-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/table-page-test.js
index 4c41a20..8aee8d7 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/table-page-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/table-page-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:table-page', 'Unit | Controller | table page', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/task-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/task-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/task-test.js
index 0a5bed1..c9cee79 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/task-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/task-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:task', 'Unit | Controller | task', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/task/attempts-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/task/attempts-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/task/attempts-test.js
index fb9439f..43badfc 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/task/attempts-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/task/attempts-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:task/attempts', 'Unit | Controller | task/attempts', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/task/counters-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/task/counters-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/task/counters-test.js
index fb453f7..6ee8adb 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/task/counters-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/task/counters-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:task/counters', 'Unit | Controller | task/counters', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/task/index-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/task/index-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/task/index-test.js
index a229ee9..86d63e9 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/task/index-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/task/index-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:task/index', 'Unit | Controller | task/index', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/vertex-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex-test.js
index 0061f74..e8e9b3f 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:vertex', 'Unit | Controller | vertex', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/attempts-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/attempts-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/attempts-test.js
index 933096e..de89864 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/attempts-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/attempts-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:vertex/attempts', 'Unit | Controller | vertex/attempts', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/counters-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/counters-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/counters-test.js
index cc73e6c..0a17240 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/counters-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/counters-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:vertex/counters', 'Unit | Controller | vertex/counters', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/index-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/index-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/index-test.js
index e9b46b5..bcf6203 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/index-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/index-test.js
@@ -27,7 +27,8 @@ moduleFor('controller:vertex/index', 'Unit | Controller | vertex/index', {
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/tasks-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/tasks-test.js b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/tasks-test.js
index a449dc2..23393ef 100644
--- a/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/tasks-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/controllers/vertex/tasks-test.js
@@ -22,12 +22,13 @@ import { moduleFor, test } from 'ember-qunit';
 
 moduleFor('controller:vertex/tasks', 'Unit | Controller | vertex/tasks', {
   // Specify the other units that are required for this test.
-  // needs: ['controller:foo']
+  // needs: ['service:local-storage']
 });
 
 test('Basic creation test', function(assert) {
   let controller = this.subject({
-    send: Ember.K
+    send: Ember.K,
+    initVisibleColumns: Ember.K
   });
 
   assert.ok(controller);

http://git-wip-us.apache.org/repos/asf/tez/blob/5c726547/tez-ui2/src/main/webapp/tests/unit/utils/misc-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/utils/misc-test.js b/tez-ui2/src/main/webapp/tests/unit/utils/misc-test.js
new file mode 100644
index 0000000..7e282cd
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/unit/utils/misc-test.js
@@ -0,0 +1,26 @@
+/**
+ * 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 isIOCounter from '../../../utils/misc';
+import { module, test } from 'qunit';
+
+module('Unit | Utility | misc');
+
+test('Basic creation test', function(assert) {
+  assert.ok(isIOCounter);
+});