Skip to content

Commit

Permalink
refactoring the way we handle sidebar opening events (#574)
Browse files Browse the repository at this point in the history
The way `v_summary` handles the loading of the sidebar
assumes there is only one type of sidebar view.

In light of the new "zoomin" view, we would have to extend and
generalize the way we load the sidebar, so as to be able to load both
the authorship and zoomin view using the same mechanism.

The design of the "event bus" is as such. The actual loading of the
tabs is done in the main app, and those functions usually have the form
`updateTabXXX()`, which write the corresponding information object into
`this.tabInfo` and does `this.tabActive='XXX';`. This will then load
the right tab in the sidebar.

To load the sidebar from without another component, the VueJS event
emitting mechanism is used. A function of the form  `openTabXXX()` is
used to call the component's `$emit()`. The main application then
handles the emitted message using the corresponding `updateTabXXX()`.

* Add highlighting to ramps (#544)

To be able to open up a "zoomed-in" view of the ramp, the user must
first be able to select part of the ramp to focus on.

Let's add a way for the user to highlight the range of the ramp to
focus on. This will later translate into the date range for the
"zoomed-in" view to display the relevant commits.

In this particular implementation, we use a global `drags` object as a
way of preventing user from highlighting on multiple ramp charts. E.g.
if a user mousedown on one ramp chart and mouseup on the other, the
second chart will be highlighted with the positions defined between the
two mouse events.

* Merge 'tabs' to get refactored v_authorship

commit b632566
Author: ongspxm <ongspxm@gmail.com>
Date:   Mon Feb 25 00:46:12 2019 +0800

    added TODO to remove change

commit 4bb21d6
Author: ongspxm <ongspxm@gmail.com>
Date:   Fri Feb 22 23:38:34 2019 +0800

    updated to use isTabActive instead of tabActive to trigger tab display

commit a7aeefd
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 22:39:18 2019 +0800

    fix lint

commit b813aa2
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 22:30:35 2019 +0800

    wrap everything within v-authorship

commit 7dbb41b
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 22:25:45 2019 +0800

    updateCount using document.getElementsByClassName

commit c66a3ee
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 15:53:22 2019 +0800

    wip. left with updateCount

commit 9e73331
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 15:49:48 2019 +0800

    move expand func to v_authorship

commit 3fcd62b
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 15:43:50 2019 +0800

    remove js for button update

commit 4fc1151
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 15:37:02 2019 +0800

    deactivating the tab

commit a387e19
Author: ongspxm <ongspxm@gmail.com>
Date:   Thu Feb 21 14:51:58 2019 +0800

    wip

* move call emitting to component func

* handle opening of tabs in main app

* refactoring ramps to their own component (#572)

Currently, the entire ramp template resides in `v_summary`. In light of
the "zoomin" tab view, we would have to reuse ramp chart view to
display the commits in the "zoomin" tab.

Let's refactor to move the ramp into its own component, so as to
support reuse in the "zoomin" tab view.

* fix lint

* fix: show min max date on authorship view

* lint

* [#554] Rename 'dashboard' instances to 'report' (#579)

The term 'report' and 'dashboard' are used throughout RepoSense to
refer to the same thing, the result after running analysis.

However, users may not understand the subtle differences between
these two terms. Instead, using a single term would help in
standardization and comprehensibility.

Let's rename all usage of 'dashboard' instances to the term 'report'
instead, as standardized in #220.

* Checkstyle: update addresses of DTD files #586

We are using the DTD files from http://checkstyle.sourceforge.net/
and http://puppycrawl.com/ in our config file of checkstyle.

However, due to security reason, checkstyle decided to remove DTDs from
above websites and ask users to use the DTD files from
https://checkstyle.org/[1].

Let's update the addresses of DTD files correspondingly.

As later version of the suppression DTD file has been released[2],
let's also update the DTD file to the latest version.

[1] Checkstyle removes DTDs from http://checkstyle.sourceforge.net:
checkstyle/checkstyle#6478

[2] Checkstyle Suppressions.xml example:
https://checkstyle.org/config_filters.html#SuppressionFilter_Examples

* [#540] Perform cloning in parallel with analyzing (#560)

Repos are processed sequentially, one at a time.

As cloning does not takes much processing power and analysis does not
take any network bandwidth, the two can be done in parallel to reduce
the total processing time.

Here are some test results to support the above hypothesis:
The test was performed using CS2103 AY1819S1 project repos on my local
machine. The average time taken to generate the report was measured
across 10 runs. Current code took 17 min 21s while new implementation
took 11 min 55s.

Let's clone the next repo in the list while the current repo is being
analyzed.

* [#465] Url: bookmark opened code view (#524)

Our report's url changes along with the state of the dashboard as a
mechanism to allow users to easily revisit her last view as well as
easily be shared with other people.

However, this was only limited to the chart view configuration, nothing
of the code view were part of the state being saved.

To allow users to easily restore their last reviewed code view, let's
also encode any opened code view into the url.

* [#510] Remove unused Checkstyle analysis feature (#597)

The checkstyle analysis feature was added to the code base in the
early stage of RepoSense, when there was some hope of running static
analysis over the code written by authors of the repositories.

As this feature has not been used since early stages(v1.0), and it
is also not in our immediate plans anymore, leaving it will
unnecessarily complicate the codebase.

Let's clean up the code base by removing this unused checkstyle
analysis feature.

* fix: codeview not opening

* update view opeing
  • Loading branch information
ongspxm committed Mar 19, 2019
1 parent a3931c3 commit 04e5cca
Show file tree
Hide file tree
Showing 47 changed files with 478 additions and 279 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -4,7 +4,7 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/08a3527378464ed4a5ad62e27f590d6a)](https://www.codacy.com/app/reposense/RepoSense?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=reposense/RepoSense&amp;utm_campaign=Badge_Grade)
[![deploy on_netlify](https://img.shields.io/badge/deploy-on_netlify-blue.svg)](https://reposense.netlify.com/)

RepoSense is a contribution analysis tool for Git repositories. It generates a static HTML dashboard including contribution information for each author in the repository.
RepoSense is a contribution analysis tool for Git repositories. It generates a static HTML report including contribution information for each author in the repository.
The features of the report includes:
* Visualization for contribution frequency
* Visualization for contribution amount
Expand Down
Binary file removed checkstyle-7.7-all.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions config/checkstyle/checkstyle.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">

<!--
This configuration file enforces rules for a modified version of the module's code standard at
Expand Down
4 changes: 2 additions & 2 deletions config/checkstyle/suppressions.xml
@@ -1,8 +1,8 @@
<?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://checkstyle.sourceforge.net/dtds/suppressions_1_1.dtd">
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">

<suppressions>
<suppress checks="JavadocType" files=".*Test\.java"/>
Expand Down
44 changes: 22 additions & 22 deletions docs/DeveloperGuide.md
Expand Up @@ -15,8 +15,8 @@ Thank you for your interest in contributing to RepoSense!
- [ReportGenerator](#reportgeneratormain)
- [System](#system)
- [Model](#model)
- [HTML Dashboard](#html-dashboard)
- [Dashboard Architecture](#dashboard-architecture)
- [HTML Report](#html-report)
- [Report Architecture](#report-architecture)
- [Javascript Files](#javascript-files)
- [JSON Report Files](#json-report-files)
- [Main](#main-mainjs)
Expand Down Expand Up @@ -62,7 +62,7 @@ Optionally, you can follow the [Using Checkstyle](UsingCheckstyle.md) document t
### Configuring the JavaScript coding style
Our project follows the [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript), the eslint configuration file is available at the root of the project. Please run a `npm run lint -- --fix frontend/src/**/*js` from the project root directory and fix all of the eslint errors before committing your code for final review.

Eslint and its accompaning modules can be installed through NPM, so do ensure that you got it [installed](https://www.npmjs.com/get-npm) if you are working on the dashboard.
Eslint and its accompaning modules can be installed through NPM, so do ensure that you got it [installed](https://www.npmjs.com/get-npm) if you are working on the report.

### Configuring Cypress for automated front-end testing
We use [Cypress](https://www.cypress.io/) for automated end-to-end front-end testing. <br/>
Expand Down Expand Up @@ -91,10 +91,10 @@ Named Arguments:
```
--help, -h Show help message.
--view [PATH], -v [PATH]
Starts a server to display the dashboard in the
Starts a server to display the report in the
provided directory. If used as a flag (with no
argument), generates a report and automatically
displays the dashboard.
displays the report.
--output PATH, -o PATH
The directory to output the report folder,
reposense-report. If not provided, the report
Expand Down Expand Up @@ -198,14 +198,14 @@ gradlew run -Dargs="-c ./configs/ -o output_path/ -s 21/10/2017 -u 21/11/2017 -f
1. uses `GitDownloader` API to download the repository from *GitHub*.
1. copies the template files into the designated output directory.
1. uses `CommitReporter` and `AuthorshipReporter` to produce the commit and authorship summary respectively.
1. generates the `JSON` files needed to generate the `HTML` dashboard.
1. generates the `JSON` files needed to generate the `HTML` report.


### System
`System` contains the classes that interact with the Operating System and external processes.
* [`CommandRunner`](/src/main/java/reposense/system/CommandRunner.java) creates processes that executes commands on the terminal. It consists of many *git* commands.
* [`LogsManager`](/src/main/java/reposense/system/LogsManager.java) uses the `java.util.logging` package for logging. The `LogsManager` class is used to manage the logging levels and logging destinations. Log messages are output through: `Console` and to a `.log` file.
* [`DashboardServer`](/src/main/java/reposense/system/DashboardServer.java) starts a server to display the dashboard on the browser. It depends on the `net.freeutils.httpserver` package.
* [`ReportServer`](/src/main/java/reposense/system/ReportServer.java) starts a server to display the report on the browser. It depends on the `net.freeutils.httpserver` package.


### Model
Expand All @@ -219,30 +219,30 @@ gradlew run -Dargs="-c ./configs/ -o output_path/ -s 21/10/2017 -u 21/11/2017 -f
- `ReportGenerator` to determine the directory to output the report.


## HTML Dashboard
The source files for the dashboard is located in [`frontend/src`](../frontend/src) and is built by [spuild](https://github.com/ongspxm/spuild2) before being packaged into the JAR file to be extracted as part of the report.
## HTML Report
The source files for the report is located in [`frontend/src`](../frontend/src) and is built by [spuild](https://github.com/ongspxm/spuild2) before being packaged into the JAR file to be extracted as part of the report.

The main HTML file is generated from [`frontend/src/index.jade`](../frontend/src/index.jade).

[Vue](https://vuejs.org/v2/api/) (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is heavily ultilized in the dashboard to dynamically update the information in the various views. (Style guide available [here](https://vuejs.org/v2/style-guide/)).
[Vue](https://vuejs.org/v2/api/) (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is heavily utilized in the report to dynamically update the information in the various views. (Style guide available [here](https://vuejs.org/v2/style-guide/)).

![dashboard screenshot](images/dashboard.png)
![report screenshot](images/report-summary.png)

### Dashboard Architecture
![dashboard architecture](images/dashboard-architecture.png)
### Report Architecture
![report architecture](images/report-architecture.png)

The main Vue object (`window.app`) is responsible for the loading of the dashboard (through `summary.json`). Its `repos` attribute is tied to the global `window.REPOS`, and is passed into the various other modules when the information is needed.
The main Vue object (`window.app`) is responsible for the loading of the report (through `summary.json`). Its `repos` attribute is tied to the global `window.REPOS`, and is passed into the various other modules when the information is needed.

`window.app` is broken down into two main parts
- the summary view
- and the tabbed interface

Summary view act as the main dashboard which shows the various calculations. </br>
Summary view act as the main report which shows the various calculations. </br>
Tabbed interface is responsible for loading various modules such as authorship to display additional information.

### Javascript Files
- [**main.js**](../frontend/src/static/js/main.js) - main controller that pushes content into different modules
- [**api.js**](../frontend/src/static/js/api.js)- loading and parsing of the dashboard content
- [**api.js**](../frontend/src/static/js/api.js)- loading and parsing of the report content
- [**v_summary.js**](../frontend/src/static/js/v_summary.js) - module that supports the ramp chart view
- [**v_authorship.js**](../frontend/src/static/js/v_authorship.js) - module that supports the authorship view

Expand All @@ -254,9 +254,9 @@ Tabbed interface is responsible for loading various modules such as authorship t
### Main (main.js)
This contains the logic for main VueJS object, `window.app`, which is responsible for passing the necessary data into the relevant modules to be loaded.

`v_summary` and `v_authorship` are components which will be embedded into dashboard and will render the corresponding content based on the data passed into it from the main `window.app`.
`v_summary` and `v_authorship` are components which will be embedded into report and will render the corresponding content based on the data passed into it from the main `window.app`.

#### Loading of dashboard information
#### Loading of report information
The main Vue object depends on the `summary.json` data to determine the right `commits.json` files to load into memory. This is handled by `api.js` which loads the relevant file information from the network files if it is available, otherwise a report archive, `archive.zip`, have to be used.

Once the relevant `commit.json` files are loaded, all the repo information will be passed into `v_summary` to be loaded in the summary view as the relevant ramp charts.
Expand All @@ -265,15 +265,15 @@ Once the relevant `commit.json` files are loaded, all the repo information will
Most activity or actions should happen within the module itself, but in the case where there is a need to spawn or alter the view of another module, an event is emitted from the first module to the main Vue object (`window.app`), which then handles the data received and passes it along to the relevant modules.

#### Hash link
Other than the global main Vue object, another global variable we have is the `window.hashParams`. This object is reponsible for generating the relevant permalink for a specific view of the summary module for the dashboard.
Other than the global main Vue object, another global variable we have is the `window.hashParams`. This object is reponsible for generating the relevant permalink for a specific view of the summary module for the report.

### Data loader (api.js)
This is the module that is in charged of loading and parsing the data files generated as part of the report.

#### Loading from ZIP file
Due to security design, most modern browsers (e.g. Chrome) do not allow web pages to obtain local files using the directory alone. As such, a ZIP archive of the report information will be produced alongside the report generation.

This archive will be used in place of the network files to load information into the dashboard, in the case when the network files are unavailable.
This archive will be used in place of the network files to load information into the report, in the case when the network files are unavailable.

The API module will be handling all request for all the JSON data files. If the network file is not available, the files will be obtained from the zip archive provided.

Expand All @@ -285,7 +285,7 @@ For the basic skeleton of `window.REPOS`, refer to the generated `summary.json`
### Summary View (v_summary.js)
The `v_summary` module is in charge of loading the ramp charts from the corresponding `commits.json`.

![summary architecture](images/dashboard-architecture-summary.png)
![summary architecture](images/report-architecture-summary.png)

#### Initializing the data for the ramp charts
The summary module is activated after the information is loaded from the main Vue.JS object. At creation, the `repo` attribute is populated with the `window.REPOS` object, which contains information loaded from `summary.json`.
Expand All @@ -299,7 +299,7 @@ For ramps between the date ranges, the slices will be selected and it will be pr
### Authorship View (v_authorship.js)
The authorship module retrieves the relevant information from the corresponding `authorship.json` file if it is not yet loaded. If it has been loaded, the data will be written into `window.REPOS` and be read from there instead.

![authorship architecture](images/dashboard-architecture-authorship.png)
![authorship architecture](images/report-architecture-authorship.png)

#### Showing relevant information by authors
The files will be filtered, picking only files the selected author has written in. The lines are then split into chunks of "touched" and "untouched" code to be displayed in the tab view which will be popped up on the right side of the screen.
4 changes: 2 additions & 2 deletions docs/UserGuide.md
Expand Up @@ -50,7 +50,7 @@ As the report consist of static pages, it can be viewed using a Web Browser, and

Here is an example of how the report looks like:

![report](images/report.png)
![report](images/report-features.png)

It consists of three main parts: the [_Chart Panel_](#chart-panel), the [_Code Panel_](#code-panel), and the [_Tool Bar_](#tool-bar), each of which is explained in the sections below.

Expand Down Expand Up @@ -113,7 +113,7 @@ The `Tool Bar` at the top provides a set of configuration options that control t
Notes:<br>
[1] **`Repo/Branch`**: the repo/branch name is constructed as `ORGANIZATION_REPOSITORY_BRANCH` e.g., `resposense_reposense_master`

**Bookmarking a specific toolbar setting**: The URL changes according to the toolbar configuration. You can save a specific configuration of the report by bookmarking the url (using browser functionality).
**Bookmarking a specific toolbar setting and the opened code panel**: The URL changes according to the toolbar configuration and opened code panel viewed. You can save a specific configuration of the report by bookmarking the url (using browser functionality).

<hr>

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
13 changes: 5 additions & 8 deletions frontend/src/index.pug
Expand Up @@ -27,7 +27,8 @@ html
.summary-status(v-if="loadedRepo<repoLength") Loading repos ... {{ loadedRepo }} / {{ repoLength }}
v_summary(
v-bind:repos="getUsers()",
v-on:view-authorship="updateTabAuthorship"
v-on:view-authorship="updateTabAuthorship",
v-on:get-dates="receiveDates"
)
.timestamp-footer
span Generated by &nbsp;
Expand All @@ -37,7 +38,7 @@ html

#tabs-wrapper(v-if="isTabActive")
#tab-resize(onmousedown="registerMouseMove()")
.tab-close(v-on:click="isTabActive=false")
.tab-close(v-on:click="isTabActive=false;")
i.fas.fa-caret-right
.tab-content
.tab-panes
Expand Down Expand Up @@ -130,10 +131,7 @@ html
.summary-chart__title--name {{ user.displayName }}
a(
title="click to view author's code",
v-on:click="$emit('view-authorship', \
{author:user.name, repo:user.repoName, name:user.displayName, location:repo[0].location, \
minDate:minDate, maxDate:maxDate, totalCommits:user.totalCommits, \
filesLinesObj:user.fileFormatContribution})"
v-on:click="openTabAuthorship(user, repo)"
)
i.summary-chart__title--button.fas.fa-code
a(
Expand Down Expand Up @@ -177,8 +175,7 @@ html

vuetemplate#v_authorship
#authorship
// TODO: remove in #524
.toolbar(v-if="info.totalCommits > 0")
.toolbar(v-if="hasCommits(info)")
a(v-if="activeFilesCount === 0", v-on:click="expandAll(true)") Expand all
a(v-else, v-on:click="expandAll(false)") Collapse all
.title
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/static/js/api.js
Expand Up @@ -32,7 +32,7 @@ window.api = {

return loadJSON(`${REPORT_DIR}/summary.json`)
.then((data) => {
window.app.creationDate = data.dashboardGeneratedTime;
window.app.creationDate = data.reportGeneratedTime;

const names = [];
data.repos.forEach((repo) => {
Expand Down
55 changes: 50 additions & 5 deletions frontend/src/static/js/main.js
Expand Up @@ -24,7 +24,12 @@ window.decodeHash = function decodeHash() {
.forEach((param) => {
const [key, val] = param.split('=');
if (key) {
hashParams[key] = decodeURIComponent(val);
try {
hashParams[key] = decodeURIComponent(val);
} catch (error) {
this.userUpdated = false;
this.isLoading = false;
}
}
});
window.hashParams = hashParams;
Expand Down Expand Up @@ -162,19 +167,52 @@ window.app = new window.Vue({
}
},

updateTabAuthorship(obj) {
this.deactivateTab();
this.tabInfo.tabAuthorship = Object.assign({}, obj);
// handle opening of sidebar //
activateTab(tabName) {
// changing isTabActive to trigger redrawing of component
this.isTabActive = false;
if (document.getElementById('tabs-wrapper')) {
document.getElementById('tabs-wrapper').scrollTop = 0;
}

this.isTabActive = true;
this.isCollapsed = false;
this.tabType = tabName;
},

updateTabAuthorship(obj) {
this.tabInfo.tabAuthorship = Object.assign({}, obj);
this.activateTab('authorship');
},

this.tabType = 'authorship';
updateTabZoomin(obj) {
this.tabInfo.tabZoomin = Object.assign({}, obj);
this.activateTab('zoomin');
},
renderAuthorShipTabHash(minDate, maxDate) {
const hash = window.hashParams;
const info = {
author: hash.tabAuthor,
repo: hash.tabRepo,
minDate,
maxDate,
};
const tabInfoLength = Object.values(info).filter((x) => x).length;
if (Object.keys(info).length === tabInfoLength) {
this.updateTabAuthorship(info);
} else if (hash.tabOpen === 'false' || tabInfoLength > 2) {
window.app.isTabActive = false;
}
},

generateKey(dataObj) {
return JSON.stringify(dataObj);
},

receiveDates(dates) {
const [minDate, maxDate] = dates;
this.renderAuthorShipTabHash(minDate, maxDate);
},
},
components: {
v_summary: window.vSummary,
Expand All @@ -183,12 +221,19 @@ window.app = new window.Vue({
},
created() {
this.updateReportDir();
window.decodeHash();
},
updated() {
this.$nextTick(() => {
if (window.$('tabs-wrapper')) {
window.$('tabs-wrapper').style.flex = `0 0 ${flexWidth * 100}%`;
}
});
if (!this.isTabActive) {
window.removeHash('tabAuthor');
window.removeHash('tabRepo');
window.addHash('tabOpen', this.isTabActive);
window.encodeHash();
}
},
});

0 comments on commit 04e5cca

Please sign in to comment.