Compare commits

...

6 Commits
3.2.0 ... 3.3.0

Author SHA1 Message Date
Jose Bolos
1d931671ff Version 3.3.0 2021-04-27 15:03:22 +01:00
Jose Bolos
9d95c79625 Version 3.2.1 2021-04-27 15:53:29 +02:00
Jose Bolos
b8029c56f7 Fix security vuln by bumping express-hbs
Also bumps pa11y-webservice to the latest version.
2021-04-27 15:53:29 +02:00
Sangita Mane
9a23b79d89 #165 - Added list view option for the dashboard. (#279)
* Added list view & grid view buttons on the dashboard, on click of which switches the view and avoids truncation of title of the page.

* Indentation fixed.
2021-04-20 09:58:33 +02:00
Jose Bolos
b7d45c0913 Reorder the routes to avoid MongoDB ObjectID error
When trying to add a new URL, the Node.js MongoDB driver complains with the following error:
```
ObjectID generation failed. Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
```

This is because the `/new` url gets captured by the `/:id` route defined in `/route/task/index.js`. It's another instance of #244 that I missed when fixing it.
2021-04-09 11:30:35 +02:00
Jose Bolos
9ae73dc446 Replace Travis with GH actions 2021-04-09 11:04:12 +02:00
14 changed files with 615 additions and 497 deletions

50
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests.
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Build and lint
on:
push:
branches: # Run actions when code is committed to these branches
- master
pull_request:
branches: # Run actions when a PR is pushed based on one of these branches
- master
jobs:
checkout_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- node-version: 8.x
lint: true # Linter is run only once to shorten the total build time
- node-version: 10.x
- node-version: 12.x
steps:
- name: Checkout code from ${{ github.repository }}
uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: MongoDB in GitHub Actions
uses: supercharge/mongodb-github-action@1.3.0
with:
mongodb-version: 3.4
- name: Install dependencies
run: npm i
- name: Run linter
if: ${{ matrix.lint }}
run: make lint
- name: Create test config
run: cp config/test.sample.json config/test.json
- name: Start test app
run: NODE_ENV=test node index.js &
- name: Wait / Sleep
uses: jakejarvis/wait-action@v0.1.0
with:
time: '10s'
- name: Run tests
run: make ci

View File

@@ -1,24 +0,0 @@
# Language/versions
language: node_js
matrix:
include:
- node_js: '8'
- node_js: '10'
- node_js: '12'
# Build only master (and pull-requests)
branches:
only:
- master
# Services setup
services:
- mongodb
# Build script
before_script:
- cp config/test.sample.json config/test.json
- NODE_ENV=test node index.js &
- sleep 5 # give server time to start
script: 'make ci'

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
## 3.3.0 (2021-04-27)
* Add new list view to the dashboard (thanks @sangitamane)
* Upgrade express-hbs to the latest version in order to address several potential vulnerabilities
* Fixes a MongoDB "ObjectID generation failed" error.
* Update pa11y-webservice to version 3.2.1 and pa11y to version 5.3.1
## 3.2.0 (2020-10-05) ## 3.2.0 (2020-10-05)
* Update pa11y to version 5.3.0, which means better compatibility with sites using AMD modules * Update pa11y to version 5.3.0, which means better compatibility with sites using AMD modules

3
app.js
View File

