implement the confidential fields of metadata dashboard

This commit is contained in:
jbai 2016-08-23 17:19:33 -07:00 committed by Mars Lan
parent 5d3b534086
commit 2a4f281ba5
9 changed files with 772 additions and 6 deletions

View File

@ -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);

View 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));
}
}

View 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;
}
}

View 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;
}

View 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;
}

View 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" }}>
&larr; Prev
</a>
</li>
{{/unless}}
<li>
{{ confidentialFieldsDatasets.count }} datasets - page {{ confidentialFieldsDatasets.page }} of {{ confidentialFieldsDatasets.totalPages }}
</li>
{{#unless cfLast}}
<li class="next">
<a {{ action "nextCfPage" }}>
Next &rarr;
</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>
}

View File

@ -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>

View File

@ -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()

View 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)