Skip to content
This repository has been archived by the owner on Dec 23, 2017. It is now read-only.

Feature/filings detail #569

Merged
merged 11 commits into from
Sep 3, 2015
54 changes: 54 additions & 0 deletions candidate.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<div class="panel__row">
<h4>{{document_description}}</h4>
<h5>Report coverage: {{datetime coverage_start_date}} - {{datetime coverage_end_date}}</h5>
<table>
<tr>
<td>Total Receipts</td>
<td>{{{currency total_receipts_period}}}</td>
</tr>
<tr>
<td>Total Disbursements</td>
<td>{{{currency total_disbursements_period}}}</td>
</tr>
<tr>
<td>Transfers to Authorized Committees</td>
<td>{{{currency transfers_to_other_authorized_committee_period}}}</td>
</tr>
<tr>
<td>Individual Contributions</td>
<td>{{{currency total_individual_contributions_period}}}</td>
</tr>
<tr>
<td>Itemized Individual Contributions</td>
<td>{{{currency individual_itemized_contributions_period}}}</td>
</tr>
<tr>
<td>Unitemized Individual Contributions</td>
<td>{{{currency individual_unitemized_contributions_period}}}</td>
</tr>
<tr>
<td>Loan Repayments</td>
<td>{{{currency total_loan_repayments_made_period}}}</td>
</tr>
<tr>
<td>Beginning Cash on Hand</td>
<td>{{{currency cash_on_hand_beginning_period}}}</td>
</tr>
<tr>
<td>Ending Cash on Hand</td>
<td>{{{currency cash_on_hand_end_period}}}</td>
</tr>
<tr>
<td>Net Contributions</td>
<td>{{{currency net_contributions_period}}}</td>
</tr>
<tr>
<td>Net Operating Expenditures</td>
<td>{{{currency net_operating_expenditures_period}}}</td>
</tr>
<tr>
<td>Debts Owed by Committee</td>
<td>{{{currency debts_owed_by_committee}}}</td>
</tr>
</table>
</div>
60 changes: 60 additions & 0 deletions static/js/modules/columns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use strict';

/* global require, module */

var _ = require('underscore');

var tables = require('./tables');
var decoders = require('./decoders');

var filings = {
pdf_url: tables.urlColumn('pdf_url', {data: 'document_description', className: 'all', orderable: false}),
filer_name: {
data: 'committee_id',
className: 'min-desktop',
orderable: false,
render: function(data, type, row, meta) {
var cycle = tables.buildCycle(row);
if (row.candidate_name) {
return tables.buildEntityLink(row.candidate_name, '/candidate/' + row.candidate_id + cycle, 'candidate');
} else if (row.committee_name) {
return tables.buildEntityLink(row.committee_name, '/committee/' + row.candidate_id + cycle, 'committee');
} else {
return '';
}
},
},
amendment_indicator: {
data: 'amendment_indicator',
className: 'min-desktop',
render: function(data, type, row, meta) {
return decoders.amendments[data] || '';
},
},
receipt_date: tables.dateColumn({data: 'receipt_date', className: 'min-tablet'}),
coverage_end_date: tables.dateColumn({data: 'coverage_end_date', className: 'min-tablet hide-panel', orderable: false}),
total_receipts: tables.currencyColumn({data: 'total_receipts', className: 'min-tablet hide-panel'}),
total_disbursements: tables.currencyColumn({data: 'total_disbursements', className: 'min-tablet hide-panel'}),
total_independent_expenditures: tables.currencyColumn({data: 'total_independent_expenditures', className: 'min-tablet hide-panel'}),
modal_trigger: {
className: 'all',
width: '20px',
orderable: false,
render: function(data, type, row, meta) {
return row.form_type && row.form_type.match(/^F3/) ?
tables.MODAL_TRIGGER_HTML :
'';
}
}
};

function getColumns (columns, keys) {
return _.map(keys, function(key) {
return columns[key];
});
}

module.exports = {
filings: filings,
getColumns: getColumns
};
49 changes: 49 additions & 0 deletions static/js/modules/filings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

/* global require, module */

var $ = require('jquery');
var _ = require('underscore');

var tables = require('./tables');
var helpers = require('../modules/helpers');

var candidateTemplate = require('../../templates/filings/candidate.hbs');
var pacTemplate = require('../../templates/filings/pac.hbs');

var templates = {
F3: candidateTemplate,
F3P: candidateTemplate,
F3X: pacTemplate
};

function resolveTemplate(row) {
return templates[row.form_type](row);
}

var renderModal = tables.modalRenderFactory(
resolveTemplate,
function(row) {
var url = helpers.buildUrl(
['committee', row.committee_id, 'reports'],
{beginning_image_number: row.beginning_image_number}
);
return $.getJSON(url).then(function(response) {
var result = response.results.length ?
response.results[0] :
{};
return _.extend({}, row, result);
});
}
);

function renderRow(row, data, index) {
if (data.form_type && data.form_type.match(/^F3[XP]?$/)) {
row.classList.add(tables.MODAL_TRIGGER_CLASS);
}
}

module.exports = {
renderModal: renderModal,
renderRow: renderRow
};
14 changes: 12 additions & 2 deletions static/js/modules/helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';

/* global require, module, Intl */
/* global require, module, Intl, API_LOCATION, API_VERSION, API_KEY */

var URI = require('URIjs');
var _ = require('underscore');
var moment = require('moment');
var Handlebars = require('hbsfy/runtime');
Expand Down Expand Up @@ -42,9 +43,18 @@ function filterNull(params) {
.value();
}

function buildUrl(path, query) {
return URI(API_LOCATION)
.path([API_VERSION].concat(path).join('/'))
.addQuery({api_key: API_KEY})
.addQuery(query)
.toString();
}

module.exports = {
currency: currency,
datetime: datetime,
cycleDates: cycleDates,
filterNull: filterNull
filterNull: filterNull,
buildUrl: buildUrl
};
105 changes: 63 additions & 42 deletions static/js/modules/tables.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,52 +230,70 @@ function mapQuerySeek(api, data) {
);
}

function modalAfterRender(template, api, data, response) {
var $table = $(api.table().node()),
$modal = $('#datatable-modal');

// Move the modal to the results div.
$modal.appendTo($('#results'));
$table.find('tr').attr('tabindex', 0);

$table.on('click keypress', '.js-panel-toggle tr', function(ev) {
if (ev.which === 13 || ev.type === 'click') {
if ($(ev.target).is('a')) {
return true;
}
if ( !$(ev.target).closest('td').hasClass('dataTables_empty') ) {
var $row = $(ev.target).closest('tr');
var index = api.row($row).index();
$modal.find('.js-panel-content').html(template(response.results[index]));
$modal.attr('aria-hidden', 'false');
$row.siblings().toggleClass('row-active', false);
$row.toggleClass('row-active', true);
$('body').toggleClass('panel-active', true);
var hideColumns = api.columns('.hide-panel');
hideColumns.visible(false);
// Populate the pdf button if there is one
if ( response.results[index].pdf_url ) {
$modal.find('.js-pdf_url').attr('href', response.results[index].pdf_url);
} else {
$modal.find('.js-pdf_url').remove();
}
function identity(value) {
return value;
}

// Set focus on the close button
$('.js-hide').focus();
var MODAL_TRIGGER_CLASS = 'js-panel-trigger';
var MODAL_TRIGGER_HTML = '<i class="icon arrow--right"></li>';

// When under $large-screen
// TODO figure way to share these values with CSS.
if ($(document).width() < 980) {
api.columns('.hide-panel-tablet').visible(false);
function modalRenderRow(row, data, index) {
row.classList.add(MODAL_TRIGGER_CLASS);
}

function modalRenderFactory(template, fetch) {
fetch = fetch || identity;
return function(api, data, response) {
var $table = $(api.table().node());
var $modal = $('#datatable-modal');

// Move the modal to the results div.
$modal.appendTo($table);
$table.find('tr').attr('tabindex', 0);

$table.on('click keypress', '.js-panel-toggle tr.' + MODAL_TRIGGER_CLASS, function(e) {
if (e.which === 13 || e.type === 'click') {
var $target = $(e.target);
if ($target.is('a')) {
return true;
}
if ( !$target.closest('td').hasClass('dataTables_empty') ) {
var $row = $target.closest('tr');
var index = api.row($row).index();
$.when(fetch(response.results[index])).done(function(fetched) {
$modal.find('.js-panel-content').html(template(fetched));
$modal.attr('aria-hidden', 'false');
$row.siblings().toggleClass('row-active', false);
$row.toggleClass('row-active', true);
$('body').toggleClass('panel-active', true);
var hideColumns = api.columns('.hide-panel');
hideColumns.visible(false);

// Populate the pdf button if there is one
if (fetched.pdf_url) {
$modal.find('.js-pdf_url').attr('href', fetched.pdf_url);
} else {
$modal.find('.js-pdf_url').remove();
}

// Set focus on the close button
$('.js-hide').focus();

// When under $large-screen
// TODO figure way to share these values with CSS.
if ($(document).width() < 980) {
api.columns('.hide-panel-tablet').visible(false);
}
});
}
}
}
});
});

$modal.on('click', '.js-panel-close', function(ev) {
ev.preventDefault();
hidePanel(api, $modal);
});
$modal.on('click', '.js-panel-close', function(e) {
e.preventDefault();
hidePanel(api, $modal);
});
};
}

function hidePanel(api, $modal) {
Expand Down Expand Up @@ -456,8 +474,11 @@ module.exports = {
urlColumn: urlColumn,
barCurrencyColumn: barCurrencyColumn,
dateColumn: dateColumn,
modalAfterRender: modalAfterRender,
barsAfterRender: barsAfterRender,
modalRenderRow: modalRenderRow,
modalRenderFactory: modalRenderFactory,
MODAL_TRIGGER_CLASS: MODAL_TRIGGER_CLASS,
MODAL_TRIGGER_HTML: MODAL_TRIGGER_HTML,
offsetCallbacks: offsetCallbacks,
seekCallbacks: seekCallbacks,
initTable: initTable,
Expand Down
11 changes: 7 additions & 4 deletions static/js/pages/candidates.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var columns = [
width: '20px',
orderable: false,
render: function(data, type, row, meta) {
return '<i class="icon arrow--right"></i>';
return tables.MODAL_TRIGGER_HTML;
}
}
];
Expand All @@ -47,9 +47,12 @@ $(document).ready(function() {
'candidates',
{},
columns,
_.extend(tables.offsetCallbacks, {
afterRender: tables.modalAfterRender.bind(undefined, candidatesTemplate)
_.extend({}, tables.offsetCallbacks, {
afterRender: tables.modalRenderFactory(candidatesTemplate)
}),
{useFilters: true}
{
useFilters: true,
rowCallback: tables.modalRenderRow
}
);
});
Loading