Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rename Dashboad to FileDashboard
Browse files Browse the repository at this point in the history
* Add dirs_count to first row
* Add unique copyright holders to first row
* Add file/mime type chart to second row
* Add copyright holders chart to second row

Addresses: #366

Signed-off-by: Steven Esser <[email protected]>
steven-esser committed Apr 24, 2019

Verified

This commit was signed with the committer’s verified signature.
romhml Romain Hamel
1 parent 033eb07 commit b81e244
Showing 6 changed files with 258 additions and 343 deletions.
2 changes: 1 addition & 1 deletion assets/app/css/main.css
Original file line number Diff line number Diff line change
@@ -548,7 +548,7 @@ div.dataTables_scrollHead th:first-child {
width: 100%;
}

#tab-dashboard{
#tab-file-dashboard{
background-color: #FAFAFB;
}

295 changes: 0 additions & 295 deletions assets/app/js/controllers/dashboard.js

This file was deleted.

227 changes: 227 additions & 0 deletions assets/app/js/controllers/fileDashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
#
# Copyright (c) 2017 - 2019 nexB Inc. and others. All rights reserved.
# https://nexb.com and https://github.com/nexB/scancode-workbench/
# The ScanCode software is licensed under the Apache License version 2.0.
# ScanCode is a trademark of nexB Inc.
#
# You may not use this software except in compliance with the License.
# You may obtain a copy of the License at: http://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.
#
*/

const Sequelize = require('sequelize');
const Progress = require('../helpers/progress');
const Controller = require('./controller');

const LEGEND_COLORS = [
'#B3F82F',
'#FFA330',
'#EC2D95',
'#2BE189',
'#9095F0',
'#2AD0D8',
'#AAB2BD',
'#3499DB'
];

const LEGEND_LIMIT = 8;

/**
* The view responsible for displaying the summary information from ScanCode
* Scan data
*/
class FileDashboard extends Controller {
constructor(dashboardId, workbenchDB) {
super(dashboardId, workbenchDB);

this.totalFilesScanned = $('#total-files').find('.title');
this.totalDirsScanned = $('#total-dirs').find('.title');
this.uniqueHolders = $('#unique-holders').find('.title');

// First row
this.totalFilesProgressbar =
new Progress('#total-files .title', {size: 25});
this.totalDirsProgressbar =
new Progress('#total-dirs .title', {size: 25});
this.uniqueHoldersProgressbar =
new Progress('#unique-holders .title', {size: 25});

// Second row
this.sourceLanguageChartProgressbar =
new Progress('#source-chart .content', {size: 50});
this.fileTypeChartProgressbar =
new Progress('#license-category-chart .content', {size: 50});
this.holdersChartProgressbar =
new Progress('#holders-chart .content', {size: 50});

this.sourceLanguageChart = c3.generate({
bindto: '#source-chart .chart',
data: {
columns: [],
type: 'pie',
order: 'desc',
},
color: {
pattern: LEGEND_COLORS
},
});

this.fileTypeChart = c3.generate({
bindto: '#file-type-chart .chart',
data: {
columns: [],
type: 'pie',
order: 'desc',
},
color: {
pattern: LEGEND_COLORS
}
});

this.holdersChart = c3.generate({
bindto: '#holders-chart .chart',
data: {
columns: [],
type: 'pie',
order: 'desc',
},
color: {
pattern: LEGEND_COLORS
}
});
}

reload() {
this.needsReload(false);

// Get # files, # dirs scanned at a certain path
this.totalFilesProgressbar.showIndeterminate();
this.totalDirsProgressbar.showIndeterminate();
this.db().sync
.then((db) => db.File.findOne({where: {path: this.selectedPath()}}))
.then((row) => {
const files_count = row.type === 'directory' ? row.files_count : 1;
const dirs_count = row.type === 'directory' ? row.dirs_count : 0;
this.totalFilesScanned.text(files_count);
this.totalDirsScanned.text(dirs_count);
this.totalFilesProgressbar.hide();
this.totalDirsProgressbar.hide();
});

// Get total unique copyright holders detected at a certain path
this.uniqueHoldersProgressbar.showIndeterminate();
this.db().sync
.then((db) => db.File.findAll({where: {path: {$like: `${this.selectedPath()}%`}}}))
.then((files) => files.map((val) => val.id))
.then((fileIds) => this.db().sync
.then((db) => db.Copyright.findAll({where: {fileId: fileIds}}))
.then((copyrights) => copyrights.map((val) => val.holders))
.then((holders) => holders.map((val) => val.pop()))
.then((holders) => this.uniqueHolders.text(new Set(holders).size)))
.then(() => this.uniqueHoldersProgressbar.hide());

// Get unique programming languages detected
this.sourceLanguageChartData = this.db().sync
.then((db) => db.File.findAll({where: {path: {$like: `${this.selectedPath()}%`}}}))
.then((files) => files.map((val) => val.programming_language ? val.programming_language : 'No Value Detected'))
.then((langs) => FileDashboard.formatData(langs))
.then((langs) => FileDashboard.limitData(langs, LEGEND_LIMIT));

// Get file (mime) type data
this.fileTypeChartData = this.db().sync
.then((db) => db.File.findAll({where: {path: {$like: `${this.selectedPath()}%`}}}))
.then((files) => files.map((val) => val.mime_type ? val.mime_type : 'No Value Detected'))
.then((types) => FileDashboard.formatData(types))
.then((types) => FileDashboard.limitData(types, LEGEND_LIMIT));


this.holdersChartData = this.db().sync
.then((db) => db.File.findAll({where: {path: {$like: `${this.selectedPath()}%`}}}))
.then((files) => files.map((val) => val.id))
.then((fileIds) => this.db().sync
.then((db) => db.Copyright.findAll({where: {fileId: fileIds}}))
.then((copyrights) => copyrights.map((val) => val.holders ? val.holders : 'No Value Detected'))
.then((holders) => FileDashboard.formatData(holders))
.then((holders) => FileDashboard.limitData(holders, LEGEND_LIMIT)));
}

redraw() {
if (this.needsReload()) {
this.reload();
}

// Get unique programming languages detected
this.sourceLanguageChartProgressbar.showIndeterminate();
this.sourceLanguageChartData
.then((data) => this.sourceLanguageChart.load({
columns: data,
unload: true,
done: () => {
this.sourceLanguageChartProgressbar.hide();
this.sourceLanguageChart.hide('No Value Detected');
this.sourceLanguageChart.flush();
}
}));

// Get license categories detected
this.fileTypeChartProgressbar.showIndeterminate();
this.fileTypeChartData
.then((data) => this.fileTypeChart.load({
columns: data,
unload: true,
done: () => {
this.fileTypeChartProgressbar.hide();
this.fileTypeChart.hide('No Value Detected');
this.fileTypeChart.flush();
}
}));

// Get license keys detected
this.holdersChartProgressbar.showIndeterminate();
this.holdersChartData
.then((data) => this.holdersChart.load({
columns: data,
unload:true,
done: () => {
this.holdersChartProgressbar.hide();
this.holdersChart.hide('No Value Detected');
this.holdersChart.flush();
}
}));
}

static limitData(data, limit) {
// TODO: Use partitioning (like in quicksort) to find top "limit"
// more efficiently.
// Sort data by count
return data.sort((a,b) => (a[1] > b[1]) ? 1 : -1)
.map((dataPair, i) => {
if (data.length - i >= limit) {
return ['other', dataPair[1]];
} else {
return dataPair;
}
});
}

// Formats data for c3: [[key1, count1], [key2, count2], ...]
static formatData(names) {
// Sum the total number of times the name appears
const count = {};
$.each(names, (i, name) => {
count[name] = count[name] + 1 || 1;
});

// Transform license count into array of objects with license name & count
return $.map(count, (val, key) => {
return [[key, val]];
});
}
}

module.exports = FileDashboard;
1 change: 1 addition & 0 deletions assets/app/js/models/file.js
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ module.exports = function(sequelize, DataTypes) {
sha1: DataTypes.STRING,
md5: DataTypes.STRING,
files_count: DataTypes.INTEGER,
dirs_count: DataTypes.INTEGER,
mime_type: DataTypes.STRING,
file_type: DataTypes.STRING,
programming_language: DataTypes.STRING,
18 changes: 9 additions & 9 deletions assets/app/js/renderer.js
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ const Progress = require('./helpers/progress');

const DejaCodeExportDialog = require('./controllers/dejacodeExportDialog');
const ConclusionDialog = require('./controllers/conclusionDialog');
const Dashboard = require('./controllers/dashboard');
const FileDashboard = require('./controllers/fileDashboard');
const BarChart = require('./controllers/barChart');
const JsTree = require('./controllers/jsTree');
const ScanDataTable = require('./controllers/scanDataTable');
@@ -45,7 +45,7 @@ $(document).ready(() => {
// Create default values for all of the data and ui classes
let workbenchDB = new WorkbenchDB();

const dashboard = new Dashboard('#tab-dashboard', workbenchDB);
const fileDashboard = new FileDashboard('#tab-file-dashboard', workbenchDB);

const barChart = new BarChart('#tab-barchart', workbenchDB)
.on('bar-clicked', (attribute, value) => {
@@ -126,7 +126,7 @@ $(document).ready(() => {
const showScanDataButton = $('#show-tab-scandata');
const showConclusionButton = $('#show-tab-conclusion');
const showBarChartButton = $('#show-tab-barchart');
const showDashboardButton = $('#show-tab-dashboard');
const showFileDashboardButton = $('#show-tab-file-dashboard');
const showWelcomePageButton = $('#show-tab-welcomepage');

// Import a ScanCode JSON resutls file
@@ -155,9 +155,9 @@ $(document).ready(() => {
barChart.redraw();
});

showDashboardButton.click(() => {
showFileDashboardButton.click(() => {
splitter.show();
dashboard.redraw();
fileDashboard.redraw();
});

showWelcomePageButton.click(() => {
@@ -184,20 +184,20 @@ $(document).ready(() => {
ipcRenderer.on('zoom-in', zoomIn);
ipcRenderer.on('zoom-out', zoomOut);

// Opens the dashboard view when the app is first opened
// Opens the Welcome Page view when the app is first opened
showWelcomePageButton.trigger('click');

function updateViewsByPath(path) {
// Update all the views with the given path string
$('#dashboard-title-text').text('Dashboard - ' + path);
$('#file-dashboard-title-text').text('File Info Dashboard - ' + path);
scanDataTable.columns(0).search(path);

conclusionDialog.selectedPath(path);
dejaCodeExportDialog.selectedPath(path);
jstree.selectedPath(path);
scanDataTable.selectedPath(path);
conclusionsTable.selectedPath(path);
dashboard.selectedPath(path);
fileDashboard.selectedPath(path);
barChart.selectedPath(path);

redrawCurrentView();
@@ -285,7 +285,7 @@ $(document).ready(() => {
jstree.db(workbenchDB);
scanDataTable.db(workbenchDB);
conclusionsTable.db(workbenchDB);
dashboard.db(workbenchDB);
fileDashboard.db(workbenchDB);
barChart.db(workbenchDB);

// Reload the jstree, then trigger the current view to reload.
58 changes: 20 additions & 38 deletions index.html
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@
</button>
</li>
<li>
<button class="btn btn-sidebar" id="show-tab-dashboard" data-toggle="tab" data-target="#tab-dashboard" data-placement="right" title="Dashboard View">
<button class="btn btn-sidebar" id="show-tab-file-dashboard" data-toggle="tab" data-target="#tab-file-dashboard" data-placement="right" title="File Info Dashboard">
<i class="fa fa-tachometer" aria-hidden="true"></i>
</button>
</li>
@@ -152,49 +152,41 @@ <h4>Additional Help and Documentation:</h4>
<table class="scandata-table display table table-striped table-bordered dataTable no-footer" cellspacing="0" width="100%" ></table>
</div>

<!-- Dashboard Tab -->
<div class="tab-pane container" id="tab-dashboard">
<div id="dashboard-container">
<div id="dashboard-title">
<h2 id="dashboard-title-text">Dashboard</h2>
<!-- File Dashboard Tab -->
<div class="tab-pane container" id="tab-file-dashboard">
<div id="file-dashboard-container">
<div id="file-dashboard-title">
<h2 id="file-dashboard-title-text">File Info Dashboard</h2>
</div>
<div id="dashboard-view">
<div id="file-dashboard-view">
<div class="row">
<div class="col-lg-3 col-sm-6 col-xs-12">
<div class="col-sm-4">
<div class="card" id="total-files">
<div class="header">
<h3 class="title">0</h3>
<p class="category">Files Scanned</p>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12">
<div class="card" id="unique-licenses">
<div class="header">
<h3 class="title">0</h3>
<p class="category">Unique Licenses Detected</p>
<p class="category">Total Number of Files</p>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12">
<div class="card" id="unique-copyrights">
<div class="col-sm-4">
<div class="card" id="total-dirs">
<div class="header">
<h3 class="title">0</h3>
<p class="category">Unique Copyrights Detected</p>
<p class="category">Total Number of Directories</p>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12">
<div class="card" id="total-packages">
<div class="col-sm-4">
<div class="card" id="unique-holders">
<div class="header">
<h3 class="title">0</h3>
<p class="category">Packages Detected</p>
<p class="category">Unique Copyright Holders Detected</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-sm-6 col-xs-12" id="source-chart">
<div class="col-sm-4" id="source-chart">
<div class="card">
<div class="header">
<p class="category">Programming Languages</p>
@@ -204,30 +196,20 @@ <h3 class="title">0</h3>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12" id="license-category-chart">
<div class="card">
<div class="header">
<p class="category">License Categories</p>
</div>
<div class="content">
<div class="chart"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12" id="license-key-chart">
<div class="col-sm-4" id="file-type-chart">
<div class="card">
<div class="header">
<p class="category">License Keys</p>
<p class="category">File Types</p>
</div>
<div class="content">
<div class="chart"></div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-6 col-xs-12" id="packages-type-chart">
<div class="col-sm-4" id="holders-chart">
<div class="card">
<div class="header">
<p class="category">Package Types</p>
<p class="category">Copyright Holders</p>
</div>
<div class="content">
<div class="chart"></div>

0 comments on commit b81e244

Please sign in to comment.