Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] web interface for DSpot #847

Merged
merged 27 commits into from
Aug 9, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
57bf7d3
Feat: add basic layout for webinterface
Jul 23, 2019
6042944
Feat&Fix: remove node nodemodules, update webpage
Aug 5, 2019
f8bb64f
Feat: add Dockerfile for webapp
Aug 5, 2019
55a83eb
Update README.md
monperrus Aug 5, 2019
2381fd6
Fix: remove docker file
Aug 5, 2019
f338b92
Merge branch 'web' of https://github.com/Tailp/dspot into web
Aug 5, 2019
4bb195d
Fix: hide UI selector(always Pitmutant) and branch(always master) choice
Aug 5, 2019
55bf1e8
Fix: default master failed, revert changes
Aug 5, 2019
fafd8ec
Fix: git branch always master
Aug 5, 2019
2693cbd
up
Aug 5, 2019
bdf133b
Feat: add screenshoots to readme
Aug 5, 2019
d73a858
Fix: attempt to fix adding screenshots
henry-lp Aug 5, 2019
91d6460
Fix: make image links works
henry-lp Aug 5, 2019
3b2695e
Fix: add comments to screenshots
Aug 6, 2019
db04a08
Fix: add comments for screenshots
Aug 6, 2019
b2f680c
Fix: Merge resolve conflict
Aug 6, 2019
7eb5baa
Fix: remove
Aug 6, 2019
a00e85d
Fix: add again
Aug 6, 2019
163be46
Fix: pics , readme, comments, ack screen and html comments
Aug 6, 2019
c7149d3
Feat: add temporary link to webapp
Aug 7, 2019
3e4fe86
Fix: fix link
Aug 7, 2019
b6d3ed9
Fix: add page title, hide TODO link, fix email validation, alerts
Aug 7, 2019
249662b
Update README.md
monperrus Aug 8, 2019
828d7e4
Update README.md
monperrus Aug 8, 2019
631413b
Fix: update pic1
henry-lp Aug 8, 2019
f169491
Fix: update pic1 and pic4
Aug 8, 2019
1e963bf
Merge branch 'web' of https://github.com/Tailp/dspot into web
Aug 8, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions dspot-web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Introduction

This is a prototype web interface of Dspot, inspired from [CommitGuru](http://commit.guru/).

henry-lp marked this conversation as resolved.
Show resolved Hide resolved
Author: Henry Luong

## Screenshots

TODO add screenshots and explanation.

## Running

```
cd dspot-web
npm install --no-optional
npm run-script start
```

## Screenshots

### Front page
![Pic 1](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic1.png)
henry-lp marked this conversation as resolved.
Show resolved Hide resolved
henry-lp marked this conversation as resolved.
Show resolved Hide resolved
![Pic 2](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic2.png)
### All amplified repos page
![Pic 3](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic3.png)
### Demo submission

A repo has been submitted

![Pic 4](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic4.png)
henry-lp marked this conversation as resolved.
Show resolved Hide resolved

Display pending status on repos page

![Pic 5](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic5.png)
henry-lp marked this conversation as resolved.
Show resolved Hide resolved

When done, specific repo page display details

![Pic 6](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic6.png)
henry-lp marked this conversation as resolved.
Show resolved Hide resolved
![Pic 7](https://github.com/Tailp/dspot/blob/web/dspot-web/screenshots/pic7.png)

## Implementation

It is built by using MEAN (Mongodb,Express,AngularJS and Nodejs) stack, therefore it will be fetching data from database Mongodb and dynamically represent the data on the templated webpages with AngularJS for the Front-End part. Routing on the Back-End will be done by Nodejs and Expressjs to handle requests from the client and communication with the database.
MongoDB will be saving the state ("error","pending","old","success") of the request for REST. Mail will be sent using gmail when done running.

43 changes: 43 additions & 0 deletions dspot-web/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require("body-parser");

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use("/public", express.static(__dirname + "/public"));

// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;
90 changes: 90 additions & 0 deletions dspot-web/bin/www
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env node

/**
* Module dependencies.
*/

var app = require('../app');
var debug = require('debug')('server:server');
var http = require('http');

/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
* Create HTTP server.
*/

var server = http.createServer(app);

/**
* Listen on provided port, on all network interfaces.
*/

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
* Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}

/**
* Event listener for HTTP server "error" event.
*/

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

/**
* Event listener for HTTP server "listening" event.
*/

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
3 changes: 3 additions & 0 deletions dspot-web/controllers/data/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"records": [{"repoName":"travisplay","data":[0, 20, 30]},{"repoName":"repairnator","data":[10, 0, 30]},{"repoName":"dspot","data":[10, 20, 30]}]
}
192 changes: 192 additions & 0 deletions dspot-web/controllers/methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Mongodb
const MONGODB_HOST = "mongodb://localhost:27017" || process.env.MONGODB_HOST;
const dbName = "Dspot" || process.env.MONGODB_NAME;
const colName = "AmpRecords" || process.env.MONGODB_COLNAME;
const MongoClient = require('mongodb').MongoClient;
// ActiveMQ
const stompit = require('stompit');
const activemq_queuename = process.env.ACTIVEMQ_QUEUENAME || "Dpipeline";;
var connectOptions = {
'host': process.env.ACTIVEMQ_HOSTNAME || 'localhost',
'port': process.env.ACTIVEMQ_PORT || 61613,
'connectHeaders': {
'host': '/',
'heart-beat': '5000,5000'
},
'alwaysConnected': true
};

// Others
const assert = require('assert');
const async = require("async");

/**
* Extract the request url path and fetch the corresponding page and
* send it to the user
*/
function get_page(req, res, next) {
var path = ''
if (req.originalUrl == '/') {
path = 'pages/index.html'
} else {
path = 'pages' + req.originalUrl + '.html'
}
res.sendFile(path, { root: __dirname });
}

function fetchData(colName, query, limit, res) {
// Database Name
/* query = {};
query["repoName"] = reqslug; */
if (query == undefined) {
query = {};
}
const dbName = "Dspot" //process.env.MONGODB_NAME;
MongoClient.connect(MONGODB_HOST, { useNewUrlParser: true }, function(err, client) {
assert.equal(null, err);
const db = client.db(dbName);
console.log("Connected to mongo");

if (limit != undefined) {
db.collection(colName).find(query,{projection:{_id: 0,"Email":0}}).sort({ Date: -1 }).limit(limit).toArray(function(err, result) {
if (err) {
res.json(err);
} else {
/*console.log(result)*/
res.json(result);
}
});
} else {
db.collection(colName).find(query,{projection:{_id: 0,"Email":0}}).sort({ Date: -1 }).toArray(function(err, result) {
if (err) {
console.log(err);
res.json(err);
} else {
/*console.log(result);*/
res.json(result);
}
});
}
client.close();
});
}

/**
* Send message to ActiveMQ queue
* @param message is a string
*/
function sendMessageToActiveMQ(message) {
stompit.connect(connectOptions, (err, client) => {
var queueName = activemq_queuename;
const frame = client.send({ destination: queueName});
frame.write(message);
frame.end();
console.log("Message sended to " + queueName)
client.disconnect();
});
}

/**
* This fetch the template page for any repository
* Data will be sent over later for the specific repo
*/
exports.get_reposTemplatePage = function(req, res, next) {
console.log("Getting repos template page");
res.sendFile('pages/reposTemplate.html', { root: __dirname });
}

/**
* Fetch data, give slug and branch, return result for both
* Pitmutant- and JacocoSelector
*/
exports.get_repoInfoData = function(req, res, next) {
var query = {};
query["RepoSlug"] = req.params.user + "/" + req.params.reponame;
query["RepoBranch"] = req.params.branchname;

fetchData('AmpRecords', query, undefined, res);
}

/**
* For the start page fetch data for displaying 3 most
* recent scanned repos.
*/
exports.get_ReposData = function(req, res, next) {
console.log("getting most 3 recent repos data");
/* res.sendFile( "." + req.originalUrl,{root: __dirname }); */
/* Check if the requested data is which selector otherwise take 3 most*/
if (req.params.state == "recent") {
fetchData('AmpRecords', {"State": "recent"}, 3, res);
} else if (req.params.state == "All") { /*Only take recent and pending state*/
fetchData('AmpRecords',{$or:[{"State":{$eq:"recent"}},{"State":{$eq:"pending"}}]},undefined,res);
}
}

/**
* THis should be removed later. UniqueRecords is removed.
*/
exports.get_reposInfoData = function(req, res, next) {
console.log("getting all unique data");
fetchData('uniqueRecords', {}, undefined, res);
}

/**
* When someone submit at the home page this function
* will check if there is already a unhandled request
* previously by checking if there is a pending state
* document in the database. If not it will submit a
* new doc with pending state with the submitted information
*/
exports.post_submitRepo = function(req, res, next) {
const url = require('url');

let repoSlug = url.parse(req.body.repo.url).pathname.substring(1);
/*let repoBranch = req.body.repo.branch;*/
let repoBranch = "master" /*Always master - will be removed in the future*/
let selector = req.body.dspot.selector;
/*Constructing query*/
var query = {};
query["RepoSlug"] = repoSlug;
query["RepoBranch"] = repoBranch;
query["State"] = "pending";
query["Email"] = req.body.email;

var ampOptions = {};
ampOptions['test-criterion'] = selector;
query["AmpOptions"] = ampOptions;

MongoClient.connect(MONGODB_HOST, { useNewUrlParser: true }, function(err, client) {
assert.equal(null, err);
const db = client.db(dbName);
console.log("Connected to mongo");

// This fetch the secret associated with the slug and check it
db.collection(colName).findOne(query, async function(err, result) {
if (err) {
console.log(err);
} else {
if (result == null) {
console.log("Proceed initializing a pending document");

var datetime = new Date().toISOString().split('.')[0]+"Z";

query["Date"] = datetime;
await db.collection(colName).insertOne(query, function(err, res) {
if (err) throw err;
console.log("1 document inserted");
});
sendMessageToActiveMQ(repoSlug + "," + repoBranch + "," + selector)
res.status(200).send("Successfully submit repo");
} else {
/*console.log(result);*/
res.status(400).send("Already existed a similar pending request");
}
client.close();
}
});
});
}



exports.get_page = get_page;
Loading