@@ -92,7 +92,6 @@ function initApp(config, callback) {
// Load routes // Load routes
require('./route/index')(app); require('./route/index')(app);
require('./route/task/index')(app);
require('./route/result/download')(app); require('./route/result/download')(app);
if (!config.readonly) { if (!config.readonly) {
require('./route/new')(app); require('./route/new')(app);
@@ -102,6 +101,8 @@ function initApp(config, callback) {
require('./route/task/ignore')(app); require('./route/task/ignore')(app);
require('./route/task/unignore')(app); require('./route/task/unignore')(app);
} }
// Needs to be loaded after `/route/new`
require('./route/task/index')(app);
// Needs to be loaded after `/route/task/edit` // Needs to be loaded after `/route/task/edit`
require('./route/result/index')(app); require('./route/result/index')(app);

View File

@@ -1,6 +1,6 @@
{ {
"name": "pa11y-dashboard", "name": "pa11y-dashboard",
"version": "3.2.0", "version": "3.3.0",
"private": true, "private": true,
"description": "Pa11y Dashboard is a visual web interface to the Pa11y accessibility reporter", "description": "Pa11y Dashboard is a visual web interface to the Pa11y accessibility reporter",
"keywords": [ "keywords": [
@@ -28,11 +28,11 @@
"body-parser": "~1.19.0", "body-parser": "~1.19.0",
"compression": "~1.7.4", "compression": "~1.7.4",
"express": "~4.17.1", "express": "~4.17.1",
"express-hbs": "~2.1.2", "express-hbs": "~2.4.0",
"http-headers": "~3.0.2", "http-headers": "~3.0.2",
"kleur": "~4.1.2", "kleur": "~4.1.2",
"moment": "~2.29.0", "moment": "~2.29.0",
"pa11y-webservice": "~3.2.0", "pa11y-webservice": "~3.2.1",
"pa11y-webservice-client-node": "~2.0.0", "pa11y-webservice-client-node": "~2.0.0",
"underscore": "~1.11.0" "underscore": "~1.11.0"
}, },

File diff suppressed because one or more lines are too long

View File

@@ -27,6 +27,8 @@ $(document).ready(function(){
var graphContainer = $('[data-role="graph"]'); var graphContainer = $('[data-role="graph"]');
var dateSelectDropdownMenu = $('[data-role="date-select-dropdown-menu"]'); var dateSelectDropdownMenu = $('[data-role="date-select-dropdown-menu"]');
var legend = graphContainer.parent('.graph-container').find('.dashedLegend'); var legend = graphContainer.parent('.graph-container').find('.dashedLegend');
var list = localStorage.getItem("listview") || ""; // get choice or nothing
var graphOptions = { var graphOptions = {
series: { series: {
@@ -397,4 +399,38 @@ $(document).ready(function(){
$.fn.collapse.Constructor.prototype.keydown $.fn.collapse.Constructor.prototype.keydown
); );
// List View
$('.btn-list').click(function () {
var elements = $("#grid-container .task-card");
for (i = 0; i < elements.length; i++) {
$(elements[i]).removeClass('col-md-4 col-sm-6');
$(elements[i]).addClass('col-md-12');
$(elements[i]).find('.gridview:nth-child(1)').addClass('listview col-md-9 col-sm-8');
$(elements[i]).find('.gridview:nth-child(2)').addClass('listview col-md-3 col-sm-4 task-actions clearfix');
$(elements[i]).find('.gridview').removeClass('gridview');
};
$('.view-btn').removeClass('btn-default')
$(this).addClass('btn-default');
localStorage.setItem("listview", "yes") //save the choice
});
// Grid View
$('.btn-grid').click(function () {
var elements = $("#grid-container .task-card");
for (i = 0; i < elements.length; i++) {
$(elements[i]).removeClass('col-md-12');
$(elements[i]).addClass('col-md-4 col-sm-6');
$(elements[i]).find('.listview').addClass('gridview')
$(elements[i]).find('.listview:nth-child(1)').removeClass('listview col-md-9 col-sm-8');
$(elements[i]).find('.listview:nth-child(2)').removeClass('listview col-md-3 col-sm-4 task-actions clearfix');
};
$('.view-btn').removeClass('btn-default')
$(this).addClass('btn-default')
localStorage.setItem("listview", "") //clears the choice
});
//load the view as per user's choice
if (list === 'yes') {
$('.btn-list').trigger('click');
}
}); });

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
// Amend the width of container if you want to here // Amend the width of container if you want to here
@container-md-ie8: @container-md; @container-md-ie8: @container-md;
@grid-adjustment: percentage(@grid-gutter-width / @container-md-ie8); @grid-adjustment: percentage((@grid-gutter-width / @container-md-ie8));
.ie7, .ie8 { .ie7, .ie8 {
* { * {

File diff suppressed because it is too large Load Diff

View File

@@ -233,7 +233,7 @@
@navbar-default-bg: @brand-primary; @navbar-default-bg: @brand-primary;
@navbar-default-border: darken(@navbar-default-bg, 6.5%); @navbar-default-border: darken(@navbar-default-bg, 6.5%);
@navbar-border-radius: @border-radius-base; @navbar-border-radius: @border-radius-base;
@navbar-padding-horizontal: floor(@grid-gutter-width / 2); // ~15px @navbar-padding-horizontal: floor((@grid-gutter-width / 2)); // ~15px
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); @navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
// Navbar links // Navbar links

View File

@@ -247,7 +247,7 @@
@navbar-height: 50px; @navbar-height: 50px;
@navbar-margin-bottom: @line-height-computed; @navbar-margin-bottom: @line-height-computed;
@navbar-border-radius: @border-radius-base; @navbar-border-radius: @border-radius-base;
@navbar-padding-horizontal: floor(@grid-gutter-width / 2); @navbar-padding-horizontal: floor((@grid-gutter-width / 2));
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); @navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
@navbar-default-color: #777; @navbar-default-color: #777;

View File

@@ -41,10 +41,18 @@ describe.only('GET /', function() {
it('should display all of the expected tasks', function() { it('should display all of the expected tasks', function() {
const tasks = this.last.dom('[data-test=task]'); const tasks = this.last.dom('[data-test=task]');
assert.strictEqual(tasks.length, 4); assert.strictEqual(tasks.length, 4);
assert.match(tasks.eq(0).text(), /npg home\s+\(wcag2aa\)/i); assert.equal(tasks.eq(0).find('.h3').text(), 'NPG Home');
assert.match(tasks.eq(1).text(), /npg home\s+\(wcag2aaa\)/i); assert.equal(tasks.eq(0).find('.h4').text(), 'nature.com');
assert.match(tasks.eq(2).text(), /nature news\s+\(section508\)/i); assert.equal(tasks.eq(0).find('.h5').text(), '(WCAG2AA)');
assert.match(tasks.eq(3).text(), /z integration test\s+\(wcag2aa\)/i); assert.equal(tasks.eq(1).find('.h3').text(), 'NPG Home');
assert.equal(tasks.eq(1).find('.h4').text(), 'nature.com');
assert.equal(tasks.eq(1).find('.h5').text(), '(WCAG2AAA)');
assert.equal(tasks.eq(2).find('.h3').text(), 'Nature News');
assert.equal(tasks.eq(2).find('.h4').text(), 'nature.com/news');
assert.equal(tasks.eq(2).find('.h5').text(), '(Section508)');
assert.equal(tasks.eq(3).find('.h3').text(), 'Z Integration Test');
assert.equal(tasks.eq(3).find('.h4').text(), 'localhost:8132');
assert.equal(tasks.eq(3).find('.h5').text(), '(WCAG2AA)');
}); });
it('should have links to each task', function() { it('should have links to each task', function() {

View File

@@ -14,11 +14,15 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>. along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
}} }}
<div class="col-md-12 task-card clearfix">
<button class="btn view-btn btn-grid btn-default"><i class="glyphicon glyphicon-th"></i> Grid</button>
<button class="btn view-btn btn-list"><i class="glyphicon glyphicon-align-justify "></i> List</button>
<ul class="list-unstyled clearfix crunch-bottom"> </div>
<ul class="list-unstyled clearfix crunch-bottom" id="grid-container">
{{#unless readonly}} {{#unless readonly}}
<li class="col-md-4 col-sm-6 task-card add-task"> <li class="col-md-4 col-sm-6 task-card add-task">
<a class="well task-card-link crunch-bottom" data-role="add-task" href="/new" data-test="add-task"> <a class="well task-card-link crunch-bottom" data-role="add-task" href="/new" data-test="add-task">
<p class="h3 crunch">Add new URL</p> <p class="h3 crunch">Add new URL</p>
<p class="supersize-me crunch">+</p> <p class="supersize-me crunch">+</p>
@@ -28,17 +32,23 @@ along with Pa11y Dashboard. If not, see <http://www.gnu.org/licenses/>.
{{#each tasks}} {{#each tasks}}
<li class="col-md-4 col-sm-6 task-card" data-test="task" data-role="task" data-keywords="{{lowercase name}} {{lowercase standard}} {{simplify-url url}}"> <li class="col-md-4 col-sm-6 task-card" data-test="task" data-role="task" data-keywords="{{lowercase name}} {{lowercase standard}} {{simplify-url url}}">
<a class="well task-card-link crunch-bottom" title="Details for URL {{simplify-url url}}" href="{{href}}"> <a class="well task-card-link crunch-bottom" title="Details for URL {{simplify-url url}}" href="{{href}}">
<p class="h3">{{name}}</p> <div class="gridview">
<p class="h5">({{standard}})</p> <p class="h3">{{name}}</p>
<p class="h4">{{simplify-url url}}</p>
<p class="h5">({{standard}})</p>
</div>
{{#if lastResult}} {{#if lastResult}}
<ul class="clearfix list-unstyled floated-list task-stats"> <div class="gridview">
{{#lastResult}} <ul class="clearfix list-unstyled floated-list task-stats">
<li class="danger" title="Number of errors ({{count.error}})">{{count.error}}<span class="stat-type">Errors</span></li> {{#lastResult}}
<li class="warning" title="Number of warnings ({{count.warning}})">{{count.warning}}<span class="stat-type">Warnings</span></li> <li class="danger" title="Number of errors ({{count.error}})">{{count.error}}<span class="stat-type">Errors</span></li>
<li class="info last" title="Number of notices ({{count.notice}})">{{count.notice}}<span class="stat-type">Notices</span></li> <li class="warning" title="Number of warnings ({{count.warning}})">{{count.warning}}<span class="stat-type">Warnings</span></li>
{{/lastResult}} <li class="info last" title="Number of notices ({{count.notice}})">{{count.notice}}<span class="stat-type">Notices</span></li>
</ul> {{/lastResult}}
Last run {{date-format lastResult.date format="DD MMM YYYY"}} </ul>
</div>
<div class="last-run">Last run {{date-format lastResult.date format="DD MMM YYYY"}}</div>
{{else}} {{else}}
<p class="no-results">No results</p> <p class="no-results">No results</p>
{{/if}} {{/if}}