From d882c552dce65afb3e54a4f8337ad5869dd5b404 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Thu, 6 Sep 2018 16:29:36 -0400 Subject: [PATCH 01/18] starting charting --- atst/domain/reports.py | 6 + atst/routes/workspaces.py | 1 + js/components/charts/budget_chart.js | 65 +++++++ js/index.js | 4 +- package.json | 2 + templates/workspaces/reports/index.html | 13 ++ yarn.lock | 234 ++++++++++++++++++++++++ 7 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 js/components/charts/budget_chart.js diff --git a/atst/domain/reports.py b/atst/domain/reports.py index 15df3ba4..e3e71319 100644 --- a/atst/domain/reports.py +++ b/atst/domain/reports.py @@ -196,3 +196,9 @@ class Reports: "projects": project_totals, "workspace": workspace_totals, } + + @classmethod + def cumulative_budget(cls, alternate): + return { + "months": CUMULATIVE_BUDGET_BELUGA if alternate else CUMULATIVE_BUDGET_AARDVARK + } diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py index e8d0df8d..f13f6ec1 100644 --- a/atst/routes/workspaces.py +++ b/atst/routes/workspaces.py @@ -87,6 +87,7 @@ def workspace_reports(workspace_id): return render_template( "workspaces/reports/index.html", + cumulative_budget=Reports.cumulative_budget(alternate_reports), workspace_totals=Reports.workspace_totals(alternate_reports), monthly_totals=Reports.monthly_totals(alternate_reports), current_month=current_month, diff --git a/js/components/charts/budget_chart.js b/js/components/charts/budget_chart.js new file mode 100644 index 00000000..bc721f42 --- /dev/null +++ b/js/components/charts/budget_chart.js @@ -0,0 +1,65 @@ +import * as d3 from 'd3' +import { format } from 'date-fns' + +export default { + name: 'budget-chart', + props: { + currentMonth: String, + months: Object + }, + + data: function () { + return { + numMonths: 10, + focusedMonthPosition: 4, // 5th spot in zero-based index, + height: 300, + width: 0, + displayedMonths: [] + } + }, + + computed: { + + }, + + mounted: function () { + console.log(this.displayedMonths) + this._setDisplayedMonths() + this._setMetrics() + }, + + methods: { + _setMetrics: function () { + this.width = this.$refs.panel.clientWidth + // for (let i = 0; i < this.numMonths; i++) { + // this.displayedMonths[i].metrics.x = (this.width / this.numMonths) + // } + }, + + _setDisplayedMonths: function () { + const [month, year] = this.currentMonth.split('/') + const monthsRange = [] + const monthsBack = this.focusedMonthPosition + const monthsForward = this.numMonths - this.focusedMonthPosition - 1 + const start = new Date(year, month - 1 - monthsBack) + + for (let i = 0; i < this.numMonths; i++) { + const date = new Date(start.getFullYear(), start.getMonth() + i) + const index = format(date, 'MM/YYYY') + monthsRange.push({ + date: { + month: format(date, 'MMM'), + year: format(date,'YYYY') + }, + budget: this.months[index] || null, + isHighlighted: this.currentMonth === index, + metrics: { + x: 0, + width: 0 + } + }) + } + this.displayedMonths = monthsRange + } + } +} diff --git a/js/index.js b/js/index.js index 2ce01476..aa659d3a 100644 --- a/js/index.js +++ b/js/index.js @@ -14,6 +14,7 @@ import toggler from './components/toggler' import NewProject from './components/forms/new_project' import Modal from './mixins/modal' import selector from './components/selector' +import BudgetChart from './components/charts/budget_chart' Vue.use(VTooltip) @@ -30,7 +31,8 @@ const app = new Vue({ poc, financial, NewProject, - selector + selector, + BudgetChart }, mounted: function() { const modalOpen = document.querySelector("#modalOpen") diff --git a/package.json b/package.json index 4c942980..10e57947 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "dependencies": { "autoprefixer": "^9.1.3", "babel-polyfill": "^6.26.0", + "d3": "^5.7.0", + "date-fns": "^1.29.0", "npm": "^6.0.1", "parcel": "^1.9.7", "text-mask-addons": "^3.8.0", diff --git a/templates/workspaces/reports/index.html b/templates/workspaces/reports/index.html index 0bc1e503..b6a8f2ac 100644 --- a/templates/workspaces/reports/index.html +++ b/templates/workspaces/reports/index.html @@ -94,6 +94,19 @@ {% set prev_month_index = prev_month.strftime('%m/%Y') %} {% set two_months_ago_index = two_months_ago.strftime('%m/%Y') %} + +
+
+

Cumulative Budget

+
+ + + + + +
+
+

Total spend per month

diff --git a/yarn.lock b/yarn.lock index cde1e83b..e0dc1fae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1444,6 +1444,10 @@ command-exists@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.7.tgz#16828f0c3ff2b0c58805861ef211b64fc15692a8" +commander@2: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + commander@^2.11.0, commander@^2.9.0, commander@~2.16.0: version "2.16.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" @@ -1805,12 +1809,232 @@ cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" +d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" + +d3-axis@1: + version "1.0.12" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9" + +d3-brush@1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.6.tgz#33691f2032d9db6c5d8cb684ff255a9883629e21" + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3-chord@1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f" + dependencies: + d3-array "1" + d3-path "1" + +d3-collection@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" + +d3-color@1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f" + +d3-contour@1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3" + dependencies: + d3-array "^1.1.1" + +d3-dispatch@1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.5.tgz#e25c10a186517cd6c82dd19ea018f07e01e39015" + +d3-drag@1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.3.tgz#46e206ad863ec465d88c588098a1df444cd33c64" + dependencies: + d3-dispatch "1" + d3-selection "1" + +d3-dsv@1: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.10.tgz#4371c489a2a654a297aca16fcaf605a6f31a6f51" + dependencies: + commander "2" + iconv-lite "0.4" + rw "1" + +d3-ease@1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb" + +d3-fetch@1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.1.2.tgz#957c8fbc6d4480599ba191b1b2518bf86b3e1be2" + dependencies: + d3-dsv "1" + +d3-force@1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.1.2.tgz#16664d0ac71d8727ef5effe0b374feac8050d6cd" + dependencies: + d3-collection "1" + d3-dispatch "1" + d3-quadtree "1" + d3-timer "1" + +d3-format@1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562" + +d3-geo@1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.11.1.tgz#3f35e582c0d29296618b02a8ade0fdffb2c0e63c" + dependencies: + d3-array "1" + +d3-hierarchy@1: + version "1.1.8" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz#7a6317bd3ed24e324641b6f1e76e978836b008cc" + +d3-interpolate@1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.3.2.tgz#417d3ebdeb4bc4efcc8fd4361c55e4040211fd68" + dependencies: + d3-color "1" + +d3-path@1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.7.tgz#8de7cd693a75ac0b5480d3abaccd94793e58aae8" + +d3-polygon@1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.5.tgz#9a645a0a64ff6cbf9efda96ee0b4a6909184c363" + +d3-quadtree@1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.5.tgz#305394840b01f51a341a0da5008585e837fe7e9b" + +d3-random@1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291" + +d3-scale-chromatic@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz#dad4366f0edcb288f490128979c3c793583ed3c0" + dependencies: + d3-color "1" + d3-interpolate "1" + +d3-scale@2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.1.2.tgz#4e932b7b60182aee9073ede8764c98423e5f9a94" + dependencies: + d3-array "^1.2.0" + d3-collection "1" + d3-format "1" + d3-interpolate "1" + d3-time "1" + d3-time-format "2" + +d3-selection@1, d3-selection@^1.1.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.2.tgz#6e70a9df60801c8af28ac24d10072d82cbfdf652" + +d3-shape@1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.2.tgz#f9dba3777a5825f9a8ce8bc928da08c17679e9a7" + dependencies: + d3-path "1" + +d3-time-format@2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b" + dependencies: + d3-time "1" + +d3-time@1: + version "1.0.10" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.10.tgz#8259dd71288d72eeacfd8de281c4bf5c7393053c" + +d3-timer@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba" + +d3-transition@1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.1.3.tgz#3a435b05ce9cef9524fe0d38121cfb6905331ca6" + dependencies: + d3-color "1" + d3-dispatch "1" + d3-ease "1" + d3-interpolate "1" + d3-selection "^1.1.0" + d3-timer "1" + +d3-voronoi@1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297" + +d3-zoom@1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.3.tgz#f444effdc9055c38077c4299b4df999eb1d47ccb" + dependencies: + d3-dispatch "1" + d3-drag "1" + d3-interpolate "1" + d3-selection "1" + d3-transition "1" + +d3@^5.7.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-5.7.0.tgz#f189d338bdde62acf02f308918e0ec34dd7568f9" + dependencies: + d3-array "1" + d3-axis "1" + d3-brush "1" + d3-chord "1" + d3-collection "1" + d3-color "1" + d3-contour "1" + d3-dispatch "1" + d3-drag "1" + d3-dsv "1" + d3-ease "1" + d3-fetch "1" + d3-force "1" + d3-format "1" + d3-geo "1" + d3-hierarchy "1" + d3-interpolate "1" + d3-path "1" + d3-polygon "1" + d3-quadtree "1" + d3-random "1" + d3-scale "2" + d3-scale-chromatic "1" + d3-selection "1" + d3-shape "1" + d3-time "1" + d3-time-format "2" + d3-timer "1" + d3-transition "1" + d3-voronoi "1" + d3-zoom "1" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" +date-fns@^1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -2806,6 +3030,12 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +iconv-lite@0.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + dependencies: + safer-buffer ">= 2.1.2 < 3" + iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" @@ -5693,6 +5923,10 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" From 22dc20ab73e8c8add0d2b40eb2c2e43f8eba3811 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:43:07 -0400 Subject: [PATCH 02/18] budget chart vue component --- js/components/charts/budget_chart.js | 102 +++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 15 deletions(-) diff --git a/js/components/charts/budget_chart.js b/js/components/charts/budget_chart.js index bc721f42..74839f49 100644 --- a/js/components/charts/budget_chart.js +++ b/js/components/charts/budget_chart.js @@ -1,39 +1,90 @@ import * as d3 from 'd3' import { format } from 'date-fns' +import { abbreviateDollars, formatDollars } from '../../lib/dollars' + +const TOP_OFFSET = 20 +const BOTTOM_OFFSET = 60 +const CHART_HEIGHT = 360 export default { name: 'budget-chart', props: { currentMonth: String, - months: Object + months: Object, + budget: String }, data: function () { + const heightScale = this.budget / (CHART_HEIGHT - TOP_OFFSET - BOTTOM_OFFSET) return { numMonths: 10, - focusedMonthPosition: 4, // 5th spot in zero-based index, - height: 300, + focusedMonthPosition: 4, + height: CHART_HEIGHT, + heightScale, + budgetHeight: CHART_HEIGHT - BOTTOM_OFFSET - (this.budget / heightScale), + baseHeight: CHART_HEIGHT - BOTTOM_OFFSET, width: 0, - displayedMonths: [] + displayedMonths: [], + spendPath: '', + projectedPath: '', + displayBudget: formatDollars(parseFloat(this.budget)) } }, - computed: { - - }, - mounted: function () { - console.log(this.displayedMonths) this._setDisplayedMonths() this._setMetrics() + addEventListener('resize', this._setMetrics) }, methods: { _setMetrics: function () { this.width = this.$refs.panel.clientWidth - // for (let i = 0; i < this.numMonths; i++) { - // this.displayedMonths[i].metrics.x = (this.width / this.numMonths) - // } + this.spendPath = '' + this.projectedPath = '' + + let lastSpend = 0 + let lastSpendPoint = '' + + for (let i = 0; i < this.numMonths; i++) { + const { metrics, budget } = this.displayedMonths[i] + const blockWidth = (this.width / this.numMonths) + const blockX = blockWidth * i + const spend = budget + ? budget.spend || lastSpend + : 0 + const cumulative = budget + ? budget.cumulative || budget.projected + : 0 + const barHeight = spend / this.heightScale + lastSpend = spend + const cumulativeY = this.height - (cumulative / this.heightScale) - BOTTOM_OFFSET + const cumulativeX = blockX + blockWidth/2 + const cumulativePoint = `${cumulativeX} ${cumulativeY}` + + this.displayedMonths[i].metrics = Object.assign(metrics, { + blockWidth, + blockX, + barHeight, + barWidth: 30, + barX: blockX + (blockWidth/2 - 15), + barY: this.height - barHeight - BOTTOM_OFFSET, + cumulativeR: 2.5, + cumulativeY, + cumulativeX + }) + + if (budget && budget.spend) { + this.spendPath += this.spendPath === '' ? 'M' : ' L' + this.spendPath += cumulativePoint + lastSpendPoint = cumulativePoint + } + + if (budget && budget.projected) { + this.projectedPath += this.projectedPath === '' ? `M${lastSpendPoint} L` : ' L' + this.projectedPath += cumulativePoint + } + } }, _setDisplayedMonths: function () { @@ -43,22 +94,43 @@ export default { const monthsForward = this.numMonths - this.focusedMonthPosition - 1 const start = new Date(year, month - 1 - monthsBack) + let previousAmount = 0 + for (let i = 0; i < this.numMonths; i++) { const date = new Date(start.getFullYear(), start.getMonth() + i) const index = format(date, 'MM/YYYY') + const budget = this.months[index] || null + const spendAmount = budget ? budget.spend || previousAmount : 0 + const cumulativeAmount = budget ? budget.cumulative || budget.projected : 0 + previousAmount = spendAmount + monthsRange.push({ + budget, + spendAmount: formatDollars(spendAmount), + abbreviatedSpend: abbreviateDollars(spendAmount), + cumulativeAmount: formatDollars(cumulativeAmount), + abbreviatedCumulative: abbreviateDollars(cumulativeAmount), date: { + monthIndex: format(date, 'M'), month: format(date, 'MMM'), year: format(date,'YYYY') }, - budget: this.months[index] || null, isHighlighted: this.currentMonth === index, metrics: { - x: 0, - width: 0 + blockWidth: 0, + blockX: 0, + barHeight: 0, + barWidth: 0, + barX: 0, + barY: 0, + cumulativeY: 0, + cumulativeX: 0, + cumulativeR: 0 } }) + } + console.log(monthsRange) this.displayedMonths = monthsRange } } From 65900b259710169bfbf088e48f4c68d5ef67134f Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:43:21 -0400 Subject: [PATCH 03/18] budget chart svg markup/vue template --- templates/workspaces/reports/index.html | 103 ++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/templates/workspaces/reports/index.html b/templates/workspaces/reports/index.html index b6a8f2ac..ba788f1e 100644 --- a/templates/workspaces/reports/index.html +++ b/templates/workspaces/reports/index.html @@ -93,16 +93,107 @@ {% set current_month_index = current_month.strftime('%m/%Y') %} {% set prev_month_index = prev_month.strftime('%m/%Y') %} {% set two_months_ago_index = two_months_ago.strftime('%m/%Y') %} + {% set reports_url = url_for("workspaces.workspace_reports", workspace_id=workspace.id) %} - +
-
+

Cumulative Budget

- - - - + + + {# make this clickable to focus on that month #} + + +  |  + + + {# container block #} + + + {# budget bar #} + + + + {# cumulative dot #} + + + {# abbreviated cumulative label #} + + + {# abbreviated spend label #} + + + {# month label #} + + + + + {# spend/projected budget path lines #} + + + + {# max budget line #} + + + Total Budget +
From 870b49778be1a4ec8599ddbc3bc16459e1405649 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:43:30 -0400 Subject: [PATCH 04/18] budget chart styles --- styles/components/_budget_chart.scss | 80 ++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 styles/components/_budget_chart.scss diff --git a/styles/components/_budget_chart.scss b/styles/components/_budget_chart.scss new file mode 100644 index 00000000..351094a2 --- /dev/null +++ b/styles/components/_budget_chart.scss @@ -0,0 +1,80 @@ +.budget-chart { + .budget-chart__header { + border-bottom: 1px solid $color-gray-light; + } + + .budget-chart__block { + fill: $color-white; + cursor: pointer; + + &--highlighted { + fill: $color-aqua-lightest; + } + + &:hover { + fill: $color-aqua-lightest; + } + } + + svg { + display: block; + + a { + text-decoration: none; + &:focus { + outline: none; + stroke: $color-gray-light; + stroke-dasharray: 2px; + } + } + } + + .budget-chart__bar { + fill: $color-blue; + + &--projected { + fill: transparent; + stroke-width: 2px; + stroke: $color-blue; + stroke-dasharray: 2px; + } + } + + .budget-chart__cumulative__dot { + fill: $color-gold; + } + + .budget-chart__projected-path { + stroke-width: 1px; + stroke: $color-gold; + stroke-dasharray: 2px; + fill: none; + } + + .budget-chart__spend-path { + stroke-width: 1px; + stroke: $color-gold; + fill: none; + } + + .budget-chart__budget-line { + stroke-width: 2px; + stroke: $color-gray-light; + stroke-dasharray: 2px; + } + + .budget-chart__label { + @include h6; + font-weight: bold; + text-transform: none; + fill: $color-gray; + + &--strong { + fill: $color-black; + } + } + + .budget-chart__budget-text { + + } +} From 3026ee21755cf16ddd7a667b6c009c76b3b41a78 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:43:38 -0400 Subject: [PATCH 05/18] fix grid overflow --- styles/core/_grid.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/styles/core/_grid.scss b/styles/core/_grid.scss index 17aa81a6..5f75b64f 100644 --- a/styles/core/_grid.scss +++ b/styles/core/_grid.scss @@ -42,5 +42,6 @@ &.col--grow { flex: 1; flex-grow: 1; + overflow: auto } } From 8b5419a8f878ce2a843cc566d847c138ff208879 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:43:49 -0400 Subject: [PATCH 06/18] import budget chart styles --- styles/atat.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/atat.scss b/styles/atat.scss index 3d70a544..ebaaa214 100644 --- a/styles/atat.scss +++ b/styles/atat.scss @@ -34,7 +34,7 @@ @import 'components/search_bar'; @import 'components/forms'; @import 'components/selector'; - +@import 'components/budget_chart'; @import 'sections/login'; @import 'sections/request_approval'; From d0e322b65aa0894fe57cb701d31448b9e24ab39e Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:44:04 -0400 Subject: [PATCH 07/18] use padding not margin --- styles/elements/_panels.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/styles/elements/_panels.scss b/styles/elements/_panels.scss index c18c2e9b..fd10671d 100644 --- a/styles/elements/_panels.scss +++ b/styles/elements/_panels.scss @@ -62,13 +62,13 @@ } .panel__heading { - margin: $gap * 2; + padding: $gap * 2; @include media($medium-screen) { - margin: $gap * 4; + padding: $gap * 4; } &--tight { - margin: $gap*2; + padding: $gap*2; } h1, h2, h3, h4, h5, h6 { From dd5f09c44c4ac70a567ec55374e138d055529981 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Fri, 7 Sep 2018 15:44:23 -0400 Subject: [PATCH 08/18] dollar formatting helper methods --- js/lib/dollars.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 js/lib/dollars.js diff --git a/js/lib/dollars.js b/js/lib/dollars.js new file mode 100644 index 00000000..65fc69ff --- /dev/null +++ b/js/lib/dollars.js @@ -0,0 +1,12 @@ +export const formatDollars = value => `$${value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')}` + +export const abbreviateDollars = (value, decimals = 1) => { + if (value === null) { return null } // terminate early + if (value === 0) { return '0' } // terminate early + var b = (value).toPrecision(2).split("e"), // get power + k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3), // floor at decimals, ceiling at trillions + c = k < 1 ? value.toFixed(0 + decimals) : (value / Math.pow(10, k * 3) ).toFixed(decimals), // divide by power + d = c < 0 ? c : Math.abs(c), // enforce -0 is 0 + e = d + ['', 'k', 'M', 'B', 'T'][k]; // append power + return e; +} From 1742415b495301314946bd8be71d8e6dab1262d0 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Tue, 11 Sep 2018 09:44:28 -0400 Subject: [PATCH 09/18] format --- atst/domain/reports.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/atst/domain/reports.py b/atst/domain/reports.py index e3e71319..7e49e0de 100644 --- a/atst/domain/reports.py +++ b/atst/domain/reports.py @@ -200,5 +200,7 @@ class Reports: @classmethod def cumulative_budget(cls, alternate): return { - "months": CUMULATIVE_BUDGET_BELUGA if alternate else CUMULATIVE_BUDGET_AARDVARK + "months": CUMULATIVE_BUDGET_BELUGA + if alternate + else CUMULATIVE_BUDGET_AARDVARK } From 9cf0ad94f5a54123361429f3efe91d7480fb725f Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Tue, 11 Sep 2018 09:45:11 -0400 Subject: [PATCH 10/18] dont destructure slot props in template --- templates/workspaces/members/edit.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/workspaces/members/edit.html b/templates/workspaces/members/edit.html index ac37cafa..af66d615 100644 --- a/templates/workspaces/members/edit.html +++ b/templates/workspaces/members/edit.html @@ -134,16 +134,16 @@ {% endcall %}
-