Skip to content

Commit

Permalink
Merge pull request #102 from oss-specs/feature/pagePerProject
Browse files Browse the repository at this point in the history
One page per project
  • Loading branch information
sponte committed Sep 7, 2015
2 parents c173e4f + b00c74b commit 8852162
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 165 deletions.
29 changes: 19 additions & 10 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var hbs = require('hbs');

var indexRoute = require('./routes/get-features');
var featuresRoute = require('./routes/features');
var handlebarHelpers = require(path.join(__dirname,'views', 'helpers'));

// Projects route, current Index.
var projectsRoute = require('./routes/projects');

// The invidual project route.
var projectRoute = require('./routes/project');

// The individual feature/markdown file route.
var featureRoute = require('./routes/feature');

var handlebarHelpers = require(path.join(__dirname,'views', 'helpers'));

var app = express();

Expand Down Expand Up @@ -58,16 +64,19 @@ app.use('/public', express.static(path.join(__dirname, 'public')));

/* Routes. */

// Front page, currently the 'get features' page.
app.use('/', indexRoute);
// Front page is the projects page.
// http://host/
app.use(projectsRoute);

// List of features.
app.use('/features', featuresRoute);
// Individual project.
// http://host/<project name>
app.use(projectRoute);

// Individual feature.
app.use('/features', featureRoute);
// Files of interest
// htpp://host/<project name>/<root/to/file>
app.use(featureRoute);

// Special resources in node_modules routes.
// Special resources in node_modules/ routes.
app.get('/github-markdown-css/github-markdown.css', function(req, res, next) {
var cssPath = path.join(__dirname, 'node_modules','github-markdown-css','github-markdown.css');
res.sendFile(cssPath, {}, function(err) {
Expand Down
38 changes: 27 additions & 11 deletions features-support/step_definitions/features.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ var request = require('request');
var should = require('should');

// Test helper.
function getFeaturesFromUrl(callback) {
function getProjectFromUrl(callback) {
var world = this;
var projectFeaturesUrl = 'http://localhost:' + world.appPort + '/?repo_url=' + encodeURIComponent(world.repoUrl);
var projectRetrievalUrl = 'http://localhost:' + world.appPort + '/?repo_url=' + encodeURIComponent(world.repoUrl);
request
.get(projectFeaturesUrl, function(error, response, body) {
.get(projectRetrievalUrl, function(error, response, body) {
if (error) {
callback(error);
return;
Expand All @@ -24,7 +24,21 @@ function getFeaturesFromUrl(callback) {
});
}

var staticTestDataExists = false;
// Cache the state of the static test data
// at the module level (on first require).
var fakeProjectMetadataExists;
var fakeProjectMetadata = {
repoName: 'made-up',
repoUrl: 'http//example.com',
head: 'testing!',
localName: 'not a real repo'
};

function getFakeProjectUrl(appPort, projectName) {
return 'http://localhost:' + appPort + '/' + projectName;
// DEBUG
//return 'http://localhost:' + appPort + '/features';
}

module.exports = function () {

Expand All @@ -35,18 +49,18 @@ module.exports = function () {
// Only generate the static test data once for the feature
// as opposed to the @cleanSlate tag which removes it for
// each scenario.
if (staticTestDataExists) {
if (fakeProjectMetadataExists) {
callback();
return;
}

// Make sure the test data is removed.
world.deleteTestSpecs()
.then(function() {
return world.createSpecsForTesting();
return world.createSpecsForTesting(fakeProjectMetadata);
})
.then(function() {
staticTestDataExists = true;
fakeProjectMetadataExists = true;
callback();
})
.catch(function(err) {
Expand All @@ -56,8 +70,9 @@ module.exports = function () {

this.When(/^an interested party attempts to view them\.?$/, function (callback) {
var world = this;
var fakeProjectUrl = getFakeProjectUrl(world.appPort, fakeProjectMetadata.repoName);
request
.get('http://localhost:' + world.appPort + '/features', function(error, response, body) {
.get(fakeProjectUrl, function(error, response, body) {
if (error) {
callback(error);
return;
Expand All @@ -83,7 +98,8 @@ module.exports = function () {

this.Given(/^a list of feature files is displayed\.?$/, function (callback) {
var world = this;
request.get('http://localhost:' + world.appPort + '/features', function(error, response, body) {
var fakeProjectUrl = getFakeProjectUrl(world.appPort, fakeProjectMetadata.repoName);
request.get(fakeProjectUrl, function(error, response, body) {
if (error) {
callback(error);
return;
Expand Down Expand Up @@ -122,6 +138,6 @@ module.exports = function () {
callback();
});

this.When(/^an interested party wants to view the features in that repo\.?$/, getFeaturesFromUrl);
this.When(/^they request the features for the same repository again\.?$/, getFeaturesFromUrl);
this.When(/^an interested party wants to view the features in that repo\.?$/, getProjectFromUrl);
this.When(/^they request the features for the same repository again\.?$/, getProjectFromUrl);
};
12 changes: 4 additions & 8 deletions features-support/world.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ module.exports = function() {
*
* @return Promise for operation completion.
*/
this.createSpecsForTesting = function createSpecsForTesting() {
this.createSpecsForTesting = function createSpecsForTesting(fakeProjectMetadata) {
var world = this;
return fs.makeTree(world.paths.public)
.then(function() {
return fs.copyTree(world.paths.features, world.paths.public);
var fakeProjectPath = path.join(world.paths.public, fakeProjectMetadata.repoName);
return fs.copyTree(world.paths.features, fakeProjectPath);
})
.then(function() {

Expand All @@ -36,12 +37,7 @@ module.exports = function() {
// Pass an object of made up repo data to be decorated with
// feature file paths and return a promise for completion
// of storage of that data.
return configuredDeriveAndStore({
repoName: 'made up',
repoUrl: 'http//example.com',
head: 'testing!',
localName: 'not a real repo'
});
return configuredDeriveAndStore(fakeProjectMetadata);
});
};

Expand Down
2 changes: 1 addition & 1 deletion lib/specifications/getProject.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var featureFileRoot = path.join(__dirname, '..', '..', 'public', 'feature-files'
/**
* Get a copy of the project, derive metadata, store metadata.
*
* @return a promise for the completion of repo metadata storage.
* @return a promise for the project metadata on storage completion.
*/
function getProject(repoUrl) {
var repoName = /\/([^\/]+?)(?:\.git)?\/?$/.exec(repoUrl);
Expand Down
7 changes: 5 additions & 2 deletions lib/specifications/projectDataStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ var projectDataDirectory = path.join(appRoot, 'project-data');

module.exports = {

// Return promise for write completion.
// Return promise for the metadata on write completion.
persist: function(projectData) {

// Ensure project data directory exists and write the file.
fs.existsSync(projectDataDirectory) || fs.mkdirSync(projectDataDirectory);
return qfs.write(path.join(projectDataDirectory, projectData.name + '.data'), JSON.stringify(projectData));
return qfs.write(path.join(projectDataDirectory, projectData.name + '.data'), JSON.stringify(projectData))
.then(function() {
return projectData;
});
},

// Return promise for an array of paths in data directory
Expand Down
22 changes: 12 additions & 10 deletions lib/specifications/projectMetaData.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ var projectDataStorage = require('./projectDataStorage');

// Get a function for use with Array.prototype.map to
// convert file paths for feature files to express routes.
function pathsToRoutes(featureFileRoot) {
function pathsToRoutes(featureFileRoot, projectName) {
return function(featurePath) {

// Remove the filesystem root.
featurePath = featurePath.replace(featureFileRoot, '');
// Remove the filesystem root and the project name
// so that we have URLs relative the project page.
var pathRoot = path.posix.join(featureFileRoot, projectName) + '/';
var featureRoute = featurePath.replace(pathRoot, '');

// Prefix with the 'features' route, always use backslashes.
featurePath = path.posix.join('features', featurePath);
// Remove the .feature for a slightly shorter display name.
var featureName = featureRoute.replace('.feature', '');

return {
featureRoute: featurePath,
featureName: featurePath.replace('.feature', '').replace('features/', '')
featureRoute: featureRoute,
featureName: featureName
};
}
}
Expand All @@ -41,7 +43,7 @@ function deriveProjectData(featureFileRoot, repoData) {
commit: repoData.commit,
shortCommit: repoData.shortCommit,
localName: repoData.localName,
projectLink: '/features#' + repoData.repoName,
projectLink: '/' + repoData.repoName,
featureFilePaths: []
}

Expand All @@ -50,7 +52,7 @@ function deriveProjectData(featureFileRoot, repoData) {
.then(function(featureFilePaths) {

// Map from the storage directory to the Express route for creating links.
projectData.featureFilePaths = featureFilePaths.map(pathsToRoutes(featureFileRoot));
projectData.featureFilePaths = featureFilePaths.map(pathsToRoutes(featureFileRoot, projectData.name));
return projectData;
});
}
Expand All @@ -59,7 +61,7 @@ function deriveProjectData(featureFileRoot, repoData) {
/**
* Return a function which takes the repo data, derives the project data and stores it.
*
* @return A promise for completion of the storage of the project data.
* @return A promise for the project data on completion of the storage.
*/
function deriveAndStore(featureFileRoot) {
return function(repoData) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "specs",
"version": "0.4.0",
"version": "0.5.0",
"private": true,
"bin": {
"module-name": "./bin/www"
Expand Down
14 changes: 8 additions & 6 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,27 @@ button.call-to-action:active {

/* Top nav. */
.header-nav {
width: 100%;
width: 70%;
margin: 0 auto;
position: relative;
top: 0.8em;
text-align: center;
text-align: left;
font-size: 1.2em;
list-style: none;
}
.header-nav hr {
max-width: 70%;
}
.header-nav a {
font-weight: bold;
color: green;
color: blue;
text-decoration: none;
}
.header-nav li {
display: inline;
margin-left: 0.2em;
}
.header-nav li:hover a {
text-decoration: underline;
color: green;
}
.header-nav li.primary {
font-size: 1.2em;
margin-right: 1em;
Expand Down
36 changes: 14 additions & 22 deletions public/css/features.css → public/css/project.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,21 @@
margin-bottom: 1em;
}

.project-title {
display: inline-block;
}
.quick-link {
text-decoration: none;
color: blue;
}
.project-title .quick-link-icon {
font-size: 1.3em;
opacity: 0.4;
color: blue;
}
.project-title:hover .quick-link-icon {
opacity: 1;
color: green;
}
.project-name {
margin-left: 0.5em;
font-size: 2.5em;
display: inline-block;
}

.project-commit {
margin-left: 0.3em;
position: relative;
top: -0.1em;
margin-left: 0.5em;
margin-right: 1em;
}

.repo-link {
position: relative;
top: -0.1em;
font-size: 0.7em;
margin-left: 2em;
margin-right: 3em;
font-weight: bold;
text-transform: uppercase;
}
Expand All @@ -40,12 +26,12 @@
}
.repo-link:hover a {
color: green;
text-decoration: underline;
}

.project-update {
margin-top: 1em;
margin-bottom: 1em;
margin-left: 2em;
}

.project-update a {
Expand All @@ -56,3 +42,9 @@
.links-container {
margin-left: 3em;
}

@media (min-width: 800px) {
.project-update {
float: right;
}
}
12 changes: 6 additions & 6 deletions public/css/get-features.css → public/css/projects.css
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
.get-features > section {
.projects > section {
float: left;
margin-right: 3em;
}

.get-features form {
.projects form {
display: inline-block;
}

.get-features form {
.projects form {
margin-bottom: 1.2em;
}

.get-features input {
.projects input {
margin-top: 1em;
margin-right: 0.5em;
margin-bottom: 1em;
}

.get-features button {
.projects button {
font-size: 1.1em;
}

/**
* Wider viewport (e.g. monitor, tv).
*/
@media (min-width: 1280px) {
.get-features input {
.projects input {
margin-top: 0;
}
}
Loading

0 comments on commit 8852162

Please sign in to comment.