Add welcome dashboard
- Add a stats overview API to aggregate global stats - Add bizcharts to the project to render visualisations - WIP: Add stats widgets and visualisations to the dashboard
This commit is contained in:
parent
31e180089e
commit
9511a78d91
|
@ -5,6 +5,7 @@
|
|||
"dependencies": {
|
||||
"antd": "^3.6.5",
|
||||
"axios": "^0.18.0",
|
||||
"bizcharts": "^3.2.5-beta.4",
|
||||
"dayjs": "^1.7.5",
|
||||
"react": "^16.4.1",
|
||||
"react-app-rewire-less": "^2.1.3",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Button, Col, Form, Icon, Input, Modal, notification, Popconfirm, Row, Select, Spin, Table, Tag, Tooltip } from "antd"
|
||||
import { Col, Row, notification, Card, Tooltip, Icon } from "antd"
|
||||
import React from "react";
|
||||
import { Chart, Axis, Geom, Tooltip as BizTooltip } from 'bizcharts';
|
||||
|
||||
import * as cs from "./constants"
|
||||
|
||||
|
@ -8,6 +9,8 @@ class Dashboard extends React.PureComponent {
|
|||
stats: null
|
||||
}
|
||||
|
||||
campaignTypes = ["running", "finished", "paused", "draft", "scheduled", "cancelled"]
|
||||
|
||||
componentDidMount = () => {
|
||||
this.props.pageTitle("Dashboard")
|
||||
|
||||
|
@ -17,17 +20,97 @@ class Dashboard extends React.PureComponent {
|
|||
notification["error"]({ message: "Error", description: e.message })
|
||||
})
|
||||
}
|
||||
|
||||
orZero(v) {
|
||||
return v ? v : 0
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<section className = "dashboard">
|
||||
<h1>Welcome</h1>
|
||||
|
||||
<hr />
|
||||
{ this.state.stats &&
|
||||
<div className="stats">
|
||||
<Row>
|
||||
<Col span={ 12 }>
|
||||
<h1></h1>
|
||||
<Col span={ 16 }>
|
||||
<Row gutter={ 24 }>
|
||||
<Col span={ 8 }>
|
||||
<Card title="Active subscribers" bordered={ false }>
|
||||
<h1 className="count">{ this.orZero(this.state.stats.subscribers.enabled) }</h1>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={ 8 }>
|
||||
<Card title="Blacklisted subscribers" bordered={ false }>
|
||||
<h1 className="count">{ this.orZero(this.state.stats.subscribers.blacklisted) }</h1>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={ 8 }>
|
||||
<Card title="Orphaned subscribers" bordered={ false }>
|
||||
<h1 className="count">{ this.orZero(this.state.stats.orphan_subscribers) }</h1>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={ 6 } offset={ 2 }>
|
||||
<Row gutter={ 24 }>
|
||||
<Col span={ 12 }>
|
||||
<Card title="Public lists" bordered={ false }>
|
||||
<h1 className="count">{ this.orZero(this.state.stats.lists.public) }</h1>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={ 12 }>
|
||||
<Card title="Private lists" bordered={ false }>
|
||||
<h1 className="count">{ this.orZero(this.state.stats.lists.private) }</h1>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<hr />
|
||||
<Row>
|
||||
<Col span={ 16 }>
|
||||
<Row gutter={ 24 }>
|
||||
<Col span={ 12 }>
|
||||
<Card title="Campaign views (last 3 months)" bordered={ false }>
|
||||
<h1 className="count">
|
||||
{ this.state.stats.campaign_views.reduce((total, v) => total + v.count, 0) }
|
||||
{' '}
|
||||
views
|
||||
</h1>
|
||||
<Chart height={ 220 } padding={ [0, 0, 0, 0] } data={ this.state.stats.campaign_views } forceFit>
|
||||
<BizTooltip crosshairs={{ type : "y" }} />
|
||||
<Geom type="area" position="date*count" size={ 0 } color="#7f2aff" />
|
||||
<Geom type='point' position="date*count" size={ 0 } />
|
||||
</Chart>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={ 12 }>
|
||||
<Card title="Link clicks (last 3 months)" bordered={ false }>
|
||||
<h1 className="count">
|
||||
{ this.state.stats.link_clicks.reduce((total, v) => total + v.count, 0) }
|
||||
{' '}
|
||||
clicks
|
||||
</h1>
|
||||
<Chart height={ 220 } padding={ [0, 0, 0, 0] } data={ this.state.stats.link_clicks } forceFit>
|
||||
<BizTooltip crosshairs={{ type : "y" }} />
|
||||
<Geom type="area" position="date*count" size={ 0 } color="#7f2aff" />
|
||||
<Geom type='point' position="date*count" size={ 0 } />
|
||||
</Chart>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
<Col span={ 6 } offset={ 2 }>
|
||||
<Card title="Campaigns" bordered={ false } className="campaign-counts">
|
||||
{ this.campaignTypes.map((key, count) =>
|
||||
<Row key={ `stats-campaigns-${ key }` }>
|
||||
<Col span={ 18 }><h1 className="name">{ key }</h1></Col>
|
||||
<Col span={ 6 }><h1 className="count">{ count }</h1></Col>
|
||||
</Row>
|
||||
)}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
|
|
@ -44,11 +44,14 @@ body {
|
|||
}
|
||||
|
||||
.content-body {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
min-height: 90vh;
|
||||
}
|
||||
|
||||
section.content {
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding: 30px;
|
||||
}
|
||||
|
@ -65,6 +68,11 @@ body {
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
.ant-card-head-title {
|
||||
font-size: .85em !important;
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -83,6 +91,14 @@ td .ant-tag {
|
|||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
.dashboard {
|
||||
margin: 24px;
|
||||
}
|
||||
.dashboard .campaign-counts .name {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
/* Templates */
|
||||
.wysiwyg {
|
||||
padding: 30px;
|
||||
|
|
|
@ -2,6 +2,75 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@antv/adjust@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@antv/adjust/-/adjust-0.1.0.tgz#c4bce8ba0aef7cd5b3bf271f75f434c07bd215a0"
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/attr@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@antv/attr/-/attr-0.1.0.tgz#68734b0557d9392645e947342acc8fca370d4a56"
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/component@~0.2.0":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/component/-/component-0.2.1.tgz#e3ef27fcd0aa0f6a76859a63c7a2578a365920bf"
|
||||
dependencies:
|
||||
"@antv/attr" "~0.1.0"
|
||||
"@antv/g" "~3.3.3"
|
||||
"@antv/util" "~1.3.1"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/coord@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@antv/coord/-/coord-0.1.0.tgz#48a80ae36d07552f96657e7f8095227c63f0c0a9"
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
|
||||
"@antv/g2@3.3.3":
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@antv/g2/-/g2-3.3.3.tgz#da997eb6422437d0827cbc26e184e455c06944b1"
|
||||
dependencies:
|
||||
"@antv/adjust" "~0.1.0"
|
||||
"@antv/attr" "~0.1.0"
|
||||
"@antv/component" "~0.2.0"
|
||||
"@antv/coord" "~0.1.0"
|
||||
"@antv/g" "~3.3.4"
|
||||
"@antv/scale" "~0.1.0"
|
||||
"@antv/util" "~1.3.1"
|
||||
venn.js "~0.2.20"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/g@~3.3.3", "@antv/g@~3.3.4":
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@antv/g/-/g-3.3.4.tgz#46cb6ae5fe0b6e1937f6ab384318d97a737385ad"
|
||||
dependencies:
|
||||
"@antv/gl-matrix" "~2.7.1"
|
||||
"@antv/util" "~1.3.1"
|
||||
d3-ease "~1.0.3"
|
||||
d3-interpolate "~1.1.5"
|
||||
d3-timer "~1.0.6"
|
||||
wolfy87-eventemitter "~5.1.0"
|
||||
|
||||
"@antv/gl-matrix@^2.7.1", "@antv/gl-matrix@~2.7.1":
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz#acb8e37f7ab3df01345aba4372d7942be42eba14"
|
||||
|
||||
"@antv/scale@~0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@antv/scale/-/scale-0.1.0.tgz#2b5459a100f97aac04781376d53904ccab18aab7"
|
||||
dependencies:
|
||||
"@antv/util" "~1.3.1"
|
||||
fecha "~2.3.3"
|
||||
|
||||
"@antv/util@~1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@antv/util/-/util-1.3.1.tgz#30a34b201ff9126ec0d58c72c8166a9c3e644ccd"
|
||||
dependencies:
|
||||
"@antv/gl-matrix" "^2.7.1"
|
||||
|
||||
"@babel/helper-module-imports@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
|
||||
|
@ -1215,6 +1284,15 @@ binary-extensions@^1.0.0:
|
|||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
||||
|
||||
bizcharts@^3.2.5-beta.4:
|
||||
version "3.2.5-beta.4"
|
||||
resolved "https://registry.yarnpkg.com/bizcharts/-/bizcharts-3.2.5-beta.4.tgz#4f27e62c3d4a9a5c49a29c54978e4f1f42ae4d1a"
|
||||
dependencies:
|
||||
"@antv/g2" "3.3.3"
|
||||
invariant "^2.2.2"
|
||||
prop-types "^15.6.0"
|
||||
warning "^3.0.0"
|
||||
|
||||
block-stream@*:
|
||||
version "0.0.9"
|
||||
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
|
||||
|
@ -1572,7 +1650,7 @@ center-align@^0.1.1:
|
|||
align-text "^0.1.3"
|
||||
lazy-cache "^1.0.3"
|
||||
|
||||
chalk@1.1.3, chalk@^1.1.3:
|
||||
chalk@1.1.3, chalk@^1.1.1, chalk@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||
dependencies:
|
||||
|
@ -1944,6 +2022,10 @@ content-type@~1.0.4:
|
|||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
|
||||
contour_plot@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/contour_plot/-/contour_plot-0.0.1.tgz#475870f032b8e338412aa5fc507880f0bf495c77"
|
||||
|
||||
convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
|
||||
|
@ -2195,6 +2277,49 @@ cyclist@~0.2.2:
|
|||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
|
||||
|
||||
d3-color@1:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f"
|
||||
|
||||
d3-dispatch@1:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.5.tgz#e25c10a186517cd6c82dd19ea018f07e01e39015"
|
||||
|
||||
d3-ease@1, d3-ease@~1.0.3:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb"
|
||||
|
||||
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-interpolate@~1.1.5:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.6.tgz#2cf395ae2381804df08aa1bf766b7f97b5f68fb6"
|
||||
dependencies:
|
||||
d3-color "1"
|
||||
|
||||
d3-selection@^1.0.2, d3-selection@^1.1.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.2.tgz#6e70a9df60801c8af28ac24d10072d82cbfdf652"
|
||||
|
||||
d3-timer@1, d3-timer@~1.0.6:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
|
||||
|
||||
d3-transition@^1.0.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"
|
||||
|
||||
d@1:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
|
||||
|
@ -2243,7 +2368,7 @@ decode-uri-component@^0.2.0:
|
|||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
deep-equal@^1.0.1, deep-equal@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
||||
|
@ -2293,7 +2418,7 @@ define-property@^2.0.2:
|
|||
is-descriptor "^1.0.2"
|
||||
isobject "^3.0.1"
|
||||
|
||||
defined@^1.0.0:
|
||||
defined@^1.0.0, defined@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
|
||||
|
||||
|
@ -2623,7 +2748,7 @@ error-ex@^1.2.0:
|
|||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-abstract@^1.7.0:
|
||||
es-abstract@^1.5.0, es-abstract@^1.7.0:
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
|
||||
dependencies:
|
||||
|
@ -3142,6 +3267,10 @@ fbjs@^0.8.0, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.9:
|
|||
setimmediate "^1.0.5"
|
||||
ua-parser-js "^0.7.18"
|
||||
|
||||
fecha@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "http://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
|
||||
|
||||
figgy-pudding@^3.0.0, figgy-pudding@^3.1.0, figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
|
||||
|
@ -3265,12 +3394,28 @@ flush-write-stream@^1.0.0:
|
|||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.4"
|
||||
|
||||
fmin@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/fmin/-/fmin-0.0.2.tgz#59bbb40d43ffdc1c94cd00a568c41f95f1973017"
|
||||
dependencies:
|
||||
contour_plot "^0.0.1"
|
||||
json2module "^0.0.3"
|
||||
rollup "^0.25.8"
|
||||
tape "^4.5.1"
|
||||
uglify-js "^2.6.2"
|
||||
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.3.0:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291"
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
|
||||
for-each@~0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
dependencies:
|
||||
is-callable "^1.1.3"
|
||||
|
||||
for-in@^1.0.1, for-in@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||
|
@ -3394,7 +3539,7 @@ fstream@^1.0.0, fstream@^1.0.2:
|
|||
mkdirp ">=0.5 0"
|
||||
rimraf "2"
|
||||
|
||||
function-bind@^1.1.1:
|
||||
function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
|
||||
|
@ -3664,7 +3809,7 @@ has-values@^1.0.0:
|
|||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
has@^1.0.1:
|
||||
has@^1.0.1, has@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
dependencies:
|
||||
|
@ -4716,6 +4861,12 @@ json-stringify-safe@~5.0.1:
|
|||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
|
||||
json2module@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/json2module/-/json2module-0.0.3.tgz#00fb5f4a9b7adfc3f0647c29cb17bcd1979be9b2"
|
||||
dependencies:
|
||||
rw "^1.3.2"
|
||||
|
||||
json2mq@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a"
|
||||
|
@ -5337,7 +5488,7 @@ minimist@0.0.8:
|
|||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
|
||||
|
@ -5913,6 +6064,10 @@ object-hash@^1.1.4:
|
|||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.0.tgz#76d9ba6ff113cf8efc0d996102851fe6723963e2"
|
||||
|
||||
object-inspect@~1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
|
||||
|
||||
object-keys@^1.0.8:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
|
||||
|
@ -7786,6 +7941,12 @@ resolve@^1.3.2, resolve@^1.5.0:
|
|||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
resolve@~1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
restore-cursor@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
||||
|
@ -7793,6 +7954,12 @@ restore-cursor@^2.0.0:
|
|||
onetime "^2.0.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
resumer@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
|
||||
dependencies:
|
||||
through "~2.3.4"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
|
@ -7831,6 +7998,14 @@ rmc-feedback@^2.0.0:
|
|||
babel-runtime "6.x"
|
||||
classnames "^2.2.5"
|
||||
|
||||
rollup@^0.25.8:
|
||||
version "0.25.8"
|
||||
resolved "http://registry.npmjs.org/rollup/-/rollup-0.25.8.tgz#bf6ce83b87510d163446eeaa577ed6a6fc5835e0"
|
||||
dependencies:
|
||||
chalk "^1.1.1"
|
||||
minimist "^1.2.0"
|
||||
source-map-support "^0.3.2"
|
||||
|
||||
run-async@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
|
||||
|
@ -7843,6 +8018,10 @@ run-queue@^1.0.0, run-queue@^1.0.3:
|
|||
dependencies:
|
||||
aproba "^1.1.1"
|
||||
|
||||
rw@^1.3.2:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
|
||||
|
||||
rx-lite-aggregates@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
|
||||
|
@ -8183,6 +8362,12 @@ source-map-resolve@^0.5.0:
|
|||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@^0.3.2:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.3.3.tgz#34900977d5ba3f07c7757ee72e73bb1a9b53754f"
|
||||
dependencies:
|
||||
source-map "0.1.32"
|
||||
|
||||
source-map-support@^0.4.15:
|
||||
version "0.4.18"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
|
||||
|
@ -8193,6 +8378,12 @@ source-map-url@^0.4.0:
|
|||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
|
||||
|
||||
source-map@0.1.32:
|
||||
version "0.1.32"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.32.tgz#c8b6c167797ba4740a8ea33252162ff08591b266"
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
|
@ -8372,6 +8563,14 @@ string-width@^1.0.1, string-width@^1.0.2:
|
|||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string.prototype.trim@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
|
||||
dependencies:
|
||||
define-properties "^1.1.2"
|
||||
es-abstract "^1.5.0"
|
||||
function-bind "^1.0.2"
|
||||
|
||||
string_decoder@^1.0.0, string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
|
@ -8512,6 +8711,24 @@ tapable@^0.2.7:
|
|||
version "0.2.8"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
|
||||
|
||||
tape@^4.5.1:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9"
|
||||
dependencies:
|
||||
deep-equal "~1.0.1"
|
||||
defined "~1.0.0"
|
||||
for-each "~0.3.3"
|
||||
function-bind "~1.1.1"
|
||||
glob "~7.1.2"
|
||||
has "~1.0.3"
|
||||
inherits "~2.0.3"
|
||||
minimist "~1.2.0"
|
||||
object-inspect "~1.6.0"
|
||||
resolve "~1.7.1"
|
||||
resumer "~0.0.0"
|
||||
string.prototype.trim "~1.1.2"
|
||||
through "~2.3.8"
|
||||
|
||||
tar@^2.0.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
|
||||
|
@ -8575,7 +8792,7 @@ through2@^2.0.0:
|
|||
readable-stream "^2.1.5"
|
||||
xtend "~4.0.1"
|
||||
|
||||
"through@>=2.2.7 <3", through@^2.3.6:
|
||||
"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4, through@~2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
|
||||
|
@ -8716,7 +8933,7 @@ uglify-js@3.4.x, uglify-js@^3.0.13:
|
|||
commander "~2.16.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
uglify-js@^2.6, uglify-js@^2.8.29:
|
||||
uglify-js@^2.6, uglify-js@^2.6.2, uglify-js@^2.8.29:
|
||||
version "2.8.29"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
|
||||
dependencies:
|
||||
|
@ -8942,6 +9159,14 @@ vendors@^1.0.0:
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801"
|
||||
|
||||
venn.js@~0.2.20:
|
||||
version "0.2.20"
|
||||
resolved "https://registry.yarnpkg.com/venn.js/-/venn.js-0.2.20.tgz#3f0e50cc75cba1f58692a8a32f67bd7aaf1aa6fa"
|
||||
dependencies:
|
||||
d3-selection "^1.0.2"
|
||||
d3-transition "^1.0.1"
|
||||
fmin "0.0.2"
|
||||
|
||||
verror@1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||
|
@ -9161,6 +9386,10 @@ window-size@0.1.0:
|
|||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
|
||||
|
||||
wolfy87-eventemitter@~5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wolfy87-eventemitter/-/wolfy87-eventemitter-5.1.0.tgz#35c1ac0dd1ac0c15e35d981508fc22084a13a011"
|
||||
|
||||
wordwrap@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
|
||||
|
|
10
queries.sql
10
queries.sql
|
@ -384,29 +384,29 @@ INSERT INTO link_clicks (campaign_id, subscriber_id, link_id)
|
|||
|
||||
-- name: get-dashboard-stats
|
||||
WITH lists AS (
|
||||
SELECT JSON_AGG(ROW_TO_JSON(row)) FROM (SELECT type, COUNT(id) AS num FROM lists GROUP BY type) row
|
||||
SELECT JSON_OBJECT_AGG(type, num) FROM (SELECT type, COUNT(id) AS num FROM lists GROUP BY type) row
|
||||
),
|
||||
subs AS (
|
||||
SELECT JSON_AGG(ROW_TO_JSON(row)) FROM (SELECT status, COUNT(id) AS num FROM subscribers GROUP by status) row
|
||||
SELECT JSON_OBJECT_AGG(status, num) FROM (SELECT status, COUNT(id) AS num FROM subscribers GROUP by status) row
|
||||
),
|
||||
orphans AS (
|
||||
SELECT COUNT(id) FROM subscribers LEFT JOIN subscriber_lists ON (subscribers.id = subscriber_lists.subscriber_id)
|
||||
WHERE subscriber_lists.subscriber_id IS NULL
|
||||
),
|
||||
camps AS (
|
||||
SELECT JSON_AGG(ROW_TO_JSON(row)) FROM (SELECT status, COUNT(id) AS num FROM campaigns GROUP by status) row
|
||||
SELECT JSON_OBJECT_AGG(status, num) FROM (SELECT status, COUNT(id) AS num FROM campaigns GROUP by status) row
|
||||
),
|
||||
clicks AS (
|
||||
-- Clicks by day for the last 3 months
|
||||
SELECT JSON_AGG(ROW_TO_JSON(row))
|
||||
FROM (SELECT COUNT(*) AS num, created_at::DATE as date
|
||||
FROM (SELECT COUNT(*) AS count, created_at::DATE as date
|
||||
FROM link_clicks GROUP by date ORDER BY date DESC LIMIT 100
|
||||
) row
|
||||
),
|
||||
views AS (
|
||||
-- Views by day for the last 3 months
|
||||
SELECT JSON_AGG(ROW_TO_JSON(row))
|
||||
FROM (SELECT COUNT(*) AS views, created_at::DATE as date
|
||||
FROM (SELECT COUNT(*) AS count, created_at::DATE as date
|
||||
FROM campaign_views GROUP by date ORDER BY date DESC LIMIT 100
|
||||
) row
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue