Repository: atlas Updated Branches: refs/heads/0.8-incubating 0e8d7d508 -> b8255d418
ATLAS-1993: UI updates to show list of Tables in detail page hive_db entity Signed-off-by: Madhan Neethiraj <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/b8255d41 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/b8255d41 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/b8255d41 Branch: refs/heads/0.8-incubating Commit: b8255d418e67a6bb01b9c3c4d2bce1cc2f24df4f Parents: 0e8d7d5 Author: kevalbhatt <[email protected]> Authored: Thu Aug 17 16:19:04 2017 +0530 Committer: Madhan Neethiraj <[email protected]> Committed: Thu Aug 17 12:47:30 2017 -0700 ---------------------------------------------------------------------- dashboardv2/gruntfile.js | 12 +- dashboardv2/package.json | 2 + dashboardv2/public/css/scss/profile-table.scss | 72 ++++ dashboardv2/public/css/scss/style.scss | 1 + dashboardv2/public/index.html | 1 + .../public/js/collection/VProfileList.js | 49 +++ dashboardv2/public/js/main.js | 17 +- dashboardv2/public/js/models/VProfile.js | 43 +++ .../detail_page/DetailPageLayoutView_tmpl.html | 8 + .../profile/ProfileColumnLayoutView_tmpl.html | 90 +++++ .../profile/ProfileLayoutView_tmpl.html | 24 ++ .../profile/ProfileTableLayoutView_tmpl.html | 40 +++ .../public/js/utils/CommonViewFunction.js | 3 + dashboardv2/public/js/utils/Enums.js | 8 +- dashboardv2/public/js/utils/Utils.js | 90 ++++- .../views/detail_page/DetailPageLayoutView.js | 29 +- .../js/views/profile/ProfileColumnLayoutView.js | 206 ++++++++++++ .../js/views/profile/ProfileLayoutView.js | 109 ++++++ .../js/views/profile/ProfileTableLayoutView.js | 332 +++++++++++++++++++ .../public/js/views/schema/SchemaLayoutView.js | 31 +- .../js/views/search/SearchResultLayoutView.js | 246 ++++++++------ 21 files changed, 1268 insertions(+), 145 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/gruntfile.js ---------------------------------------------------------------------- diff --git a/dashboardv2/gruntfile.js b/dashboardv2/gruntfile.js index 1ca5069..12af6fd 100644 --- a/dashboardv2/gruntfile.js +++ b/dashboardv2/gruntfile.js @@ -130,7 +130,9 @@ module.exports = function(grunt) { 'jquery-placeholder/js': 'jquery-placeholder/jquery.placeholder.js', 'platform': 'platform/platform.js', 'jQueryQueryBuilder/js': 'jQuery-QueryBuilder/dist/js/query-builder.standalone.min.js', - 'bootstrap-daterangepicker/js': 'bootstrap-daterangepicker/daterangepicker.js' + 'bootstrap-daterangepicker/js': 'bootstrap-daterangepicker/daterangepicker.js', + 'nvd3': 'nvd3/build/nv.d3.min.js', + 'sparkline': 'jquery-sparkline/jquery.sparkline.min.js' } }, css: { @@ -152,7 +154,8 @@ module.exports = function(grunt) { 'font-awesome/css': 'font-awesome/css/font-awesome.min.css', 'font-awesome/fonts': 'font-awesome/fonts', 'jQueryQueryBuilder/css': 'jQuery-QueryBuilder/dist/css/query-builder.default.min.css', - 'bootstrap-daterangepicker/css': 'bootstrap-daterangepicker/daterangepicker.css' + 'bootstrap-daterangepicker/css': 'bootstrap-daterangepicker/daterangepicker.css', + 'nvd3/css': 'nvd3/build/nv.d3.min.css' } }, @@ -182,7 +185,8 @@ module.exports = function(grunt) { 'backgrid-select-all': 'backgrid-select-all/LICENSE-MIT', 'jquery-placeholder': 'jquery-placeholder/LICENSE.txt', 'platform/': 'platform/LICENSE', - 'jQueryQueryBuilder/': 'jQuery-QueryBuilder/LICENSE' + 'jQueryQueryBuilder/': 'jQuery-QueryBuilder/LICENSE', + 'nvd3/': 'nvd3/LICENSE.md' } } }, @@ -320,4 +324,4 @@ module.exports = function(grunt) { 'cssmin:build', 'htmlmin:build' ]); -}; +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/package.json ---------------------------------------------------------------------- diff --git a/dashboardv2/package.json b/dashboardv2/package.json index bcf5fe7..6068c79 100644 --- a/dashboardv2/package.json +++ b/dashboardv2/package.json @@ -37,7 +37,9 @@ "jquery": "2.2.4", "jquery-asBreadcrumbs": "0.2.2", "jquery-placeholder": "2.3.1", + "jquery-sparkline": "2.4.0", "moment": "2.18.1", + "nvd3": "1.8.5", "platform": "1.3.4", "pnotify": "3.2.0", "requirejs": "2.3.3", http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/css/scss/profile-table.scss ---------------------------------------------------------------------- diff --git a/dashboardv2/public/css/scss/profile-table.scss b/dashboardv2/public/css/scss/profile-table.scss new file mode 100644 index 0000000..2b0b483 --- /dev/null +++ b/dashboardv2/public/css/scss/profile-table.scss @@ -0,0 +1,72 @@ +/* + * 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. + */ + + +/* Profile Tab css */ + +.graphkey { + font-size: 12px; + color: $action_gray; +} + +.graphval { + font-size: 15px; + .value-loader { + top: 10px; + } +} + +.nv-axislabel { + fill: $action_gray; +} + +.profileGraphDetail hr { + margin: 3px; +} + +svg.dateType .nv-bar { + cursor: pointer; +} + +.jqstooltip { + height: auto !important; + width: auto !important; +} + +.progress.cstm_progress { + margin-bottom: 0px; + .progress-bar-success.cstm_success-bar { + background-color: $color_jungle_green_approx; + } + .progress-bar-success.cstm_success-bar:hover { + background-color: $color_puerto_rico_approx; + } +} + +th.renderable.nonNullData { + a { + text-align: center; + } +} + +.profileGraphDetail>div div { + text-align: right; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/css/scss/style.scss ---------------------------------------------------------------------- diff --git a/dashboardv2/public/css/scss/style.scss b/dashboardv2/public/css/scss/style.scss index c7085cc..f634c44 100644 --- a/dashboardv2/public/css/scss/style.scss +++ b/dashboardv2/public/css/scss/style.scss @@ -31,4 +31,5 @@ @import "tree.scss"; @import "tag.scss"; @import "search.scss"; +@import "profile-table.scss"; @import "override.scss"; http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/index.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/index.html b/dashboardv2/public/index.html index 2b0b5d7..f572049 100644 --- a/dashboardv2/public/index.html +++ b/dashboardv2/public/index.html @@ -53,6 +53,7 @@ <link href="js/external_lib/pnotify/pnotify.custom.min.css" rel="stylesheet"> <link href="js/libs/jQueryQueryBuilder/css/query-builder.default.min.css" rel="stylesheet"> <link href="js/libs/bootstrap-daterangepicker/css/daterangepicker.css" rel="stylesheet"> + <link rel="stylesheet" href="js/libs/nvd3/css/nv.d3.min.css"> <link href="css/style.css" rel="stylesheet"> </head> http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/collection/VProfileList.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/collection/VProfileList.js b/dashboardv2/public/js/collection/VProfileList.js new file mode 100644 index 0000000..c5edcc1 --- /dev/null +++ b/dashboardv2/public/js/collection/VProfileList.js @@ -0,0 +1,49 @@ +/** + * 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', + 'utils/Globals', + 'collection/BaseCollection', + 'models/VProfile' +], function(require, Globals, BaseCollection, VProfile) { + 'use strict'; + var VProfileList = BaseCollection.extend( + //Prototypal attributes + { + url: Globals.baseURL + '/api/atlas/entities', + + model: VProfile, + + initialize: function() { + this.modelName = 'VProfile'; + this.modelAttrName = 'definition'; + this.bindErrorEvents(); + } + }, + //Static Class Members + { + /** + * Table Cols to be passed to Backgrid + * UI has to use this as base and extend this. + * + */ + tableCols: {} + } + ); + return VProfileList; +}); http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/main.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js index b04141f..63e9abc 100644 --- a/dashboardv2/public/js/main.js +++ b/dashboardv2/public/js/main.js @@ -22,8 +22,8 @@ require.config({ 'disableI18n': true, // This disables the i18n helper and doesn't require the json i18n files (e.g. en_us.json) 'helperPathCallback': // Callback to determine the path to look for helpers function(name) { // ('/template/helpers/'+name by default) - return 'modules/Helpers'; - }, + return 'modules/Helpers'; + }, 'templateExtension': 'html', // Set the extension automatically appended to templates 'compileOptions': {} // options object which is passed to Handlebars compiler }, @@ -112,6 +112,13 @@ require.config({ }, 'daterangepicker': { 'deps': ['jquery', 'moment'] + }, + 'nvd3': { + 'deps': ['d3'] + }, + 'sparkline': { + 'deps': ['jquery'], + 'exports': ['sparkline'] } }, @@ -149,7 +156,9 @@ require.config({ 'jquery-placeholder': 'libs/jquery-placeholder/js/jquery.placeholder', 'platform': 'libs/platform/platform', 'query-builder': 'libs/jQueryQueryBuilder/js/query-builder.standalone.min', - 'daterangepicker': 'libs/bootstrap-daterangepicker/js/daterangepicker' + 'daterangepicker': 'libs/bootstrap-daterangepicker/js/daterangepicker', + 'nvd3': 'libs/nvd3/nv.d3.min', + 'sparkline': 'libs/sparkline/jquery.sparkline.min' }, /** @@ -254,4 +263,4 @@ require(['App', startApp(); } }); -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/models/VProfile.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/models/VProfile.js b/dashboardv2/public/js/models/VProfile.js new file mode 100644 index 0000000..2eace1d --- /dev/null +++ b/dashboardv2/public/js/models/VProfile.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. + */ + +define(['require', + 'utils/Globals', + 'models/BaseModel' +], function(require, Globals, VBaseModel) { + 'use strict'; + var VProfile = VBaseModel.extend({ + + urlRoot: Globals.baseURL, + + defaults: {}, + + serverSchema: {}, + + idAttribute: 'id', + + initialize: function() { + this.modelName = 'VLineage'; + this.bindErrorEvents(); + }, + toString: function() { + return this.get('id'); + }, + }, {}); + return VProfile; +}); http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html index 983b0f8..18da242 100644 --- a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html @@ -89,6 +89,7 @@ {{/if}} <li role="audits" class="tab"><a href="#tab-audit" aria-controls="tab-audit" role="tab" data-toggle="tab">Audits</a></li> <li role="schema" class="tab schemaTable" style="display:none"><a href="#tab-schema" aria-controls="tab-schema" role="tab" data-toggle="tab">Schema</a></li> + <li role="profile" class="tab profileTab" style="display:none"><a href="#tab-profile" aria-controls="tab-profile" role="tab" data-toggle="tab">Profile</a></li> </ul> </div> </div> @@ -128,6 +129,13 @@ </div> </div> </div> + <div id="tab-profile" role="profile" class="tab-pane"> + <div id="r_profileLayoutView" style="position: relative;"> + <div class="fontLoader"> + <i class="fa fa-refresh fa-spin-custom"></i> + </div> + </div> + </div> </div> </div> </div> http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html new file mode 100644 index 0000000..5215254 --- /dev/null +++ b/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html @@ -0,0 +1,90 @@ +<!-- + * 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="row"> + <div class=""> + <div class="col-md-3 rowValue"> + <div><span class="graphkey">Rows</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + <div class="col-md-3 table_created"> + <div><span class="graphkey">Date Created</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + <div class="col-md-6 table_name"> + <div><span class="graphkey">Table</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + </div> +</div> +<hr/> +<div class="row"> + <h4 class="col-md-12">{{typeObject.label}}</h4> +</div> +<div class="row"> + <a href="javascript:void(0);" class="backButton" data-id="backToYear" style="display: none"><i class="fa fa-chevron-left"></i> Back To Year</a> +</div> +</br> +<div class="row"> + <div class=""> + <div class="col-md-10"> + <svg class="graph" width="100%" height="250px"></svg> + </div> + <div class="col-md-2 profileGraphDetail"> + {{#if profileData}} + <div class=""> + <div><span class="graphkey">Cardinality</span></div> + <div title="{{profileData.cardinality}}"><span class="graphval text-right"><b>{{profileData.cardinality}}</b></span></div> + </div> + <hr/> + <div class=""> + <div><span class="graphkey">% NonNull</span></div> + <div title="{{profileData.nonNullData}}%"><span class="graphval text-right"><b>{{profileData.nonNullData}}%</b></span></div> + </div> + <hr/> {{#ifCond typeObject.type "==" "string"}} + <div class=""> + <div><span class="graphkey">Average Length</span></div> + <div title="{{profileData.averageLength}}"><span class="graphval text-right"><b>{{profileData.averageLength}}</b></span></div> + </div> + <hr/> + <div class=""> + <div><span class="graphkey">Max Length</span></div> + <div title="{{profileData.maxLength}}"><span class="graphval text-right"><b>{{profileData.maxLength}}</b></span></div> + </div> + <hr/> {{/ifCond}} {{#ifCond typeObject.type "==" "numeric"}} + <div class=""> + <div><span class="graphkey">Min</span></div> + <div title="{{profileData.minValue}}"><span class="graphval text-right"><b>{{profileData.minValue}}</b></span></div> + </div> + <hr/> + <div class=""> + <div><span class="graphkey">Max</span></div> + <div title="{{profileData.maxValue}}"><span class="graphval text-right"><b>{{profileData.maxValue}}</b></span></div> + </div> + <hr/> + <div class=""> + <div><span class="graphkey">Mean</span></div> + <div title="{{profileData.meanValue}}"><span class="graphval text-right"><b>{{profileData.meanValue}}</b></span></div> + </div> + <hr/> + <div class=""> + <div><span class="graphkey">Median</span></div> + <div title="{{profileData.medianValue}}"><span class="graphval text-right"><b>{{profileData.medianValue}}</b></span></div> + </div> + {{/ifCond}} {{/if}} + </div> + </div> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html new file mode 100644 index 0000000..b1fba11 --- /dev/null +++ b/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html @@ -0,0 +1,24 @@ +<!-- + * 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="r_profileTableOrColumnLayoutView"> + {{#if profileData}} + <div class="fontLoader" style="display: block;"> + <i class="fa fa-refresh fa-spin-custom"></i> + </div> {{else}} {{#ifCond typeName "==" "hive_db"}} + <h3>No Tables to Show!</h3> {{else}} + <h3>No Profile to Show!</h3> {{/ifCond}} {{/if}} +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html new file mode 100644 index 0000000..d0ae3e0 --- /dev/null +++ b/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html @@ -0,0 +1,40 @@ +<!-- + * 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="row"> + <div class=""> + <div class="col-md-3 rowValue"> + <div><span class="graphkey">Rows</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + <div class="col-md-3 table_created"> + <div><span class="graphkey">Date Created</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + <div class="col-md-3 table_name"> + <div><span class="graphkey">Table</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + <div class="col-md-3 db_name"> + <div><span class="graphkey">DB</span></div> + <div><span class="graphval"><div class="value-loader"></div></span></div> + </div> + </div> +</div> +<hr/> +<div class=""> + <div id="r_profileTableLayoutView"></div> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/utils/CommonViewFunction.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js index 710c5af..177e052 100644 --- a/dashboardv2/public/js/utils/CommonViewFunction.js +++ b/dashboardv2/public/js/utils/CommonViewFunction.js @@ -199,6 +199,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum } _.sortBy(_.keys(valueObject)).map(function(key) { key = _.escape(key); + if (key == "profileData") { + return; + } var keyValue = valueObject[key]; var defEntity = _.find(attributeDefs, { name: key }); if (defEntity && defEntity.typeName) { http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/utils/Enums.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/Enums.js b/dashboardv2/public/js/utils/Enums.js index 90510bc..db2c46c 100644 --- a/dashboardv2/public/js/utils/Enums.js +++ b/dashboardv2/public/js/utils/Enums.js @@ -51,5 +51,11 @@ define(['require'], function(require) { FULLTEXT: 'basic' } + Enums.profileTabType = { + 'count-frequency': "Count Frequency Distribution", + 'decile-frequency': "Decile Frequency Distribution", + 'annual': "Annual Distribution" + } + return Enums; -}); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/utils/Utils.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js index 9ddd5f4..6d378bc 100644 --- a/dashboardv2/public/js/utils/Utils.js +++ b/dashboardv2/public/js/utils/Utils.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages) { +define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums) { 'use strict'; var Utils = {}; @@ -507,6 +507,94 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'pnotify.button getData(data, collection); return attributeDefs } + + Utils.getProfileTabType = function(profileData, skipData) { + var parseData = profileData.distributionData; + if (_.isString(parseData)) { + parseData = JSON.parse(parseData); + } + var createData = function(type) { + var orderValue = [], + sort = false; + if (type === "date") { + var dateObj = {}; + _.keys(parseData).map(function(key) { + var splitValue = key.split(":"); + if (!dateObj[splitValue[0]]) { + dateObj[splitValue[0]] = { + value: splitValue[0], + monthlyCounts: {}, + totalCount: 0 // use when count is null + } + } + if (dateObj[splitValue[0]] && splitValue[1] == "count") { + dateObj[splitValue[0]].count = parseData[key]; + } + if (dateObj[splitValue[0]] && splitValue[1] !== "count") { + dateObj[splitValue[0]].monthlyCounts[splitValue[1]] = parseData[key]; + if (!dateObj[splitValue[0]].count) { + dateObj[splitValue[0]].totalCount += parseData[key] + } + } + }); + return _.toArray(dateObj).map(function(obj) { + if (!obj.count && obj.totalCount) { + obj.count = obj.totalCount + } + return obj + }); + } else { + var data = []; + if (profileData.distributionKeyOrder) { + orderValue = profileData.distributionKeyOrder; + } else { + sort = true; + orderValue = _.keys(parseData); + } + _.each(orderValue, function(key) { + if (parseData[key]) { + data.push({ + value: key, + count: parseData[key] + }); + } + }); + if (sort) { + data = _.sortBy(data, function(o) { + return o.value.toLowerCase() + }); + } + return data; + } + } + if (profileData && profileData.distributionType) { + if (profileData.distributionType === "count-frequency") { + return { + type: "string", + label: Enums.profileTabType[profileData.distributionType], + actualObj: !skipData ? createData("string") : null, + xAxisLabel: "FREQUENCY", + yAxisLabel: "COUNT" + } + } else if (profileData.distributionType === "decile-frequency") { + return { + label: Enums.profileTabType[profileData.distributionType], + type: "numeric", + xAxisLabel: "DECILE RANGE", + actualObj: !skipData ? createData("numeric") : null, + yAxisLabel: "FREQUENCY" + } + } else if (profileData.distributionType === "annual") { + return { + label: Enums.profileTabType[profileData.distributionType], + type: "date", + xAxisLabel: "", + actualObj: !skipData ? createData("date") : null, + yAxisLabel: "COUNT" + } + } + } + } $.fn.toggleAttribute = function(attributeName, firstString, secondString) { if (this.attr(attributeName) == firstString) { this.attr(attributeName, secondString); http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js index 9a27ee1..5f172e9 100644 --- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js +++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js @@ -43,7 +43,8 @@ define(['require', RTagTableLayoutView: "#r_tagTableLayoutView", RLineageLayoutView: "#r_lineageLayoutView", RAuditTableLayoutView: "#r_auditTableLayoutView", - RTermTableLayoutView: "#r_termTableLayoutView" + RTermTableLayoutView: "#r_termTableLayoutView", + RProfileLayoutView: "#r_profileLayoutView" }, /** ui selector cache */ @@ -190,6 +191,18 @@ define(['require', this.renderAuditTableLayoutView(obj); this.renderTagTableLayoutView(obj); this.renderTermTableLayoutView(_.extend({}, obj, { term: true })); + if (collectionJSON && (!_.isUndefined(collectionJSON.attributes['profileData']) || collectionJSON.typeName === "hive_db")) { + if (collectionJSON.typeName === "hive_db") { + this.$('.profileTab a').text("Tables") + } + this.$('.profileTab').show(); + this.renderProfileLayoutView(_.extend({}, obj, { + entityDetail: collectionJSON.attributes, + profileData: collectionJSON.attributes.profileData, + typeName: collectionJSON.typeName + })); + } + // To render Schema check attribute "schemaElementsAttribute" var schemaOptions = this.entityDefCollection.fullCollection.find({ name: collectionJSON.typeName }).get('options'); if (schemaOptions && schemaOptions.hasOwnProperty('schemaElementsAttribute') && schemaOptions.schemaElementsAttribute !== "") { @@ -250,6 +263,14 @@ define(['require', } }) }, + onShow: function() { + var params = Utils.getUrlState.getQueryParams(); + if (params && params.profile) { + this.$('.nav.nav-tabs').find('.profileTab').addClass('active').siblings().removeClass('active'); + this.$('.tab-content').find('#tab-profile').addClass('active').siblings().removeClass('active'); + $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000); + } + }, fetchCollection: function() { this.collection.fetch({ reset: true }); }, @@ -400,6 +421,12 @@ define(['require', that.RAuditTableLayoutView.show(new AuditTableLayoutView(obj)); }); }, + renderProfileLayoutView: function(obj) { + var that = this; + require(['views/profile/ProfileLayoutView'], function(ProfileLayoutView) { + that.RProfileLayoutView.show(new ProfileLayoutView(obj)); + }); + }, onClickEditEntity: function(e) { var that = this; $(e.currentTarget).blur(); http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js b/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js new file mode 100644 index 0000000..874474f --- /dev/null +++ b/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js @@ -0,0 +1,206 @@ +/** + * 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', + 'backbone', + 'hbs!tmpl/profile/ProfileColumnLayoutView_tmpl', + 'collection/VProfileList', + 'utils/Utils', + 'utils/Messages', + 'utils/Globals', + 'moment', + 'models/VEntity', + 'nvd3' +], function(require, Backbone, ProfileColumnLayoutViewTmpl, VProfileList, Utils, Messages, Globals, moment, VEntity) { + 'use strict'; + + var ProfileColumnLayoutView = Backbone.Marionette.LayoutView.extend( + /** @lends ProfileColumnLayoutView */ + { + _viewName: 'ProfileColumnLayoutView', + + template: ProfileColumnLayoutViewTmpl, + + /** Layout sub regions */ + regions: {}, + templateHelpers: function() { + return { + profileData: this.profileData.attributes ? this.profileData.attributes : this.profileData, + entityDetail: this.entityDetail, + typeObject: this.typeObject + }; + }, + /** ui selector cache */ + ui: { + "backToYear": '[data-id="backToYear"]' + }, + /** ui events hash */ + events: function() { + var events = {}; + events["click " + this.ui.backToYear] = 'backToYear'; + return events; + }, + /** + * intialize a new ProfileColumnLayoutView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'profileData', 'guid', 'entityDetail')); + this.typeObject = Utils.getProfileTabType(this.profileData.attributes); + this.entityModel = new VEntity(); + this.formatValue = d3.format("2s") + + }, + fetchEntity: function(argument) { + var that = this; + this.entityModel.getEntity(this.entityDetail.table.guid, { + skipDefaultError: true, + success: function(data) { + var entity = data.entity, + profileData = entity && entity.attributes && entity.attributes.profileData ? entity.attributes.profileData.attributes : null; + if (profileData && profileData.rowCount) { + that.$('.rowValue').show(); + that.$('.rowValue .graphval').html('<b>' + that.formatValue(profileData.rowCount).replace('G', 'B') + '</b>'); + } + if (entity.attributes) { + if (entity.guid) { + that.$('.table_name .graphval').html('<b><a href="#!/detailPage/' + entity.guid + "?profile=true" + '">' + Utils.getName(entity) + '</a></b>'); + } + that.$('.table_created .graphval').html('<b>' + moment(entity.attributes.createTime).format("LL") + '</b>'); + } + } + }); + }, + bindEvents: function() {}, + onRender: function() { + this.renderGraph(); + this.fetchEntity(); + if (this.typeObject && this.typeObject.type === "date") { + this.$('svg').addClass('dateType'); + } + + }, + renderGraph: function(argument) { + if (!this.typeObject) { + return; + } + var that = this, + profileData = this.profileData.attributes; + this.data = [{ + key: this.typeObject.label, + values: this.typeObject.actualObj || [] + }]; + nv.addGraph(function() { + that.chart = nv.models.multiBarChart() + .x(function(d) { + return d.value || d.year + }) //Specify the data accessors. + .y(function(d) { + return d.count + }) + .height(220) + .stacked(false) + .showControls(false) + .reduceXTicks(false) + .staggerLabels(true) + .duration(1000) + .groupSpacing(0.6) + .wrapLabels(true) + .showLegend(false); + if (that.typeObject.type !== "date") { + that.chart.rotateLabels(-45); + } + that.chart.color(["#38BB9B"]); + + that.chart.yAxis.tickFormat(function(d) { + return that.formatValue(d).replace('G', 'B'); + }); + that.chart.xAxis + .axisLabel(that.typeObject.xAxisLabel) + .axisLabelDistance(-185); + that.chart.yAxis + .axisLabel(that.typeObject.yAxisLabel) + .axisLabelDistance(-5); + that.chart.margin({ + right: 30, + left: 80, + top: 20, + bottom: 60 + }); + if (that.typeObject.type === "date") { + that.chart.multibar.dispatch.elementClick = function(e) { + if (!that.monthsData) { + that.createMonthData(e.data.monthlyCounts) + } + } + } + that.svg = d3.select(that.$('svg')[0]).datum(that.data) + that.svg.transition().duration(0).call(that.chart); + + nv.utils.windowResize(that.chart.update); + + return that.chart; + }); + + }, + backToYear: function() { + this.ui.backToYear.hide(); + this.$('.profileGraphDetail').show(); + this.monthsData = null; + this.updateGraph(this.data); + }, + createMonthData: function(data) { + var monthsKey = { + "1": "Jan", + "2": "Feb", + "3": "Mar", + "4": "Apr", + "5": "May", + "6": "Jun", + "7": "Jul", + "8": "Aug", + "9": "Sep", + "10": "Oct", + "11": "Nov", + "12": "Dec" + }, + i = 1; + + this.monthsData = [{ + key: this.typeObject.label, + values: [] + }]; + + while (i <= 12) { + this.monthsData[0].values.push({ + value: monthsKey[i], + count: data[i] || 0 + }); + i++; + } + this.ui.backToYear.show(); + this.$('.profileGraphDetail').hide(); + this.updateGraph(this.monthsData); + + }, + updateGraph: function(data) { + this.svg.datum(data).transition().duration(0).call(this.chart); + }, + }); + return ProfileColumnLayoutView; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/profile/ProfileLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/profile/ProfileLayoutView.js b/dashboardv2/public/js/views/profile/ProfileLayoutView.js new file mode 100644 index 0000000..6b640d9 --- /dev/null +++ b/dashboardv2/public/js/views/profile/ProfileLayoutView.js @@ -0,0 +1,109 @@ +/** + * 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', + 'backbone', + 'hbs!tmpl/profile/ProfileLayoutView_tmpl', + 'collection/VProfileList', + 'utils/Utils', + 'utils/Messages', + 'utils/Globals' +], function(require, Backbone, ProfileLayoutViewTmpl, VProfileList, Utils, Messages, Globals) { + 'use strict'; + + var ProfileLayoutView = Backbone.Marionette.LayoutView.extend( + /** @lends ProfileLayoutView */ + { + _viewName: 'ProfileLayoutView', + + template: ProfileLayoutViewTmpl, + + /** Layout sub regions */ + regions: { + RProfileTableOrColumnLayoutView: "#r_profileTableOrColumnLayoutView" + }, + /** ui selector cache */ + ui: {}, + templateHelpers: function() { + return { + profileData: this.profileData ? this.profileData.attributes : this.profileData, + typeName: this.typeName + }; + }, + + /** ui events hash */ + events: function() { + var events = {}; + events["click " + this.ui.addTag] = 'checkedValue'; + return events; + }, + /** + * intialize a new ProfileLayoutView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'profileData', 'guid', 'typeName', 'entityDetail', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection')); + if (this.typeName === "hive_db") { + this.profileData = { attributes: true }; + } + }, + bindEvents: function() {}, + onRender: function() { + if (this.profileData) { + if (this.typeName === "hive_table") { + this.renderProfileTableLayoutView(); + } else if (this.typeName === "hive_db") { + this.renderSearchResultLayoutView(); + } else { + this.renderProfileColumnLayoutView(); + } + } + + }, + renderSearchResultLayoutView: function() { + var that = this; + require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) { + var value = { + 'guid': that.guid, + 'searchType': 'relationship', + 'profileDBView': true + }; + that.RProfileTableOrColumnLayoutView.show(new SearchResultLayoutView({ + 'value': value, + 'typeHeaders': that.typeHeaders, + 'entityDefCollection': that.entityDefCollection, + 'enumDefCollection': that.enumDefCollection, + 'classificationDefCollection': that.classificationDefCollection + })); + }); + }, + renderProfileTableLayoutView: function(tagGuid) { + var that = this; + require(['views/profile/ProfileTableLayoutView'], function(ProfileTableLayoutView) { + that.RProfileTableOrColumnLayoutView.show(new ProfileTableLayoutView(that.options)); + }); + }, + renderProfileColumnLayoutView: function(tagGuid) { + var that = this; + require(['views/profile/ProfileColumnLayoutView'], function(ProfileColumnLayoutView) { + that.RProfileTableOrColumnLayoutView.show(new ProfileColumnLayoutView(that.options)); + }); + }, + }); + return ProfileLayoutView; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js b/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js new file mode 100644 index 0000000..3e654eb --- /dev/null +++ b/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js @@ -0,0 +1,332 @@ +/** + * 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', + 'backbone', + 'hbs!tmpl/profile/ProfileTableLayoutView_tmpl', + 'collection/VProfileList', + 'utils/Utils', + 'utils/Messages', + 'utils/Globals', + 'moment', + 'collection/VCommonList', + 'models/VEntity', + 'sparkline' +], function(require, Backbone, ProfileTableLayoutViewTmpl, VProfileList, Utils, Messages, Globals, moment, VCommonList, VEntity, sparkline) { + 'use strict'; + + var ProfileTableLayoutView = Backbone.Marionette.LayoutView.extend( + /** @lends ProfileTableLayoutView */ + { + _viewName: 'ProfileTableLayoutView', + + template: ProfileTableLayoutViewTmpl, + + /** Layout sub regions */ + regions: { + RProfileTableLayoutView: '#r_profileTableLayoutView' + }, + /** ui selector cache */ + ui: {}, + + /** ui events hash */ + events: function() { + var events = {}; + events["click " + this.ui.addTag] = 'checkedValue'; + return events; + }, + /** + * intialize a new ProfileTableLayoutView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'profileData', 'guid', 'entityDetail')); + var that = this; + this.entityModel = new VEntity(); + this.profileCollection = new VCommonList([], { + comparator: function(item) { + return item.get('position') || 999; + } + }); + _.each(this.entityDetail.columns, function(obj) { + if (obj.attributes.profileData !== null) { + var profileObj = Utils.getProfileTabType(obj.attributes.profileData.attributes, true); + var changeValueObj = {} + if (profileObj && profileObj.type) { + if (profileObj.type === "numeric") { + changeValueObj['averageLength'] = 0; + changeValueObj['maxLength'] = 0; + } + if (profileObj.type === "string") { + changeValueObj['minValue'] = 0; + changeValueObj['maxValue'] = 0; + changeValueObj['meanValue'] = 0; + changeValueObj['medianValue'] = 0; + } + if (profileObj.type === "date") { + changeValueObj['averageLength'] = 0; + changeValueObj['maxLength'] = 0; + changeValueObj['minValue'] = 0; + changeValueObj['maxValue'] = 0; + changeValueObj['meanValue'] = 0; + changeValueObj['medianValue'] = 0; + } + } + + that.profileCollection.fullCollection.add(_.extend({}, obj.attributes, obj.attributes.profileData.attributes, changeValueObj, { guid: obj.guid, position: obj.attributes ? obj.attributes.position : null })); + } + }); + this.bindEvents(); + }, + onRender: function() { + this.fetchEntity(); + this.renderTableLayoutView(); + if (this.entityDetail) { + if (this.guid && this.entityDetail.name) { + this.$('.table_name .graphval').html('<b><a href="#!/detailPage/' + this.guid + '">' + this.entityDetail.name + '</a></b>'); + } + var profileData = this.entityDetail.profileData; + if (profileData && profileData.attributes && profileData.attributes.rowCount) { + this.$('.rowValue .graphval').html('<b>' + d3.format("2s")(profileData.attributes.rowCount).replace('G', 'B') + '</b>'); + } + this.$('.table_created .graphval').html('<b>' + (this.entityDetail.createTime ? moment(this.entityDetail.createTime).format("LL") : "--") + '</b>'); + } + }, + fetchEntity: function(argument) { + var that = this; + this.entityModel.getEntity(this.entityDetail.db.guid, { + skipDefaultError: true, + success: function(data) { + var entity = data.entity; + if (entity.attributes) { + if (entity.guid) { + that.$('.db_name .graphval').html('<b><a href="#!/detailPage/' + entity.guid + "?profile=true" + '">' + Utils.getName(entity) + '</a></b>'); + } + } + } + }); + }, + bindEvents: function() { + this.listenTo(this.profileCollection, 'backgrid:refresh', function(model, checked) { + this.renderGraphs(); + }, this); + }, + renderTableLayoutView: function() { + var that = this; + require(['utils/TableLayout'], function(TableLayout) { + var cols = new Backgrid.Columns(that.getAuditTableColumns()); + that.RProfileTableLayoutView.show(new TableLayout(_.extend({}, { + columns: cols, + collection: that.profileCollection, + includeFilter: false, + includePagination: true, + includePageSize: false, + includeFooterRecords: true, + gridOpts: { + className: "table table-hover backgrid table-quickMenu", + emptyText: 'No records found!' + } + }))); + that.renderGraphs(); + }); + }, + renderGraphs: function() { + this.$('.sparklines').sparkline('html', { enableTagOptions: true }); + this.$('.sparklines').bind('sparklineClick', function(ev) { + var id = $(ev.target).data().guid; + Utils.setUrl({ + url: '#!/detailPage/' + id, + mergeBrowserUrl: false, + trigger: true, + urlParams: { + 'profile': true + } + }); + }); + }, + getAuditTableColumns: function() { + var that = this; + return this.profileCollection.constructor.getTableCols({ + name: { + label: "Name", + cell: "Html", + editable: false, + sortable: true, + sortType: 'toggle', + direction: 'ascending', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + return '<div><a href="#!/detailPage/' + model.get('guid') + '?profile=true">' + rawValue + '</a></div>'; + } + }) + }, + type: { + label: "Type", + cell: "String", + editable: false, + sortable: true, + sortType: 'toggle', + }, + nonNullData: { + label: "% NonNull", + cell: "Html", + editable: false, + sortable: true, + sortType: 'toggle', + width: "180", + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + if (rawValue < 50) { + var barClass = ((rawValue > 30) && (rawValue <= 50)) ? "progress-bar-warning" : "progress-bar-danger"; + } else { + var barClass = "progress-bar-success"; + } + return '<div class="progress cstm_progress" title="' + rawValue + '%"><div class="progress-bar ' + barClass + ' cstm_success-bar progress-bar-striped" style="width:' + rawValue + '%">' + rawValue + '%</div></div>' + } + }) + }, + + distributionDecile: { + label: "Distribution", + cell: "Html", + editable: false, + sortable: false, + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var sparkarray = []; + var distibutionObj = Utils.getProfileTabType(model.toJSON()); + if (distibutionObj) { + _.each(distibutionObj.actualObj, function(obj) { + sparkarray.push(obj.count); + }) + } + + return '<span data-guid="' + model.get('guid') + '" class="sparklines" sparkType="bar" sparkBarColor="#38BB9B" values="' + sparkarray.join(',') + '"></span>' + } + }) + }, + cardinality: { + label: "Cardinality", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle' + }, + minValue: { + label: "Min", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "numeric") { + return rawValue; + } + return "-"; + } + }) + }, + maxValue: { + label: "Max", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "numeric") { + return rawValue; + } + return "-"; + } + }) + }, + averageLength: { + label: "Average Length", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "string") { + return rawValue; + } + return "-"; + } + }) + }, + maxLength: { + label: "Max Length", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "string") { + return rawValue; + } + return "-"; + } + }) + }, + meanValue: { + label: "Mean", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "numeric") { + return rawValue; + } + return "-"; + } + }) + }, + medianValue: { + label: "Median", + cell: "Number", + editable: false, + sortable: true, + sortType: 'toggle', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var profileObj = Utils.getProfileTabType(model.toJSON(), true); + if (profileObj && profileObj.type === "numeric") { + return rawValue; + } + return "-"; + } + }) + } + }, this.profileCollection); + + } + + }); + return ProfileTableLayoutView; +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/schema/SchemaLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/schema/SchemaLayoutView.js b/dashboardv2/public/js/views/schema/SchemaLayoutView.js index e7765f3..585cf1b 100644 --- a/dashboardv2/public/js/views/schema/SchemaLayoutView.js +++ b/dashboardv2/public/js/views/schema/SchemaLayoutView.js @@ -184,7 +184,7 @@ define(['require', }); if (this.schemaCollection.length === 0 && this.deleteObj.length) { this.ui.checkDeletedEntity.find("input").prop('checked', true); - this.schemaCollection.reset(this.deleteObj, { silent: true }); + this.schemaCollection.fullCollection.reset(this.deleteObj, { silent: true }); } if (this.activeObj.length === 0 && this.deleteObj.length === 0) { this.ui.checkDeletedEntity.hide(); @@ -202,29 +202,8 @@ define(['require', renderTableLayoutView: function() { var that = this; require(['utils/TableLayout'], function(TableLayout) { - var columnCollection = Backgrid.Columns.extend({ - // sortKey: "position", - // comparator: function(item) { - // return item.get(this.sortKey) || 999; - // }, - // setPositions: function() { - // _.each(this.models, function(model, index) { - // if (model.get('name') == "name") { - // model.set("position", 2, { silent: true }); - // model.set("label", "Name"); - // } else if (model.get('name') == "description") { - // model.set("position", 3, { silent: true }); - // model.set("label", "Description"); - // } else if (model.get('name') == "owner") { - // model.set("position", 4, { silent: true }); - // model.set("label", "Owner"); - // } - // }); - // return this; - // } - }); - var columns = new columnCollection(that.getSchemaTableColumns()); - //columns.setPositions().sort(); + var columnCollection = Backgrid.Columns.extend({}), + columns = new columnCollection(that.getSchemaTableColumns()); that.RSchemaTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { columns: columns }))); @@ -436,10 +415,10 @@ define(['require', onCheckDeletedEntity: function(e) { if (e.target.checked) { if (this.deleteObj.length) { - this.schemaCollection.reset(this.activeObj.concat(this.deleteObj)); + this.schemaCollection.fullCollection.reset(this.activeObj.concat(this.deleteObj)); } } else { - this.schemaCollection.reset(this.activeObj); + this.schemaCollection.fullCollection.reset(this.activeObj) } } }); http://git-wip-us.apache.org/repos/asf/atlas/blob/b8255d41/dashboardv2/public/js/views/search/SearchResultLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchResultLayoutView.js b/dashboardv2/public/js/views/search/SearchResultLayoutView.js index 072295e..80b5b04 100644 --- a/dashboardv2/public/js/views/search/SearchResultLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchResultLayoutView.js @@ -138,7 +138,7 @@ define(['require', collection: this.searchCollection, includePagination: false, includeFooterRecords: false, - includeColumnManager: (Utils.getUrlState.isSearchTab() && this.value && this.value.searchType === "basic" ? true : false), + includeColumnManager: (Utils.getUrlState.isSearchTab() && this.value && this.value.searchType === "basic" && !this.value.profileDBView ? true : false), includeOrderAbleColumns: false, includeSizeAbleColumns: false, includeTableLoader: false, @@ -394,11 +394,14 @@ define(['require', that.ui.previousData.attr('disabled', true); } that.renderTableLayoutView(); - var searchString = 'Results for: <span class="filterQuery">' + that.generateQueryOfFilter() + "</span>"; - if (Globals.entityCreate && Globals.entityTypeConfList && Utils.getUrlState.isSearchTab()) { - searchString += "<p>If you do not find the entity in search result below then you can" + '<a href="javascript:void(0)" data-id="createEntity"> create new entity</a></p>'; + + if (value && !value.profileDBView) { + var searchString = 'Results for: <span class="filterQuery">' + that.generateQueryOfFilter() + "</span>"; + if (Globals.entityCreate && Globals.entityTypeConfList && Utils.getUrlState.isSearchTab()) { + searchString += "<p>If you do not find the entity in search result below then you can" + '<a href="javascript:void(0)" data-id="createEntity"> create new entity</a></p>'; + } + that.$('.searchResult').html(searchString); } - that.$('.searchResult').html(searchString); }, silent: true, reset: true @@ -409,6 +412,14 @@ define(['require', this.searchCollection.url = UrlLinks.searchApiUrl(value.searchType); } _.extend(this.searchCollection.queryParams, { 'query': (value.query ? value.query.trim() : null), 'typeName': value.type || null, 'classification': value.tag || null }); + if (value.profileDBView && value.guid) { + var profileParam = {}; + profileParam['guid'] = value.guid; + profileParam['relation'] = '__hive_table.db'; + profileParam['sortBy'] = 'name'; + profileParam['sortOrder'] = 'ASCENDING'; + $.extend(this.searchCollection.queryParams, profileParam); + } if (isPostMethod) { this.searchCollection.filterObj = _.extend({}, filterObj); apiObj['data'] = _.extend({}, filterObj, _.pick(this.searchCollection.queryParams, 'query', 'excludeDeletedEntities', 'limit', 'offset', 'typeName', 'classification')) @@ -502,7 +513,7 @@ define(['require', }; col['name'] = { - label: "Name", + label: this.value && this.value.profileDBView ? "Table Name" : "Name", cell: "html", editable: false, sortable: false, @@ -555,130 +566,149 @@ define(['require', } }) }; - - col['description'] = { - label: "Description", - cell: "String", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: true, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.attributes && obj.attributes.description) { - return obj.attributes.description; + if (this.value && this.value.profileDBView) { + col['createTime'] = { + label: "Date Created", + cell: "Html", + editable: false, + sortable: false, + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var obj = model.toJSON(); + if (obj && obj.attributes && obj.attributes.createTime) { + return new Date(obj.attributes.createTime); + } else { + return '-' + } } - } - }) - }; - col['typeName'] = { - label: "Type", - cell: "Html", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'typeName') : true), - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.typeName) { - return '<a title="Search ' + obj.typeName + '" href="#!/search/searchResult?query=' + obj.typeName + ' &searchType=dsl&dslChecked=true">' + obj.typeName + '</a>'; + }) + } + } + if (this.value && !this.value.profileDBView) { + col['description'] = { + label: "Description", + cell: "String", + editable: false, + sortable: false, + resizeable: true, + orderable: true, + renderable: true, + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var obj = model.toJSON(); + if (obj && obj.attributes && obj.attributes.description) { + return obj.attributes.description; + } } - } - }) - }; - - col['tag'] = { - label: "Tags", - cell: "Html", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'tag') : true), - className: 'searchTag', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj.status && Enums.entityStateReadOnly[obj.status]) { - return '<div class="readOnly">' + CommonViewFunction.tagForTable(obj); + '</div>'; - } else { - return CommonViewFunction.tagForTable(obj); + }) + }; + col['typeName'] = { + label: "Type", + cell: "Html", + editable: false, + sortable: false, + resizeable: true, + orderable: true, + renderable: (columnToShow ? _.contains(columnToShow, 'typeName') : true), + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var obj = model.toJSON(); + if (obj && obj.typeName) { + return '<a title="Search ' + obj.typeName + '" href="#!/search/searchResult?query=' + obj.typeName + ' &searchType=dsl&dslChecked=true">' + obj.typeName + '</a>'; + } } + }) + }; - } - }) - }; - if (Globals.taxonomy) { - col['terms'] = { - label: "Terms", + col['tag'] = { + label: "Tags", cell: "Html", editable: false, sortable: false, resizeable: true, orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'terms') : true), - className: 'searchTerm', + renderable: (columnToShow ? _.contains(columnToShow, 'tag') : true), + className: 'searchTag', formatter: _.extend({}, Backgrid.CellFormatter.prototype, { fromRaw: function(rawValue, model) { var obj = model.toJSON(); - var returnObject = CommonViewFunction.termTableBreadcrumbMaker(obj); - if (returnObject.object) { - that.bradCrumbList.push(returnObject.object); - } if (obj.status && Enums.entityStateReadOnly[obj.status]) { - return '<div class="readOnly">' + returnObject.html + '</div>'; + return '<div class="readOnly">' + CommonViewFunction.tagForTable(obj); + '</div>'; } else { - return returnObject.html; + return CommonViewFunction.tagForTable(obj); } + } }) }; - } - if (this.value && this.value.searchType === "basic") { - var def = this.entityDefCollection.fullCollection.find({ name: this.value.type }); - if (def) { - var attrObj = Utils.getNestedSuperTypeObj({ data: def.toJSON(), collection: this.entityDefCollection, attrMerge: true }); - _.each(attrObj, function(obj, key) { - var key = obj.name, - isRenderable = _.contains(columnToShow, key) - if (key == "name" || key == "description" || key == "owner") { - if (columnToShow) { - col[key].renderable = isRenderable; + if (Globals.taxonomy) { + col['terms'] = { + label: "Terms", + cell: "Html", + editable: false, + sortable: false, + resizeable: true, + orderable: true, + renderable: (columnToShow ? _.contains(columnToShow, 'terms') : true), + className: 'searchTerm', + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var obj = model.toJSON(); + var returnObject = CommonViewFunction.termTableBreadcrumbMaker(obj); + if (returnObject.object) { + that.bradCrumbList.push(returnObject.object); + } + if (obj.status && Enums.entityStateReadOnly[obj.status]) { + return '<div class="readOnly">' + returnObject.html + '</div>'; + } else { + return returnObject.html; + } } - return; - } - col[obj.name] = { - label: obj.name.capitalize(), - cell: "Html", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: isRenderable, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var modelObj = model.toJSON(); + }) + }; + } + if (this.value && this.value.searchType === "basic") { + var def = this.entityDefCollection.fullCollection.find({ name: this.value.type }); + if (def) { + var attrObj = Utils.getNestedSuperTypeObj({ data: def.toJSON(), collection: this.entityDefCollection, attrMerge: true }); + _.each(attrObj, function(obj, key) { + var key = obj.name, + isRenderable = _.contains(columnToShow, key) + if (key == "name" || key == "description" || key == "owner") { + if (columnToShow) { + col[key].renderable = isRenderable; + } + return; + } + col[obj.name] = { + label: obj.name.capitalize(), + cell: "Html", + editable: false, + sortable: false, + resizeable: true, + orderable: true, + renderable: isRenderable, + formatter: _.extend({}, Backgrid.CellFormatter.prototype, { + fromRaw: function(rawValue, model) { + var modelObj = model.toJSON(); - if (modelObj && modelObj.attributes && !_.isUndefined(modelObj.attributes[key])) { - var tempObj = { - 'scope': that, - 'attributeDefs': [obj], - 'valueObject': {}, - 'isTable': false - } + if (modelObj && modelObj.attributes && !_.isUndefined(modelObj.attributes[key])) { + var tempObj = { + 'scope': that, + 'attributeDefs': [obj], + 'valueObject': {}, + 'isTable': false + } - tempObj.valueObject[key] = modelObj.attributes[key] - Utils.findAndMergeRefEntity(tempObj.valueObject, that.searchCollection.referredEntities); - return CommonViewFunction.propertyTable(tempObj); + tempObj.valueObject[key] = modelObj.attributes[key] + Utils.findAndMergeRefEntity(tempObj.valueObject, that.searchCollection.referredEntities); + return CommonViewFunction.propertyTable(tempObj); + } } - } - }) - }; - }); + }) + }; + }); + } } } return this.searchCollection.constructor.getTableCols(col, this.searchCollection);
