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

Feature/better project page #138

Merged
merged 38 commits into from
Oct 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
429baff
Refactor some naming around files in the project data object.
jimCresswell Oct 7, 2015
e51d621
Make feature file and markdown file processed data structures availab…
jimCresswell Oct 7, 2015
02754e6
Get rid of unused renderingOptions object.
jimCresswell Oct 8, 2015
6c19704
Catch feature file parsing errors in the project and feature view and…
jimCresswell Oct 8, 2015
608a28c
Move the clone options.
jimCresswell Oct 8, 2015
cb9a792
Put the project page error handling in the right place and tidy up th…
jimCresswell Oct 8, 2015
9c94e2f
Record fetch bug and associated GitHub ticket.
jimCresswell Oct 8, 2015
e09d79e
Fix the link to the plain versions of files given on parse error.
jimCresswell Oct 8, 2015
67b83b5
Add a test empty feature file
jimCresswell Oct 8, 2015
819e427
Style empty files in the project file list.
jimCresswell Oct 8, 2015
931c860
Consolidate use of variable names filePath and fileName.
jimCresswell Oct 8, 2015
b945eaa
Create a partial and styling for project file list. Demark files whic…
jimCresswell Oct 8, 2015
07689b2
Prune local list of remote refs on update.
jimCresswell Oct 8, 2015
8223c72
Simpligy HTML on the project page and styling.
jimCresswell Oct 8, 2015
d6874c8
Add feature name and abbreviated feature description on project page.
jimCresswell Oct 8, 2015
a64aa23
Make the whole file description a click target. Styling.
jimCresswell Oct 8, 2015
f4b8bef
Code climate.
jimCresswell Oct 8, 2015
97b62b5
Linting.
jimCresswell Oct 8, 2015
ba179dc
Stop long file names and long file paths from breaking out of the fil…
jimCresswell Oct 8, 2015
217f2ca
Docs.
jimCresswell Oct 8, 2015
b74f737
Version
jimCresswell Oct 8, 2015
c8e5599
Layout tweaks.
jimCresswell Oct 9, 2015
0fa0f48
Fix misleading function name.
jimCresswell Oct 9, 2015
665b21a
Move file list data decoration to a single location. Handle some erro…
jimCresswell Oct 9, 2015
47977ad
Move the definition of which files are of interest to the config module.
jimCresswell Oct 9, 2015
59b8bba
Docs.
jimCresswell Oct 9, 2015
7daeb40
Change a forEach to a map so we don't rely on side effects. Store the…
jimCresswell Oct 9, 2015
345db15
Create an example of generating a file tree data structure from the f…
jimCresswell Oct 9, 2015
2e47c61
Create resuable list of file extensions the app is interested in.
jimCresswell Oct 12, 2015
093c909
Keep the file content in the list of files and link to that from the …
jimCresswell Oct 12, 2015
56083e8
Use the tree of files to generate list of files keyed by containing d…
jimCresswell Oct 12, 2015
9a68834
Toggle showing files in a given directory.
jimCresswell Oct 12, 2015
228a364
Tweaking patch number so pull request will notice there are new commi…
jimCresswell Oct 12, 2015
aba86a4
Move all project page javascript to a script file. Add an expand/coll…
jimCresswell Oct 12, 2015
21b8ad8
Linting.
jimCresswell Oct 12, 2015
47c8283
Use different partials for features files, markdown and generic files.
jimCresswell Oct 13, 2015
6875692
Fix passing through currentBranchName in new context and some styling.
jimCresswell Oct 13, 2015
20c0232
Collapse files on first click of expand/collapse all button.
jimCresswell Oct 13, 2015
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
3 changes: 3 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var hbs = require('hbs');

// Pull in polyfills.
require('./polyfill');

var appVersion = require('./package.json').version;

// Set the config object for use elsewhere.
Expand Down
Empty file.
1 change: 1 addition & 0 deletions features-support/test-data/no-feature-file.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# This file contains no feature.
11 changes: 11 additions & 0 deletions lib/configuration/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ var folderNames = {
projects: 'projects'
};

// List of filename extensions the app cares about.
var filesOfInterest = [
'feature',
'md'
];

// Cached instance of Config.
var configInstance;

Expand All @@ -25,6 +31,11 @@ function Config(configuration) {
this.dataStoragePath = path.join(this.rootPath, folderNames.dataStorage);
this.derivedDataPath = path.join(this.dataStoragePath, folderNames.derived);
this.projectsPath = path.join(this.dataStoragePath, folderNames.projects);

this.regex = {};

// Define which file types the application willl process and display.
this.regex['fileOfInterest'] = new RegExp('\\.(' + filesOfInterest.join('|') + ')$');
}

/**
Expand Down
25 changes: 17 additions & 8 deletions lib/specifications/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

var fs = require('q-io/fs');

var getProject = require('./repositoryTypes/git').getProject;
var getProjectData = require('./repositoryTypes/git').getProjectData;
var getProjectGit = require('./repositoryTypes/git').getProject;
var getProjectDataGit = require('./repositoryTypes/git').getProjectData;
var getFileContentsGit = require('./repositoryTypes/git').getFileContents;
var config = require('../configuration').get();


Expand All @@ -13,16 +14,23 @@ var config = require('../configuration').get();
* @return a promise for the meta data for one project.
*/
function get(projectData) {
return getProject(projectData);
return getProjectGit(projectData);
}

function getData(projectData, targetBranchName) {
return getProjectDataGit(projectData, targetBranchName);
}

function getFileContents(projectData, filePath) {
return getFileContentsGit(projectData, filePath);
}

/**
* Get the meta data for all projects.
* Get a list of known project names.
*
* @return a promise for an array meta data for all the projects.
* @return a promise for an array of project names.
*/
function getAll() {
function getNames() {
return fs.list(config.projectsPath)
.then(function(paths) {
return paths.map(function(path) {
Expand All @@ -40,7 +48,8 @@ function getAll() {
}

module.exports = {
getAll: getAll,
get: get,
getData: getProjectData
getData: getData,
getNames: getNames,
getFileContents: getFileContents
};
73 changes: 37 additions & 36 deletions lib/specifications/repositoryTypes/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ function generateRepoMetaData(projectData, sha, tagsAndBranches, currentBranchNa
shortCommit: sha.substring(0, 7),
tagsAndBranches: tagsAndBranches,
currentBranchName: currentBranchName,
currentBranchNameShort: currentBranchName,
featureFilePaths: files,
repoUrl: remoteUrl
repoUrl: remoteUrl,
files: files
};

// Filter falsey values and empty arrays.
Expand All @@ -78,8 +77,24 @@ function generateRepoMetaData(projectData, sha, tagsAndBranches, currentBranchNa
*
* @return a promise for the repo metadata.
*/
function clone(projectData, cloneOptions) {
function clone(projectData) {
var repository;

// Need to define this here as the Clone function modifies the passed object (face palm).
var cloneOptions = {};
cloneOptions.bare = 1;

// Mac OSX certificate issue http://www.nodegit.org/guides/cloning/
// This is now an undocumented Mac only part of the API.
cloneOptions.remoteCallbacks = ignoreSSLErrors;

// General option to ingore SSL errors.
if(appConfig.allowInsecureSSL) {
cloneOptions.fetchOpts = {
callbacks: ignoreSSLErrors
};
}

if (!projectData.repoUrl) {
throw new TypeError('Clone called without a repo URL. Possible wrong project name?');
}
Expand All @@ -104,11 +119,13 @@ function update(projectData) {
return git.Repository.openBare(projectData.localPath)
.then(function (repository) {

// Sync.
// BUG: this doesn't seem to pull down new tags.
repository.fetch(repository.getRemote('origin'), {
// BUG: This isn't working at all, no new tags or branch are pulled down,
// current heads aren't updated.
// https://github.com/nodegit/nodegit/issues/742
return repository.fetch(repository.getRemote('origin'), {
callback: ignoreSSLErrors,
downloadTags: 1
downloadTags: 1,
prune: 1
});
})
.then(function () {
Expand All @@ -125,35 +142,20 @@ function getProject(projectData) {
return fs.exists(projectData.localPath)
.then(function (pathExists) {

// Need to define this here as the Clone function modifies the passed object (face palm).
var cloneOptions = {};
cloneOptions.bare = 1;

// Mac OSX certificate issue http://www.nodegit.org/guides/cloning/
// This is now an undocumented Mac only part of the API.
cloneOptions.remoteCallbacks = ignoreSSLErrors;

// General option to ingore SSL errors.
if(appConfig.allowInsecureSSL) {
cloneOptions.fetchOpts = {
callbacks: ignoreSSLErrors
};
}

/**
* If there is no matching directory then clone the repo
* else perform a pull on it.
*/
if (!pathExists) {
return clone(projectData, cloneOptions);
return clone(projectData);
} else {
return update(projectData);
}
});
}

function getBranch(projectData, branchName) {
return git.Repository.open(projectData.localPath)
return git.Repository.openBare(projectData.localPath)
.then(function (repo) {
if (branchName) {
return repo.getBranch(branchName);
Expand All @@ -168,7 +170,7 @@ function getBranch(projectData, branchName) {
// if that fails fall bacl to try the annotated tag approach.
function getCommitByName(repository, refName) {
return repository.getReferenceCommit(refName)
.catch(function(err) {
.catch(function() {
return repository.getTagByName(refName).then(function(tag) {
return repository.getCommit(tag.targetId().tostrS());
});
Expand All @@ -185,7 +187,7 @@ function getProjectData(projectData, targetBranchName) {
return getBranch(projectData, targetBranchName)
.then(function (ref) {
currentRef = ref;
return git.Repository.open(projectData.localPath);
return git.Repository.openBare(projectData.localPath);
})
.then(function (repo) {
repository = repo;
Expand All @@ -201,13 +203,8 @@ function getProjectData(projectData, targetBranchName) {
})
.then(getAllFiles)
.then(function (files) {
listOfFiles = files.map(function (fileOfInterestName) {
return {
ref: currentRef.name(),
featureName: fileOfInterestName,
featureNameShort: fileOfInterestName.replace(/\.feature$/, '')
};
});
listOfFiles = files;

return repository.getReferences(git.Reference.TYPE.OID);
})
.then(function (refs) {
Expand All @@ -219,7 +216,11 @@ function getProjectData(projectData, targetBranchName) {
function getFileContents(projectData, filePath) {
var repository;

return git.Repository.open(projectData.localPath)
if (!filePath) {
throw new TypeError('Please supply a file path to read file contents.');
}

return git.Repository.openBare(projectData.localPath)
.then(function (repo) {
repository = repo;
return getCommitByName(repository, projectData.currentBranchName);
Expand Down Expand Up @@ -261,7 +262,7 @@ function getAllFiles(tree) {
return _getAllFiles(tree)
.then(function (files) {
return files.filter(function (f) {
return /\.(feature|md)/.test(f);
return (appConfig.regex.fileOfInterest).test(f);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move file filtering into project.js rather at low level inside please?

});
});
}
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "oss-specs",
"version": "0.10.1",
"version": "0.11.1",
"bin": {
"oss-specs": "./bin/www"
},
Expand Down Expand Up @@ -56,6 +56,7 @@
"express": "^4.13.3",
"express-session": "^1.11.3",
"file-stream-rotator": "0.0.6",
"file-tree": "git+https://github.com/jimCresswell/file-tree#v1.0.1-rc1",
"gherkin": "^3.1.1",
"github-markdown-css": "^2.0.10",
"hbs": "^3.1.1",
Expand All @@ -68,6 +69,7 @@
"q-io": "^1.13.1",
"serve-favicon": "^2.3.0",
"session-file-store": "0.0.20",
"tree-model": "^1.0.2",
"underscore": "1.8.3"
},
"devDependencies": {
Expand Down
13 changes: 13 additions & 0 deletions polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
}

module.exports = 'done';
7 changes: 7 additions & 0 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ button.call-to-action:active {
}
}

/**
* Hide things.
*/
.hidden {
display: none;
}

/**
* Semantic clearfix.
*/
Expand Down
85 changes: 81 additions & 4 deletions public/css/project.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,86 @@
text-decoration: underline;
}

.spec-links > h2 {
color: grey;

.file-list li {
max-width: 100%;
}

a.spec-link {
max-width: 100%;
color: black;
text-decoration: none;
}

.directory {
margin: 1em;
}
/* Minus and plus signs for expandable directories */
.directory-path::before {
content: '\2296\2003';
}
.directory-path.expand::before {
content: '\2295\2003';
}

.file-container {
font-size: 1.2em;

/*
* M ke max-width:100% constrain the width out
* to the edge of the border rather than the
* content.
*/
box-sizing: border-box;
max-width: 100%;

padding: 0.8em;
margin-bottom: 1.5em;
margin-left: 1.5em;
background-color: #FAFAFA;
border: 2px solid rgba(100, 100, 100, 0.5);
border-radius: 0.8em;
box-shadow: -0.1em 0.1em 0.2em 0.1em rgba(100, 100, 100, 0.5);
}

.empty-file {
color: #555;
}

.parse-error {
color: darkred;
}

.file-details {
word-wrap: break-word; /* break long file names and paths */
padding: 0.6em;
}
.file-name {
margin-bottom: 0.3em;
color: darkblue;
}
.file-path {
font-size: 0.6em;
margin-bottom: 0;
}
.spec-links > div {
margin-left: 3em;

.feature-summary {
padding: 1em;
border-radius: 1em;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 2%, rgba(240, 240, 240, 1) 16%, rgba(255, 255, 255, 0) 100%);
}
.feature-summary p {
margin-bottom: 0.5em;
margin-left: 0.5em;
}
.feature-summary .feature-name {
color: blue;
}
.feature-summary .feature-description {
font-size: 0.8em;

/* Truncate the feature descriptions. */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Loading