Last active
June 26, 2020 23:12
-
-
Save mattborn/8c0a2a4e6f74beef81eed98b6174c4fc to your computer and use it in GitHub Desktop.
Pivot Prototype
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>Pivot Prototype</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/Faker/3.1.0/faker.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script> | |
<script src="https://unpkg.com/moment"></script> | |
<script src="https://unpkg.com/@ag-grid-enterprise/all-modules/dist/ag-grid-enterprise.min.noStyle.js"></script> | |
<link rel="stylesheet" href="https://unpkg.com/@ag-grid-community/all-modules/dist/styles/ag-grid.css"> | |
<link rel="stylesheet" href="https://unpkg.com/@ag-grid-community/all-modules/dist/styles/ag-theme-alpine.css"> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body> | |
<div class="Page-Section"> | |
<h2>Example 1</h2> | |
<p>Many time periods per client, many trends per row group</p> | |
<div id="Example-1" class="ag-theme-alpine"></div> | |
</div> | |
<div class="Page-Section"> | |
<h2>Example Data Quality Pivot Table</h2> | |
<p>Four dimensions: service month, paid month, carrier name, and tie out measures (sum claims, count distinct members)</p> | |
<div id="Reconcile" class="ag-theme-alpine"></div> | |
</div> | |
<script src="scripts.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// wrap all direct body children innerHTML with div.Center | |
Array.from(document.body.children).forEach(child => { | |
const div = document.createElement('div') | |
div.className = 'Center' | |
while (child.firstChild) div.appendChild(child.firstChild) | |
child.appendChild(div) | |
}) | |
const MONTHS = 12 | |
const gridOptions_Shared = { | |
defaultColDef: { | |
flex: 1, | |
// enableRowGroup: true, | |
// enablePivot: true, | |
// filter: 'agTextColumnFilter', | |
resizable: true, | |
sortable: true, | |
}, | |
autoGroupColumnDef: { | |
cellRendererParams: { | |
suppressCount: true, | |
}, | |
minWidth: 200, | |
}, | |
domLayout: 'autoHeight', | |
enableRangeSelection: true, | |
// floatingFilter: true, | |
// masterDetail: true, | |
onFirstDataRendered: (params) => params.api.sizeColumnsToFit(), | |
sideBar: 'columns', | |
} | |
const gridOptions_Reconcile = Object.assign({ | |
columnDefs: [ | |
{headerName: 'Service Month', field: 'service_month', comparator: dateComparator, rowGroup: true, enableRowGroup: true}, | |
{headerName: 'Paid Month', field: 'paid_month', comparator: dateComparator, pivotComparator: dateComparator, rowGroup: true, enableRowGroup: true, enablePivot: true}, | |
{headerName: 'Carrier', field: 'carrier', enablePivot: true}, | |
{headerName: 'Employer Paid (Med)', field: 'dollars', aggFunc: 'sum'}, | |
], | |
rowData: _.range(MONTHS * MONTHS).map(makeRow), // number of service months | |
}, gridOptions_Shared) | |
new agGrid.Grid(document.querySelector('#Reconcile'), gridOptions_Reconcile) | |
// functions | |
function makeRow(obj, i) { | |
const carriers = [] | |
const serviceDate = moment().subtract(Math.ceil((i + 1) / MONTHS), 'month').valueOf() | |
return Object.assign(obj, { | |
service_month: moment(serviceDate).format('MMM YYYY'), | |
paid_month: moment().subtract(i % MONTHS + 1, 'month').format('MMM YYYY'), | |
// paid_month: moment(serviceDate + Math.random() * (moment().valueOf() - serviceDate)).format('MMM YYYY'), | |
carrier: faker.random.boolean() ? 'Aetna' : 'Cigna', | |
// sum: faker.phone.phoneNumber('#########'), | |
dollars: faker.random.number() | |
}) | |
} | |
function dateComparator(date1, date2) { | |
var a = moment(date1, 'MMM YYYY').valueOf() | |
var b = moment(date2, 'MMM YYYY').valueOf() | |
if (a === null && b === null) return 0 | |
if (a === null) return -1 | |
if (b === null) return 1 | |
return a - b | |
} | |
// simulate interactions | |
// gridOptions_Reconcile.columnApi.setPivotMode(true) | |
gridOptions_Reconcile.columnApi.setPivotColumns(['paid_month','carrier']) | |
gridOptions_Reconcile.columnApi.setRowGroupColumns(['service_month']) | |
// Example 1 | |
const gridOptions_Example_1 = Object.assign({ | |
columnDefs: [ | |
{headerName: 'Client(s)', field: 'client', rowGroup: true, enableRowGroup: true}, | |
{headerName: 'Time Period', field: 'time_period', rowGroup: true, enableRowGroup: true, enablePivot: true}, | |
{headerName: 'Measure', field: 'measure', rowGroup: true, enableRowGroup: true}, | |
{headerName: 'Data Category', field: 'category'}, | |
{headerName: 'Trend', field: 'trend', aggFunc: 'first', hide: true}, | |
], | |
rowData: [ | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Allowed Amount', | |
category: 'Overall Trend', | |
trend: '-0.5%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Allowed Amount', | |
category: 'Medical Trend', | |
trend: '-0.6%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Allowed Amount', | |
category: 'Pharmacy Trend', | |
trend: '-0.3%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Member Cost Sharing', | |
category: 'Overall Trend', | |
trend: '-0.5%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Member Cost Sharing', | |
category: 'Medical Trend', | |
trend: '-0.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Member Cost Sharing', | |
category: 'Pharmacy Trend', | |
trend: '-3.4%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Net Pay', | |
category: 'Overall Trend', | |
trend: '-0.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Net Pay', | |
category: 'Medical Trend', | |
trend: '0.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP2', | |
measure: 'Net Pay', | |
category: 'Pharmacy Trend', | |
trend: '-0.7%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Allowed Amount', | |
category: 'Overall Trend', | |
trend: '4.8%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Allowed Amount', | |
category: 'Medical Trend', | |
trend: '4.7%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Allowed Amount', | |
category: 'Pharmacy Trend', | |
trend: '5.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Member Cost Sharing', | |
category: 'Overall Trend', | |
trend: '5.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Member Cost Sharing', | |
category: 'Medical Trend', | |
trend: '4.7%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Member Cost Sharing', | |
category: 'Pharmacy Trend', | |
trend: '7.6%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Net Pay', | |
category: 'Overall Trend', | |
trend: '4.8%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Net Pay', | |
category: 'Medical Trend', | |
trend: '4.9%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP2 – TP3', | |
measure: 'Net Pay', | |
category: 'Pharmacy Trend', | |
trend: '4.3%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Overall Trend', | |
trend: '2.1%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Medical Trend', | |
trend: '2.0%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Pharmacy Trend', | |
trend: '2.4%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Overall Trend', | |
trend: '2.3%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Medical Trend', | |
trend: '2.3%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Pharmacy Trend', | |
trend: '1.9%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Overall Trend', | |
trend: '2.3%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Medical Trend', | |
trend: '2.5%', | |
}, | |
{ | |
client: 'Client A', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Pharmacy Trend', | |
trend: '1.8%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Overall Trend', | |
trend: '3.6%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Medical Trend', | |
trend: '3.8%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Allowed Amount', | |
category: 'Pharmacy Trend', | |
trend: '2.6%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Overall Trend', | |
trend: '1.1%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Medical Trend', | |
trend: '3.1%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Member Cost Sharing', | |
category: 'Pharmacy Trend', | |
trend: '-5.5%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Overall Trend', | |
trend: '3.6%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Medical Trend', | |
trend: '3.7%', | |
}, | |
{ | |
client: 'BoB', | |
time_period: 'TP1 – TP3 (Annualized)', | |
measure: 'Net Pay', | |
category: 'Pharmacy Trend', | |
trend: '3.5%', | |
}, | |
], | |
}, gridOptions_Shared) | |
new agGrid.Grid(document.querySelector('#Example-1'), gridOptions_Example_1) | |
gridOptions_Example_1.columnApi.setPivotMode(true) | |
gridOptions_Example_1.columnApi.setPivotColumns(['client','time_period']) | |
gridOptions_Example_1.columnApi.setRowGroupColumns(['measure', 'category']) | |
gridOptions_Example_1.api.forEachNode((node) => node.setExpanded(true)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import url('https://yourlifechurch.org/assets/fontawesome-pro-5/css/all.min.css'); | |
/* cascade */ | |
:focus { | |
outline: 1px solid #36fc; | |
outline-offset: 2px; | |
} | |
:disabled { | |
cursor: not-allowed; | |
opacity: .3; | |
} | |
:disabled:hover { transform: none; } | |
body { | |
-webkit-font-smoothing: antialiased; | |
background: #fff; | |
color: #234; | |
font: 500 15px/1.5 'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif; | |
/* letter-spacing: -.02em; */ | |
margin: 0; | |
} | |
button { | |
border-radius: 4px; | |
box-shadow: 1px 2px 4px #0124; | |
cursor: pointer; | |
line-height: 24px; | |
padding: 4px 12px; | |
} | |
button:hover { transform: translateY(-1px); } | |
button:active { transform: none; } | |
button i { | |
font-size: 14px; | |
margin-right: 4px; | |
} | |
h1 { | |
font: bold 48px/48px 'SF Pro Display', sans-serif; | |
letter-spacing: -0.03em; | |
} | |
input { | |
font-weight: 600; | |
line-height: 1; | |
} | |
/* stop padding from being added to width or height */ | |
/* { box-sizing: border-box; } */ | |
/* reset */ | |
a { | |
color: #28f; | |
text-decoration: none; | |
} | |
button, | |
input { | |
background: #fff; | |
border: none; | |
color: inherit; | |
cursor: pointer; | |
font: inherit; | |
} | |
input { padding: 0; } | |
input:focus { outline: none; } | |
label { cursor: pointer; } | |
h2 { | |
font-size: 16px; | |
line-height: 16px; | |
margin: 0 0 16px; | |
} | |
/* layout helpers */ | |
.Center { | |
margin: 0 auto; | |
max-width: 944px; | |
} | |
.Encapsulate { position: relative; } | |
.Flex, | |
.Justify { | |
align-items: center; | |
display: flex; | |
} | |
.Justify { justify-content: space-between; } | |
/* components: demo only */ | |
/* components: table examples */ | |
.Page-Section { padding: 48px 0 24px; } | |
.Page-Section:nth-child(odd) { background: #f1f3f5; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment