commit
d4e8dcd0a6
45
js/components/tables/spend_table.js
Normal file
45
js/components/tables/spend_table.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { set } from 'vue/dist/vue'
|
||||||
|
import { formatDollars } from '../../lib/dollars'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'spend-table',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
projects: Object,
|
||||||
|
workspace: Object,
|
||||||
|
environments: Object,
|
||||||
|
currentMonthIndex: String,
|
||||||
|
prevMonthIndex: String,
|
||||||
|
twoMonthsAgoIndex: String
|
||||||
|
},
|
||||||
|
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
projectsState: this.projects
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created: function () {
|
||||||
|
Object.keys(this.projects).forEach(project => {
|
||||||
|
set(this.projectsState[project], 'isVisible', false)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
toggle: function (e, projectName) {
|
||||||
|
this.projectsState = Object.assign(this.projectsState, {
|
||||||
|
[projectName]: Object.assign(this.projectsState[projectName],{
|
||||||
|
isVisible: !this.projectsState[projectName].isVisible
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
formatDollars: function (value) {
|
||||||
|
return formatDollars(value, false)
|
||||||
|
},
|
||||||
|
|
||||||
|
round: function (value) {
|
||||||
|
return Math.round(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import NewProject from './components/forms/new_project'
|
|||||||
import Modal from './mixins/modal'
|
import Modal from './mixins/modal'
|
||||||
import selector from './components/selector'
|
import selector from './components/selector'
|
||||||
import BudgetChart from './components/charts/budget_chart'
|
import BudgetChart from './components/charts/budget_chart'
|
||||||
|
import SpendTable from './components/tables/spend_table'
|
||||||
import CcpoApproval from './components/forms/ccpo_approval'
|
import CcpoApproval from './components/forms/ccpo_approval'
|
||||||
import LocalDatetime from './components/local_datetime'
|
import LocalDatetime from './components/local_datetime'
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ const app = new Vue({
|
|||||||
NewProject,
|
NewProject,
|
||||||
selector,
|
selector,
|
||||||
BudgetChart,
|
BudgetChart,
|
||||||
|
SpendTable,
|
||||||
CcpoApproval,
|
CcpoApproval,
|
||||||
LocalDatetime
|
LocalDatetime
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
export const formatDollars = value => `$${value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}`
|
export const formatDollars = (value, cents = true) => {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return cents
|
||||||
|
? `$${value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}`
|
||||||
|
: `$${value.toFixed(0).replace(/\d(?=(\d{3})+(?!\d))/g, '$&,')}`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
export const abbreviateDollars = (value, decimals = 1) => {
|
export const abbreviateDollars = (value, decimals = 1) => {
|
||||||
if (value === null) { return null } // terminate early
|
if (value === null) { return null } // terminate early
|
||||||
|
@ -15,4 +15,10 @@ meter {
|
|||||||
&::-moz-meter-bar {
|
&::-moz-meter-bar {
|
||||||
background: $color-primary;
|
background: $color-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.meter__fallback {
|
||||||
|
display: inline-block;
|
||||||
|
background: $color-primary;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@
|
|||||||
@include panel-margin;
|
@include panel-margin;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
|
|
||||||
|
@include ie-only {
|
||||||
|
border-collapse: separate;
|
||||||
|
}
|
||||||
|
|
||||||
th, td {
|
th, td {
|
||||||
&.table-cell--align-right {
|
&.table-cell--align-right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -217,7 +217,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.previous-month {
|
&.previous-month {
|
||||||
opacity: 0.65;
|
color: $color-gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.meter-cell {
|
&.meter-cell {
|
||||||
@ -250,9 +250,12 @@
|
|||||||
@include media($medium-screen) {
|
@include media($medium-screen) {
|
||||||
display: block;
|
display: block;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
|
background-color: rgba($color-blue, 0.65);
|
||||||
|
border-radius: $gap/2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2.3rem;
|
top: 2.3rem;
|
||||||
left: $gap;
|
left: $gap / 2;
|
||||||
|
padding: 0 ($gap / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,6 +280,13 @@
|
|||||||
|
|
||||||
.spend-table__project__env {
|
.spend-table__project__env {
|
||||||
margin-left: $gap;
|
margin-left: $gap;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
td, th {
|
||||||
|
padding-bottom: $gap * 5;
|
||||||
|
box-shadow: inset 0 (-$gap * 2.5) 0 $color-gray-lightest;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<meter value='{{ spent }}' min='0' max='{{ budget }}' title='{{ spent | dollars }} Total spend to date'></meter>
|
<meter value='{{ spent }}' min='0' max='{{ budget }}' title='{{ spent | dollars }} Total spend to date'>
|
||||||
|
<div class='meter__fallback' style='width:{{ (spent / budget) * 100 }}%;'></div>
|
||||||
|
</meter>
|
||||||
|
|
||||||
<dl class='spend-summary__spent'>
|
<dl class='spend-summary__spent'>
|
||||||
<dt>Total spend to date</dt>
|
<dt>Total spend to date</dt>
|
||||||
@ -223,14 +225,22 @@
|
|||||||
|
|
||||||
<div class='spend-table responsive-table-wrapper'>
|
<div class='spend-table responsive-table-wrapper'>
|
||||||
<div class='spend-table__header'>
|
<div class='spend-table__header'>
|
||||||
<h2 class='spend-table__title'>Total spend per month</h2>
|
<h2 class='spend-table__title'>Total spend per month </h2>
|
||||||
|
|
||||||
<select name='month' id='month' class='spend-table__month-select'>
|
<select name='month' id='month' class='spend-table__month-select'>
|
||||||
<option value='03/2019'>{{ current_month.strftime('%B %Y') }}</option>
|
<option value='03/2019'>{{ current_month.strftime('%B %Y') }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table>
|
<spend-table
|
||||||
|
v-bind:projects='{{ monthly_totals['projects'] | tojson }}'
|
||||||
|
v-bind:workspace='{{ workspace_totals | tojson }}'
|
||||||
|
v-bind:environments='{{ monthly_totals['environments'] | tojson }}'
|
||||||
|
current-month-index='{{ current_month_index }}'
|
||||||
|
prev-month-index='{{ prev_month_index }}'
|
||||||
|
two-months-ago-index='{{ two_months_ago_index }}'
|
||||||
|
inline-template>
|
||||||
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th scope='col'><span class='usa-sr-only'>Spending scope</span></th>
|
<th scope='col'><span class='usa-sr-only'>Spending scope</span></th>
|
||||||
<th scope='col' class='table-cell--align-right previous-month'>{{ two_months_ago.strftime('%B %Y') }}</th>
|
<th scope='col' class='table-cell--align-right previous-month'>{{ two_months_ago.strftime('%B %Y') }}</th>
|
||||||
@ -251,9 +261,63 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
{% for project_name, project_totals in monthly_totals['projects'].items() %}
|
<tbody v-for='(project, name) in projectsState' class='spend-table__project'>
|
||||||
<tbody is='toggler' class='spend-table__project'>
|
<tr>
|
||||||
<template slot-scope='props'>
|
<th scope='rowgroup'>
|
||||||
|
<button v-on:click='toggle($event, name)' class='icon-link icon-link--large spend-table__project__toggler'>
|
||||||
|
<template v-if='project.isVisible'>{{ Icon('caret_down') }}</template>
|
||||||
|
<template v-else>{{ Icon('caret_right') }}</template>
|
||||||
|
<span v-html='name'></span>
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<td class='table-cell--align-right previous-month'>
|
||||||
|
<span v-html='formatDollars(project[twoMonthsAgoIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--align-right previous-month'>
|
||||||
|
<span v-html='formatDollars(project[prevMonthIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--align-right current-month'>
|
||||||
|
<span v-html='formatDollars(project[currentMonthIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--expand current-month meter-cell'>
|
||||||
|
<span class='spend-table__meter-value'>
|
||||||
|
<span v-html='round( 100 * ((project[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%"'></span>
|
||||||
|
</span>
|
||||||
|
<meter v-bind:value='project[currentMonthIndex] || 0' min='0' v-bind:max='workspace[currentMonthIndex] || 1'>
|
||||||
|
<div class='meter__fallback' v-bind:style='"width:" + round( 100 * ((project[currentMonthIndex] || 0) / (workspace[currentMonthIndex] || 1) )) + "%;"'></div>
|
||||||
|
</meter>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr v-for='(environment, envName) in environments[name]' v-show='project.isVisible' class='spend-table__project__env'>
|
||||||
|
<th scope='rowgroup'>
|
||||||
|
<a href='#' class='icon-link spend-table__project__env'>
|
||||||
|
{{ Icon('link') }}
|
||||||
|
<span v-html='envName'></span>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<td class='table-cell--align-right previous-month'>
|
||||||
|
<span v-html='formatDollars(environment[twoMonthsAgoIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--align-right previous-month'>
|
||||||
|
<span v-html='formatDollars(environment[prevMonthIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--align-right current-month'>
|
||||||
|
<span v-html='formatDollars(environment[currentMonthIndex] || 0)'></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class='table-cell--expand current-month'></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
{# {% for project_name, project_totals in monthly_totals['projects'].items() %}
|
||||||
|
<tbody is='tbody-toggler' class='spend-table__project'>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope='rowgroup'>
|
<th scope='rowgroup'>
|
||||||
<button v-on:click='props.toggle' class='icon-link icon-link--large spend-table__project__toggler'>
|
<button v-on:click='props.toggle' class='icon-link icon-link--large spend-table__project__toggler'>
|
||||||
@ -280,10 +344,12 @@
|
|||||||
<td class='table-cell--expand current-month'></td>
|
<td class='table-cell--expand current-month'></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endfor %}
|
{% endfor %} #}
|
||||||
</table>
|
</table>
|
||||||
|
</spend-table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user