mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-12 10:35:51 +00:00
implement the confidential fields of metadata dashboard
This commit is contained in:
parent
5d3b534086
commit
2a4f281ba5
@ -23,12 +23,8 @@ import play.mvc.Result;
|
||||
import play.Logger;
|
||||
import play.mvc.Security;
|
||||
import utils.Tree;
|
||||
import views.html.index;
|
||||
import views.html.login;
|
||||
import views.html.lineage;
|
||||
import views.html.schemaHistory;
|
||||
import views.html.scriptFinder;
|
||||
import views.html.idpc;
|
||||
import views.html.*;
|
||||
|
||||
import static play.data.Form.form;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import security.AuthenticationManager;
|
||||
@ -143,6 +139,18 @@ public class Application extends Controller
|
||||
return ok(idpc.render(username, isInternal));
|
||||
}
|
||||
|
||||
@Security.Authenticated(Secured.class)
|
||||
public static Result dashboard()
|
||||
{
|
||||
Boolean isInternal = Play.application().configuration().getBoolean(LINKEDIN_INTERNAL_KEY, false);
|
||||
String username = session("user");
|
||||
if (username == null)
|
||||
{
|
||||
username = "";
|
||||
}
|
||||
return ok(dashboard.render(username, isInternal));
|
||||
}
|
||||
|
||||
public static Result login()
|
||||
{
|
||||
Boolean isInternal = Play.application().configuration().getBoolean(LINKEDIN_INTERNAL_KEY, false);
|
||||
|
||||
81
web/app/controllers/api/v1/Dashboard.java
Normal file
81
web/app/controllers/api/v1/Dashboard.java
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright 2015 LinkedIn Corp. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
package controllers.api.v1;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import dao.DashboardDAO;
|
||||
import dao.JiraDAO;
|
||||
import dao.UserDAO;
|
||||
import models.JiraTicket;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import play.Logger;
|
||||
import play.libs.Json;
|
||||
import play.mvc.Controller;
|
||||
import play.mvc.Result;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Dashboard extends Controller
|
||||
{
|
||||
|
||||
public static Result getConfidentialDatasetsPercentage(String managerId)
|
||||
{
|
||||
return ok(DashboardDAO.getConfidentialPercentageByManagerId(managerId));
|
||||
}
|
||||
|
||||
public static Result getPagedConfidentialDatasets(String managerId)
|
||||
{
|
||||
int page = 1;
|
||||
String pageStr = request().getQueryString("page");
|
||||
if (StringUtils.isBlank(pageStr))
|
||||
{
|
||||
page = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
page = Integer.parseInt(pageStr);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
Logger.error("Dashboard Controller getPagedConfidentialDatasets wrong page parameter. Error message: " + e.getMessage());
|
||||
page = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int size = 10;
|
||||
String sizeStr = request().getQueryString("size");
|
||||
if (StringUtils.isBlank(sizeStr))
|
||||
{
|
||||
size = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
size = Integer.parseInt(sizeStr);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
Logger.error("Dashboard Controller getPagedConfidentialDatasets wrong size parameter. Error message: " + e.getMessage());
|
||||
size = 10;
|
||||
}
|
||||
}
|
||||
|
||||
return ok(DashboardDAO.getPagedConfidentialDatasetsByManagerId(managerId, page, size));
|
||||
}
|
||||
}
|
||||
230
web/app/dao/DashboardDAO.java
Normal file
230
web/app/dao/DashboardDAO.java
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright 2015 LinkedIn Corp. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
package dao;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import models.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import play.Logger;
|
||||
import play.libs.Json;
|
||||
|
||||
public class DashboardDAO extends AbstractMySQLOpenSourceDAO
|
||||
{
|
||||
private final static String GET_ORG_HIERARCHY = "SELECT display_name, org_hierarchy FROM " +
|
||||
"dir_external_user_info WHERE user_id = ? limit 1";
|
||||
|
||||
private final static String GET_CONFIDENTIAL_DATASETS = "SELECT SQL_CALC_FOUND_ROWS o.dataset_id, " +
|
||||
"GROUP_CONCAT(o.owner_id ORDER BY o.owner_id ASC SEPARATOR ',') as owner_id, d.name FROM " +
|
||||
"dataset_owner o JOIN dict_dataset d ON o.dataset_id = d.id WHERE o.dataset_id in " +
|
||||
"( SELECT DISTINCT dataset_id from dict_pii_field )" +
|
||||
" and owner_id in ( " +
|
||||
"SELECT user_id FROM dir_external_user_info WHERE org_hierarchy = ? or org_hierarchy like ?) " +
|
||||
"GROUP BY o.dataset_id, d.name ORDER BY d.name LIMIT ?, ?";
|
||||
|
||||
private final static String GET_TOP_LEVEL_CONFIDENTIAL_DATASETS = "SELECT SQL_CALC_FOUND_ROWS o.dataset_id, " +
|
||||
"GROUP_CONCAT(o.owner_id ORDER BY o.owner_id ASC SEPARATOR ',') as owner_id, d.name FROM " +
|
||||
"dataset_owner o JOIN dict_dataset d ON o.dataset_id = d.id WHERE o.dataset_id in " +
|
||||
"( SELECT DISTINCT dataset_id from dict_pii_field )" +
|
||||
" and owner_id in ( " +
|
||||
"SELECT user_id FROM dir_external_user_info WHERE org_hierarchy = ? or org_hierarchy like ?) " +
|
||||
"GROUP BY o.dataset_id, d.name ORDER BY d.name LIMIT ?, ?";
|
||||
|
||||
private final static String GET_CONFIDENTIAL_INFO = "SELECT count(distinct o.dataset_id) as count " +
|
||||
"FROM dataset_owner o JOIN dict_dataset d ON o.dataset_id = d.id " +
|
||||
"WHERE o.dataset_id in ( SELECT DISTINCT dataset_id from dict_pii_field ) and owner_id in ( " +
|
||||
"SELECT user_id FROM dir_external_user_info WHERE org_hierarchy = ? or org_hierarchy like ?)";
|
||||
|
||||
private final static String GET_TOP_LEVEL_CONFIDENTIAL_INFO = "SELECT count(distinct o.dataset_id) as count " +
|
||||
"FROM dataset_owner o JOIN dict_dataset d ON o.dataset_id = d.id " +
|
||||
"WHERE o.dataset_id in ( SELECT DISTINCT dataset_id from dict_pii_field ) and owner_id in ( " +
|
||||
"SELECT user_id FROM dir_external_user_info WHERE org_hierarchy = ? or org_hierarchy like ?)";
|
||||
|
||||
private final static String GET_CONFIDENTIAL_FIELDS = "SELECT field_name " +
|
||||
"FROM dict_pii_field WHERE dataset_id = ?";
|
||||
|
||||
|
||||
public static ObjectNode getConfidentialPercentageByManagerId(String managerId) {
|
||||
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
ConfidentialFieldsOwner currentUser = null;
|
||||
List<ConfidentialFieldsOwner> memberList = new ArrayList<ConfidentialFieldsOwner>();
|
||||
if (StringUtils.isNotBlank(managerId))
|
||||
{
|
||||
List<LdapInfo> ldapInfoList = JiraDAO.getCurrentUserLdapInfo(managerId);
|
||||
if (ldapInfoList != null && ldapInfoList.size() > 0)
|
||||
{
|
||||
LdapInfo ldapInfo = ldapInfoList.get(0);
|
||||
if (ldapInfo != null)
|
||||
{
|
||||
currentUser = new ConfidentialFieldsOwner();
|
||||
currentUser.displayName = ldapInfo.displayName;
|
||||
currentUser.iconUrl = ldapInfo.iconUrl;
|
||||
currentUser.managerUserId = ldapInfo.managerUserId;
|
||||
currentUser.orgHierarchy = ldapInfo.orgHierarchy;
|
||||
currentUser.userName = ldapInfo.userName;
|
||||
if (StringUtils.isNotBlank(ldapInfo.orgHierarchy)) {
|
||||
currentUser.potentialDatasets = getJdbcTemplate().queryForObject(
|
||||
GET_CONFIDENTIAL_INFO,
|
||||
Long.class,
|
||||
currentUser.orgHierarchy,
|
||||
currentUser.orgHierarchy + "/%");
|
||||
}
|
||||
else if (managerId.equalsIgnoreCase("jweiner"))
|
||||
{
|
||||
currentUser.potentialDatasets = getJdbcTemplate().queryForObject(
|
||||
GET_CONFIDENTIAL_INFO,
|
||||
Long.class,
|
||||
"/" + currentUser.userName,
|
||||
"/" + currentUser.userName + "/%");
|
||||
}
|
||||
currentUser.confirmed = 0L;
|
||||
if (currentUser.potentialDatasets != 0)
|
||||
{
|
||||
currentUser.completed = 100.0 * (currentUser.confirmed / currentUser.potentialDatasets);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUser.completed = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
List<LdapInfo> members = JiraDAO.getFirstLevelLdapInfo(managerId);
|
||||
if (members != null)
|
||||
{
|
||||
for(LdapInfo member : members)
|
||||
{
|
||||
if (member != null && StringUtils.isNotBlank(member.orgHierarchy))
|
||||
{
|
||||
ConfidentialFieldsOwner owner = new ConfidentialFieldsOwner();
|
||||
owner.displayName = member.displayName;
|
||||
owner.fullName = member.fullName;
|
||||
owner.userName = member.userName;
|
||||
owner.iconUrl = member.iconUrl;
|
||||
owner.managerUserId = member.managerUserId;
|
||||
owner.orgHierarchy = member.orgHierarchy;
|
||||
owner.potentialDatasets = getJdbcTemplate().queryForObject(
|
||||
GET_CONFIDENTIAL_INFO,
|
||||
Long.class,
|
||||
owner.orgHierarchy,
|
||||
owner.orgHierarchy + "/%");
|
||||
|
||||
owner.confirmed = 0L;
|
||||
if (owner.potentialDatasets != 0)
|
||||
{
|
||||
owner.completed = 100.0 * (owner.confirmed / owner.potentialDatasets);
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.completed = 0.0;
|
||||
}
|
||||
memberList.add(owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resultNode.put("status", "ok");
|
||||
resultNode.set("currentUser", Json.toJson(currentUser));
|
||||
resultNode.set("members", Json.toJson(memberList));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode getPagedConfidentialDatasetsByManagerId(String managerId, Integer page, Integer size) {
|
||||
|
||||
ObjectNode result = Json.newObject();
|
||||
|
||||
javax.sql.DataSource ds = getJdbcTemplate().getDataSource();
|
||||
DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(tm);
|
||||
result = txTemplate.execute(new TransactionCallback<ObjectNode>()
|
||||
{
|
||||
public ObjectNode doInTransaction(TransactionStatus status)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<DatasetConfidential> confidentialList = new ArrayList<DatasetConfidential>();
|
||||
|
||||
if (StringUtils.isNotBlank(managerId))
|
||||
{
|
||||
List<LdapInfo> ldapInfoList = JiraDAO.getCurrentUserLdapInfo(managerId);
|
||||
if (ldapInfoList != null && ldapInfoList.size() > 0)
|
||||
{
|
||||
LdapInfo ldapInfo = ldapInfoList.get(0);
|
||||
if (ldapInfo != null)
|
||||
{
|
||||
List<Map<String, Object>> rows = null;
|
||||
if (StringUtils.isNotBlank(ldapInfo.orgHierarchy)) {
|
||||
rows = getJdbcTemplate().queryForList(
|
||||
GET_CONFIDENTIAL_DATASETS,
|
||||
ldapInfo.orgHierarchy,
|
||||
ldapInfo.orgHierarchy + "/%",
|
||||
(page - 1) * size,
|
||||
size);
|
||||
}
|
||||
else if (managerId.equalsIgnoreCase("jweiner"))
|
||||
{
|
||||
rows = getJdbcTemplate().queryForList(
|
||||
GET_CONFIDENTIAL_DATASETS,
|
||||
"/" + ldapInfo.userName,
|
||||
"/" + ldapInfo.userName + "/%",
|
||||
(page - 1) * size,
|
||||
size);
|
||||
}
|
||||
|
||||
try {
|
||||
count = getJdbcTemplate().queryForObject(
|
||||
"SELECT FOUND_ROWS()",
|
||||
Long.class);
|
||||
}
|
||||
catch(EmptyResultDataAccessException e)
|
||||
{
|
||||
Logger.error("Exception = " + e.getMessage());
|
||||
}
|
||||
|
||||
for (Map row : rows) {
|
||||
DatasetConfidential datasetConfidential = new DatasetConfidential();
|
||||
datasetConfidential.datasetId = (Long) row.get("dataset_id");
|
||||
datasetConfidential.datasetName = (String) row.get("name");
|
||||
datasetConfidential.ownerId = (String) row.get("owner_id");
|
||||
if (datasetConfidential.datasetId != null && datasetConfidential.datasetId > 0) {
|
||||
datasetConfidential.confidentialFieldList =
|
||||
getJdbcTemplate().queryForList(
|
||||
GET_CONFIDENTIAL_FIELDS,
|
||||
String.class,
|
||||
datasetConfidential.datasetId);
|
||||
}
|
||||
confidentialList.add(datasetConfidential);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resultNode.put("status", "ok");
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("totalPages", (int) Math.ceil(count / ((double) size)));
|
||||
resultNode.set("datasets", Json.toJson(confidentialList));
|
||||
return resultNode;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
28
web/app/models/ConfidentialFieldsOwner.java
Normal file
28
web/app/models/ConfidentialFieldsOwner.java
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright 2015 LinkedIn Corp. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
package models;
|
||||
|
||||
public class ConfidentialFieldsOwner {
|
||||
|
||||
public String userName;
|
||||
public String fullName;
|
||||
public String displayName;
|
||||
public String email;
|
||||
public String managerUserId;
|
||||
public String orgHierarchy;
|
||||
public String iconUrl;
|
||||
public Long potentialDatasets;
|
||||
public Long confirmed;
|
||||
public Double completed;
|
||||
}
|
||||
24
web/app/models/DatasetConfidential.java
Normal file
24
web/app/models/DatasetConfidential.java
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright 2015 LinkedIn Corp. All rights reserved.
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
package models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DatasetConfidential {
|
||||
|
||||
public Long datasetId;
|
||||
public String ownerId;
|
||||
public String datasetName;
|
||||
public List<String> confidentialFieldList;
|
||||
}
|
||||
189
web/app/views/dashboard.scala.html
Normal file
189
web/app/views/dashboard.scala.html
Normal file
@ -0,0 +1,189 @@
|
||||
@(user: String, isInternal:Boolean)
|
||||
@main(user, "", isInternal) {
|
||||
<div id="content">
|
||||
<script type="text/x-handlebars" id="dashboard">
|
||||
<div id="schemaView" class="container-fluid">
|
||||
<div class="col-xs-12">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h3>Metadata Dashboard</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 well well-sm">
|
||||
<ul class="breadcrumbs">
|
||||
{{#each breadcrumbs as |crumb|}}
|
||||
<li>
|
||||
<a href={{crumb.urn}} title={{crumb.title }}>
|
||||
{{ crumb.title }}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="dashboardtabs" class="nav nav-tabs">
|
||||
<li id="confidentialpage">
|
||||
<a id="confidentiallink" data-toggle="tab" href="#confidentialtab">Confidential Fields</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="confidentialtab" class="tab-pane">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<h4>Confidential Fields for {{ currentConfidentialFieldsUser.displayName }}</h4>
|
||||
<table class="table table-bordered table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Name</th>
|
||||
<th class="text-center">Completion</th>
|
||||
<th class="text-center">Total Potential</th>
|
||||
<th class="text-center">Confirmed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src={{currentConfidentialFieldsUser.iconUrl}} title={{currentConfidentialFieldsUser.displayName}}
|
||||
width="25px"
|
||||
height="25px"/>
|
||||
<a href='metadata#/dashboard/{{currentConfidentialFieldsUser.userName}}' title={{currentConfidentialFieldsUser.displayName}}>
|
||||
{{ currentConfidentialFieldsUser.displayName }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">{{ currentConfidentialFieldsUser.completed }}%</td>
|
||||
<td class="text-center">{{ currentConfidentialFieldsUser.potentialDatasets }}</td>
|
||||
<td class="text-center">{{ currentConfidentialFieldsUser.confirmed }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>Ticket Roll-Up for Individual User</h4>
|
||||
<table class="table table-bordered table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Name</th>
|
||||
<th class="text-center">Completion</th>
|
||||
<th class="text-center">Total Potential</th>
|
||||
<th class="text-center">Confirmed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if userNoMembers}}
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-center">
|
||||
This user has no one that reports to them.
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
{{#each confidentialFieldsOwners as |user|}}
|
||||
<tr>
|
||||
<td>
|
||||
<img src={{user.iconUrl}} title={{user.displayName}}
|
||||
width="25px"
|
||||
height="25px"/>
|
||||
<a href='metadata#/dashboard/{{user.userName}}' title={{user.displayName}}>
|
||||
{{ user.displayName }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">{{ user.completed }}%</td>
|
||||
<td class="text-center">{{ user.potentialDatasets }}</td>
|
||||
<td class="text-center">{{ user.confirmed }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-8">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<h4>List of Potential Datasets</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-pagination">
|
||||
<ul class="pager">
|
||||
{{#unless cfFirst}}
|
||||
<li class="previous">
|
||||
<a {{ action "prevCfPage" }}>
|
||||
← Prev
|
||||
</a>
|
||||
</li>
|
||||
{{/unless}}
|
||||
<li>
|
||||
{{ confidentialFieldsDatasets.count }} datasets - page {{ confidentialFieldsDatasets.page }} of {{ confidentialFieldsDatasets.totalPages }}
|
||||
</li>
|
||||
{{#unless cfLast}}
|
||||
<li class="next">
|
||||
<a {{ action "nextCfPage" }}>
|
||||
Next →
|
||||
</a>
|
||||
</li>
|
||||
{{/unless}}
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-bordered table-condensed table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Dataset</th>
|
||||
<th class="text-center">Fields</th>
|
||||
<th class="text-center">Owners</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if ticketsInProgress}}
|
||||
<tr>
|
||||
<td colspan="8" class="text-center">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<i class="fa fa-spinner spinning fa-4x">
|
||||
</i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
{{#if userNoConfidentialFields}}
|
||||
<tr>
|
||||
<td colspan="8">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-center">
|
||||
This user has no datasets with confidential fields.
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
{{#each confidentialFieldsDatasets.datasets as |dataset|}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/#/datasets/{{dataset.datasetId}}">
|
||||
{{ dataset.datasetName }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ dataset.confidentialFieldList }}
|
||||
</td>
|
||||
<td class="text-center">{{ dataset.ownerId }}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<script src="@routes.Assets.at("vendors/ember-2.6.2/ember-template-compiler.js")" type="text/javascript"></script>
|
||||
<script src="@routes.Assets.at("vendors/ember-2.6.2/ember.js")" type="text/javascript"></script>
|
||||
<script src="@routes.Assets.at("javascripts/dashboard.js")" type="text/javascript"></script>
|
||||
}
|
||||
@ -90,6 +90,13 @@
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
@if(isInternal) {
|
||||
<li>
|
||||
<a href="/metadata">
|
||||
<span>
|
||||
Metadata Dashboard
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/scriptFinder">
|
||||
<span>
|
||||
|
||||
@ -35,6 +35,8 @@ GET /lineage/metric/:id controllers.Application.metr
|
||||
|
||||
GET /lineage/flow/:application/:project/:flow controllers.Application.flowLineage(application: String, project: String, flow: String)
|
||||
|
||||
GET /metadata controllers.Application.dashboard()
|
||||
|
||||
GET /scriptFinder controllers.Application.scriptFinder()
|
||||
|
||||
GET /schemaHistory controllers.Application.schemaHistory()
|
||||
@ -213,6 +215,10 @@ GET /api/v1/jira/ldapinfo controllers.api.v1.Jira.getL
|
||||
|
||||
GET /api/v1/jira/members/:managerId controllers.api.v1.Jira.getFirstLevelLdapInfo(managerId :String)
|
||||
|
||||
GET /api/v1/metadata/dashboard/:managerId controllers.api.v1.Dashboard.getConfidentialDatasetsPercentage(managerId :String)
|
||||
|
||||
GET /api/v1/metadata/dataset/:managerId controllers.api.v1.Dashboard.getPagedConfidentialDatasets(managerId :String)
|
||||
|
||||
GET /api/v1/scriptFinder/scripts controllers.api.v1.ScriptFinder.getScripts()
|
||||
|
||||
GET /api/v1/scriptFinder/scripts/types controllers.api.v1.ScriptFinder.getAllScriptTypes()
|
||||
|
||||
193
web/public/javascripts/dashboard.js
Normal file
193
web/public/javascripts/dashboard.js
Normal file
@ -0,0 +1,193 @@
|
||||
(function ($) {
|
||||
$(document).ready(function() {
|
||||
|
||||
App = Ember.Application.create({rootElement: "#content"});
|
||||
|
||||
if (Ember.Debug && typeof Ember.Debug.registerDeprecationHandler === 'function') {
|
||||
Ember.Debug.registerDeprecationHandler(function(message, options, next) {
|
||||
if (options && options.id && options.id == 'ember-routing.router-resource') {
|
||||
return;
|
||||
}
|
||||
next(message, options);
|
||||
});
|
||||
}
|
||||
|
||||
App.Router.map(function() {
|
||||
this.resource('dashboard', function(){
|
||||
this.resource('user', {path: '/:user'});
|
||||
});
|
||||
});
|
||||
|
||||
App.IndexRoute = Ember.Route.extend({
|
||||
redirect: function() {
|
||||
this.transitionTo('user', "jweiner");
|
||||
}
|
||||
});
|
||||
|
||||
var genBreadcrumbs = function(urn) {
|
||||
var breadcrumbs = []
|
||||
var b = urn.split('/')
|
||||
b.shift();
|
||||
for(var i = 0; i < b.length; i++) {
|
||||
var updatedUrn = "/metadata#/dashboard/" + b[i]
|
||||
if(i === 0)
|
||||
{
|
||||
|
||||
breadcrumbs.push({title: b[i], urn: updatedUrn})
|
||||
}
|
||||
else
|
||||
{
|
||||
breadcrumbs.push({title: b[i], urn: updatedUrn})
|
||||
}
|
||||
}
|
||||
return breadcrumbs
|
||||
}
|
||||
|
||||
var setActiveTab = function(){
|
||||
$('#dashboardtabs a:last').tab("show");
|
||||
}
|
||||
|
||||
function refreshCfDatasets(user, page, size)
|
||||
{
|
||||
if (!user)
|
||||
return;
|
||||
|
||||
if (!page)
|
||||
page = 1;
|
||||
if (!size)
|
||||
size = 10;
|
||||
var datasetsUrl = '/api/v1/metadata/dataset/' + user + '?page=' + page + '&size=' + size;
|
||||
$.get(datasetsUrl, function(data) {
|
||||
if (data && data.status == "ok") {
|
||||
var currentPage = data.page;
|
||||
var totalPage = data.totalPages;
|
||||
if (currentPage == 1)
|
||||
{
|
||||
jiraController.set('cfFirst', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
jiraController.set('cfFirst', false);
|
||||
}
|
||||
if (currentPage == totalPage)
|
||||
{
|
||||
jiraController.set('cfLast', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
jiraController.set('cfLast', false);
|
||||
}
|
||||
jiraController.set('confidentialFieldsDatasets', data);
|
||||
jiraController.set('currentCfPage', data.page);
|
||||
if (data.datasets && data.datasets.length > 0)
|
||||
{
|
||||
jiraController.set('userNoConfidentialFields', false);
|
||||
}
|
||||
else
|
||||
{
|
||||
jiraController.set('userNoConfidentialFields', true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var jiraController = null;
|
||||
var hierarchy = '/jweiner';
|
||||
var breadcrumbs;
|
||||
var sortOptions = ['Assignee First', 'Jira Status First', 'Directory Path First'];
|
||||
var selectedUser = {
|
||||
'userId': 'jweiner',
|
||||
'displayName': 'jweiner',
|
||||
'headlessTicketsCompletion': 0,
|
||||
'totalHeadlessTickets': 0,
|
||||
'openedHeadlessTickets': 0,
|
||||
'closedHeadlessTickets': 0,
|
||||
'cfCompletion': 0,
|
||||
'cfTotalDatasets': 0,
|
||||
'cfConfirmedDatasets': 0,
|
||||
'url': '/metadata#/dashboard/jweiner'};
|
||||
setTimeout(setActiveTab, 500);
|
||||
|
||||
App.DashboardRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
jiraController = controller;
|
||||
breadcrumbs = genBreadcrumbs(hierarchy);
|
||||
jiraController.set('breadcrumbs', breadcrumbs);
|
||||
jiraController.set('selectedUser', selectedUser);
|
||||
jiraController.set('sortOptions', sortOptions);
|
||||
}
|
||||
});
|
||||
|
||||
App.UserRoute = Ember.Route.extend({
|
||||
setupController: function(controller, params) {
|
||||
if (params && params.user)
|
||||
{
|
||||
jiraController.set('ticketsInProgress', true);
|
||||
var confidentialUrl = 'api/v1/metadata/dashboard/' + params.user;
|
||||
var headlessTickets;
|
||||
var userTickets;
|
||||
$.get(confidentialUrl, function(data) {
|
||||
jiraController.set('ticketsInProgress', false);
|
||||
if (data && data.status == "ok") {
|
||||
jiraController.set('membersInProgress', true);
|
||||
jiraController.set('confidentialFieldsOwners', data.members);
|
||||
if (data.members && data.members.length > 0)
|
||||
{
|
||||
jiraController.set('userNoMembers', false);
|
||||
}
|
||||
else
|
||||
{
|
||||
jiraController.set('userNoMembers', true);
|
||||
}
|
||||
jiraController.set('currentConfidentialFieldsUser', data.currentUser);
|
||||
var breadcrumbs;
|
||||
if (data.currentUser.orgHierarchy)
|
||||
{
|
||||
breadcrumbs = genBreadcrumbs(data.currentUser.orgHierarchy);
|
||||
}
|
||||
else
|
||||
{
|
||||
var hierarchy = '/jweiner';
|
||||
breadcrumbs = genBreadcrumbs(hierarchy);
|
||||
}
|
||||
jiraController.set('breadcrumbs', breadcrumbs);
|
||||
|
||||
refreshCfDatasets(params.user, 1, 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
App.DashboardController = Ember.Controller.extend({
|
||||
cfFirst: false,
|
||||
cfLast: false,
|
||||
actions: {
|
||||
prevCfPage: function() {
|
||||
var cfInfo = this.get("confidentialFieldsDatasets");
|
||||
var user = this.get("currentConfidentialFieldsUser");
|
||||
if (cfInfo && user) {
|
||||
var currentPage = parseInt(cfInfo.page) - 1;
|
||||
if (currentPage > 0) {
|
||||
refreshCfDatasets(user.userName, currentPage, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
nextCfPage: function() {
|
||||
var cfInfo = this.get("confidentialFieldsDatasets");
|
||||
var user = this.get("currentConfidentialFieldsUser");
|
||||
if (cfInfo && user) {
|
||||
var currentPage = parseInt(cfInfo.page) + 1;
|
||||
var totalPages = cfInfo.totalPages;
|
||||
if (currentPage < totalPages) {
|
||||
refreshCfDatasets(user.userName, currentPage, 10);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery)
|
||||
Loading…
x
Reference in New Issue
Block a user