├── .editorconfig ├── .eslintignore ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TODO.md ├── babel.config.js ├── cypress.json ├── docs ├── .vuepress │ ├── components │ │ └── githubbuttons.vue │ ├── config.js │ ├── enhanceApp.js │ ├── public │ │ ├── d2.png │ │ ├── dashblocks.png │ │ ├── dashboard_dark.png │ │ └── logo.png │ └── styles │ │ └── index.styl ├── README.md ├── components │ ├── README.md │ ├── d3 │ │ ├── DbHorizon.vue.md │ │ ├── DbSankey.vue.md │ │ └── DbSunburst.vue.md │ └── dygraphs │ │ ├── DbDygraphs.vue.md │ │ ├── DbDygraphsBar.vue.md │ │ └── DbDygraphsLine.vue.md └── guide │ ├── README.md │ ├── firstdashboard.md │ └── gettingstarted.md ├── images ├── dblogo.png ├── dblogo.xcf └── logo.xcf ├── package.json ├── public ├── data │ └── superstore.arrow ├── favicon.ico ├── images │ └── poster_grand_tour.png └── index.html ├── screenshots ├── dashboard.png ├── dblogo.png └── sample_dashboard.png ├── scripts ├── buildComponentDocs.js ├── pagesdeploy.sh └── templates │ └── component.md ├── src ├── App.vue ├── assets │ ├── logo.png │ └── scss │ │ ├── dashblocks.scss │ │ └── dashblocks │ │ ├── _dbdashboard.scss │ │ ├── _gridlayout.scss │ │ ├── _gridlayout12.scss │ │ ├── _material-colors.scss │ │ ├── _variables.scss │ │ ├── components │ │ ├── _dbdygraps.scss │ │ ├── _dbeasypie.scss │ │ └── _dbnumber.scss │ │ └── themes │ │ ├── _theme-dark.scss │ │ └── _theme-default.scss ├── components.js ├── components │ ├── chartjs │ │ ├── DbChartjs.js │ │ └── index.js │ ├── d3 │ │ ├── DbHorizon.vue │ │ ├── DbRidgeline.vue │ │ ├── DbSankey.vue │ │ ├── DbSunburst.vue │ │ ├── domuid.js │ │ └── index.js │ ├── dashboard │ │ ├── DbDashboard.vue │ │ └── index.js │ ├── db │ │ ├── DbEasyPie.vue │ │ ├── DbHeatmapVariants.vue │ │ ├── DbLinearProgress.vue │ │ ├── DbMarkup.vue │ │ ├── DbMultiProgress.vue │ │ ├── DbNone.vue │ │ ├── DbNumber.vue │ │ ├── DbProgress.vue │ │ ├── DbSparkHeatmap.vue │ │ ├── DbSparkLinemap.vue │ │ ├── DbSparkRidgeline.vue │ │ ├── DbSparkRidgelineHeight.vue │ │ ├── DbSparkline.vue │ │ ├── DbTrendBar.vue │ │ ├── DbTrendLine.vue │ │ └── index.js │ ├── dbcolors.js │ ├── dbdata.js │ ├── dblayouts.js │ ├── dbutils.js │ ├── dbwidgets.js │ ├── dygraphs │ │ ├── DbDygraphs.vue │ │ ├── DbDygraphsBar.vue │ │ ├── DbDygraphsDateTimeHistogram.vue │ │ ├── DbDygraphsLine.vue │ │ ├── DbDygraphsSparkLine.vue │ │ └── index.js │ ├── funnel │ │ ├── DbFunnel.vue │ │ └── index.js │ ├── geo │ │ ├── DbGeoMapbox.vue │ │ ├── geomap.vue │ │ ├── index.js │ │ └── old_DbGeoMapbox.vue │ ├── index.js │ ├── layout │ │ ├── DbGridLayout.vue │ │ └── DbWidgetContainer.vue │ ├── log.js │ ├── mixins │ │ └── dbstdprops.js │ ├── perspective │ │ ├── DbPerspective.vue │ │ └── index.js │ ├── plotly │ │ ├── DbPlotly.vue │ │ ├── DbPlotlyLine.vue │ │ └── DbPlotlyPie.vue │ └── utils │ │ └── colors.js ├── css.js ├── demo │ ├── assets │ │ └── images │ │ │ └── poster_grand_tour.png │ ├── dashboards │ │ ├── ChartJsShowcase.json │ │ ├── dashfive.json │ │ ├── dashsix.json │ │ └── dashthree.json │ ├── data │ │ ├── energy.json │ │ ├── flare.json │ │ ├── geo_data_us.json │ │ ├── metrics3.json │ │ ├── ridgedata.json │ │ ├── ridgemapdata.json │ │ ├── series_api_latency.json │ │ ├── series_rate_api_req_count.json │ │ ├── series_test_jvm_memory_used_bytes.json │ │ ├── sws_api_stats.json │ │ └── testdata.js │ ├── layouts │ │ └── Default.vue │ ├── mixins │ │ └── demodashboard.js │ ├── themes │ │ ├── README.md │ │ └── _theme_custom.scss │ └── views │ │ ├── About.vue │ │ ├── ChartJsShowcase.vue │ │ ├── CodeViewer.vue │ │ ├── DashFive.vue │ │ ├── DashFour.vue │ │ ├── DashRidgeline.vue │ │ ├── DashSix.vue │ │ ├── DashThree.vue │ │ ├── DashblocksShowcase.vue │ │ ├── DygraphsDynamic.vue │ │ ├── DynamicPerspective.vue │ │ ├── DynamicSalesDashboard.vue │ │ ├── DynamicSankey.vue │ │ ├── DynamicTimelines.vue │ │ ├── DynamicTimelinesDygraphs.vue │ │ ├── GeoMapboxUS.vue │ │ ├── Home.vue │ │ ├── OverlayDashboard.vue │ │ ├── OverlayDashboardImage.vue │ │ ├── OverlayDashboardParallax.vue │ │ ├── Perspective.vue │ │ ├── Playground.vue │ │ ├── ProgressDashboard.vue │ │ ├── SalesFunnelDashboard.vue │ │ ├── SalesSunburstDashboard.vue │ │ ├── SampleDashboard.vue │ │ ├── SankeyDashboard.vue │ │ ├── SparkHeatMap.vue │ │ ├── SparkLineMap.vue │ │ ├── SparkLineMapDyn.vue │ │ └── samples │ │ ├── DbDygraphsBarSamples.vue │ │ ├── DbHorizonSamples.vue │ │ └── ProgressSamples.vue ├── index.esm.js ├── main.js ├── quasar.js ├── router.js ├── store.js ├── styles │ ├── quasar.scss │ └── quasar.variables.scss ├── views │ ├── About.vue │ └── Home.vue └── webcomponents │ ├── dashboard.vue │ └── dygraphs.vue ├── tests ├── e2e │ ├── .eslintrc.js │ ├── plugins │ │ └── index.js │ ├── specs │ │ └── test.js │ └── support │ │ ├── commands.js │ │ └── index.js ├── unit │ ├── .eslintrc.js │ └── example.spec.js └── wc │ ├── db.html │ └── index.html ├── vue.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | public 4 | tests 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: sv2 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | pages 5 | /dist 6 | /demo 7 | /docs/.vuepress/dist 8 | /pages 9 | 10 | /tests/e2e/videos/ 11 | /tests/e2e/screenshots/ 12 | 13 | # local env files 14 | .env.local 15 | .env.*.local 16 | 17 | # Log files 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # Editor directories and files 23 | .idea 24 | .vscode 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw* 30 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 180 4 | } 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Want to contribute to **dashblocks**? Awesome! 4 | 5 | 6 | There are many ways you can contribute: 7 | 8 | * by reviewing 9 | * by reporting bugs 10 | * by suggesting improvements and new features 11 | * by writing or editing documentation 12 | * by writing code ( no patch is too small ) 13 | * by closing issues 14 | 15 | ## Proposing pull requests 16 | 17 | Pull requests are very welcome. Note that if you are going to propose drastic changes, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it. 18 | 19 | 20 | Inspired by https://github.com/middleman/middleman-heroku/blob/master/CONTRIBUTING.md 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 slana.tech 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # DashBlocks TODO 2 | 3 | 4 | ## Event propagation up to dashboard level 5 | 6 | - [X] db-event: generated by all widgets and propagated up to dashboard 7 | - [X] augment db-event with widget id on widget level 8 | - [X] Events for chartjs 9 | - [ ] Events for plotly 10 | 11 | 12 | ## Dashboards 13 | 14 | - [X] Overlay - dashboard on top of video, picture, etc - on a boarder & bottom [DEMO](https://dashblocks.io/demo/#/overlayimage) 15 | - [X] Dynamically generated dashboard based on data. I.e. multiple pie charts [DEMO](https://dashblocks.io/demo/#/dynamicsalesdashboard) 16 | 17 | ## Test Data 18 | 19 | - [X] Datasets, aggregation lib - use in sample dashboards 20 | - [X] Time-series sample dataset - i.e. sales over time 21 | 22 | [https://github.com/finos/perspective](https://github.com/finos/perspective) is used, together with [Apache Arrow](https://arrow.apache.org/) dataset 23 | Perspective enables dynamically aggregating Arrow data 24 | 25 | [DEMO](https://dashblocks.io/demo/#/dynamicsankey) 26 | 27 | ## Documentation 28 | 29 | - [X] Self-documenting components - jsdoc 30 | 31 | ## Pages 32 | 33 | - [x] github pages with doc - vuepress 34 | - [x] [Demo project](https://slanatech.github.io/dashblocks) 35 | 36 | 37 | ## Issues 38 | 39 | 40 | ## Style, Themes and Colors 41 | 42 | - [X] more color sets 43 | - [X] Dark mode support across all widgets 44 | - [ ] Examples of custom theme 45 | 46 | 47 | ## Dashboard widget 48 | - [ ] Title 49 | 50 | 51 | ## Chart Types / Components 52 | 53 | ### D3 54 | - [ ] Horizon: show values 55 | - [X] Sankey 56 | - [X] Sunburst 57 | - [X] Showcase dashboard 58 | 59 | https://dashblocks.io/demo/#/dynamicsankey 60 | https://dashblocks.io/demo/#/salessunburst 61 | 62 | ### Chart.js 63 | - [x] Showcase dashboard 64 | 65 | ### Plotly 66 | - [ ] Showcase dashboard 67 | - [ ] Consider: use more customized bundle ( specific modules ) instead of all-in-one. 68 | plotly.js-dist is too big to include in bundle ( ~6M ) 69 | 70 | 71 | ### Dygraphs 72 | - [X] Showcase dashboard 73 | https://dashblocks.io/demo/#/dygraphsdynamic 74 | 75 | ### Dashblocks 76 | - [X] Number 77 | - [X] Percent 78 | - [ ] Multiple values - rows with sparklines 79 | - [X] [Showcase dashboard](https://dashblocks.io/demo/#/) 80 | 81 | 82 | 83 | ### Other 84 | - [X] Table - goodtable. Used in [dashblock-template separately](https://slanatech.github.io/dashblocks-template/#/vgt) 85 | - [X] Markup 86 | - [ ] Markdown 87 | - [ ] Showcase dashboard 88 | 89 | 90 | ## Options templates 91 | 92 | Create class to manage standard props/options templates for various chart types. 93 | So instead of specifying all props in dashboard definition always, just refer to 94 | template name (like DbDygraphs-AreaLine) 95 | 96 | Consider making template parameterized, i.e. pass axis name (see plotly props) 97 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | plugins: [ 4 | [ 5 | 'transform-imports', 6 | { 7 | quasar: { 8 | transform: 'quasar/dist/babel-transforms/imports.js', 9 | preventFullImport: true 10 | } 11 | } 12 | ] 13 | ] 14 | }; 15 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /docs/.vuepress/components/githubbuttons.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const webpack = require('webpack'); 4 | 5 | const isDirectory = source => fs.lstatSync(source).isDirectory(); 6 | const isNotDirectory = source => !fs.lstatSync(source).isDirectory(); 7 | const getDirectories = source => 8 | fs.readdirSync(source).map(name => path.join(source, name)).filter(isDirectory); 9 | const getFiles = source => 10 | fs.readdirSync(source).map(name => path.join(source, name)).filter(isNotDirectory); 11 | 12 | module.exports = { 13 | base: '/', 14 | locales: { 15 | '/': { 16 | lang: 'en-US', 17 | title: 'dashblocks', 18 | description: 'Enable Analytics in your Apps' 19 | } 20 | }, 21 | markdown: { 22 | lineNumbers: true 23 | }, 24 | serviceWorker: true, 25 | themeConfig: { 26 | repo: 'slanatech/dashblocks', 27 | docsDir: 'docs', 28 | editLinks: true, 29 | sidebarDepth: 1, 30 | locales: { 31 | '/': { 32 | label: 'English', 33 | selectText: 'Languages', 34 | lastUpdated: 'Last Updated', 35 | editLinkText: 'Edit this page on GitHub', 36 | nav: [ 37 | { 38 | text: 'Guide', 39 | link: '/guide/' 40 | }, 41 | { 42 | text: 'Components', 43 | link: '/components/' 44 | }, 45 | { 46 | text: 'Changelog', 47 | link: 'https://github.com/dashblocks/blob/dev/CHANGELOG.md' 48 | } 49 | ], 50 | sidebar: { 51 | '/guide/': ['/guide/', 'firstdashboard'], 52 | '/components/': getComponentsSidebar() 53 | /*[ 54 | { 55 | title: 'Components', 56 | collapsable: false, 57 | children: [''] 58 | }, 59 | { 60 | title: 'd3', 61 | collapsable: true, 62 | children: ['d3/DbHorizon.vue'] 63 | } 64 | ]*/ 65 | } 66 | } 67 | } 68 | }, 69 | configureWebpack: { 70 | plugins: [ 71 | // Ignore all locale files of moment.js 72 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) 73 | ], 74 | resolve: { 75 | alias: { 76 | dashblocks: path.resolve(__dirname, '../../src/components/') 77 | } 78 | } 79 | } 80 | }; 81 | 82 | function getComponentsSidebar() { 83 | let result = [ 84 | { 85 | title: 'Components', 86 | collapsable: false, 87 | children: [''] 88 | } 89 | ]; 90 | 91 | // Enumerate all folders 92 | let dirs = getDirectories(path.join(__dirname,'..','components')); 93 | console.log(`Directories: ${JSON.stringify(dirs)}`); 94 | for(let dir of dirs){ 95 | let dirname = path.basename(dir); 96 | let files = getFiles(dir); 97 | let children = []; 98 | for(let file of files){ 99 | let filename = path.basename(file); 100 | children.push(`${dirname}/${filename}`); 101 | } 102 | 103 | result.push( 104 | { 105 | title: dirname, 106 | collapsable: true, 107 | children: children 108 | } 109 | ); 110 | } 111 | 112 | return result; 113 | } 114 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | import DbHorizonSamples from '../../src/demo/views/samples/DbHorizonSamples'; 2 | import DbDygraphsBarSamples from '../../src/demo/views/samples/DbDygraphsBarSamples'; 3 | import SampleDashboard from '../../src/demo/views/SampleDashboard'; 4 | 5 | export default ({ 6 | Vue, // the version of Vue being used in the VuePress app 7 | options, // the options for the root Vue instance 8 | router, // the router instance for the app 9 | siteData // site metadata 10 | }) => { 11 | Vue.component('DbHorizonSamples', DbHorizonSamples); 12 | Vue.component('DbDygraphsBarSamples', DbDygraphsBarSamples); 13 | Vue.component('SampleDashboard', SampleDashboard); 14 | }; 15 | -------------------------------------------------------------------------------- /docs/.vuepress/public/d2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/docs/.vuepress/public/d2.png -------------------------------------------------------------------------------- /docs/.vuepress/public/dashblocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/docs/.vuepress/public/dashblocks.png -------------------------------------------------------------------------------- /docs/.vuepress/public/dashboard_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/docs/.vuepress/public/dashboard_dark.png -------------------------------------------------------------------------------- /docs/.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/docs/.vuepress/public/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | body { 2 | background: rgba(0,0,0,0); 3 | } 4 | 5 | 6 | .theme-default-content:not(.custom) { 7 | max-width: 80%; 8 | width: 80%; 9 | } 10 | 11 | /* 12 | .theme-container.dashblocks-landing { 13 | background-image: url("/dashblocks/d2-3.png"); 14 | height: 100%; 15 | background-repeat: no-repeat; 16 | background-size: cover; 17 | background-position: center; 18 | } 19 | */ 20 | 21 | 22 | .theme-container.dashblocks-landing::before { 23 | background-image: url("/d2.png"); 24 | filter: blur(6px); 25 | background-size: cover; 26 | content: ""; 27 | display: block; 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | width: 100%; 32 | height: 100%; 33 | z-index: -2; 34 | opacity: 0.4; 35 | -webkit-clip-path: polygon(0 0, 0 100%, 100% 40%, 100% 0); 36 | clip-path: polygon(0 0, 0 100%, 100% 40%, 100% 0); 37 | } 38 | 39 | 40 | /* 41 | .home { 42 | background-color: #00acc1; 43 | padding: 3.6rem 2rem 0; 44 | max-width: 100%; 45 | width: 100%; 46 | margin: 0px auto; 47 | display: block; 48 | } 49 | 50 | .home > features { 51 | background-color: #00acc1; 52 | padding: 3.6rem 2rem 0; 53 | max-width: 960px; 54 | margin: 0px auto; 55 | display: block; 56 | } 57 | 58 | .hero img { 59 | width: 100%; 60 | } 61 | */ 62 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /logo.png 4 | actionText: Get Started → 5 | actionLink: /guide/ 6 | meta: 7 | - name: google-site-verification 8 | content: ypsB9NFIxGEr1b5D0BoZ0dyVzt8lLkilkI0dO755M54 9 | features: 10 | - title: Declarative 11 | details: Use declarative approach to define dashboard layout - Javascript object or JSON 12 | - title: Out of the box 13 | details: Provide reasonable out of the box defaults for all chart types, such as colors 14 | - title: Light and Dark 15 | details: Support Light and Dark themes out of the box 16 | - title: Interactive 17 | details: Enable interactivity by providing event handling on dashboard level 18 | - title: Dynamic 19 | details: Streamline dynamic updates of dashboard data, for example based on user interaction with dashboard 20 | - title: Data Driven 21 | details: Even dynamically generate Dashboard itself based on the data - thanks to declarative approach 22 | footer: MIT Licensed | Copyright © 2019 slana.tech 23 | pageClass: dashblocks-landing 24 | --- 25 | 26 |
27 |
28 | Follow 29 | Star 30 | Fork 31 |
32 |
33 | 34 |
35 |

See the Demo →

36 |
37 | 38 | ![sample](dashboard_dark.png) 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/components/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components Reference 3 | lang: en-US 4 | --- 5 | 6 | # Components Reference 7 | 8 | This is the index page for all the documented components. 9 | -------------------------------------------------------------------------------- /docs/components/d3/DbHorizon.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbHorizon" 3 | --- 4 | # DbHorizon 5 | 6 | D3 Horizon Chart. 7 | Based on [https://observablehq.com/@d3/horizon-chart](https://observablehq.com/@d3/horizon-chart) 8 | 9 | DbHorizon accepts data in the following format: 10 | 11 | ```json 12 | [ 13 | {key:'Series1', values:[{date:new Date(),value: 1},{date:new Date(),value: 2}]}, 14 | {key:'Series2', values:[{date:new Date(),value: 2},{date:new Date(),value: 1}]} 15 | ] 16 | ``` 17 | 18 | 19 | ### Properties 20 | 21 | |Name |Type |Required|Default |Description 22 | |:--------------|:--------|:-------|:-------|:---------- 23 | |**_updated**|number|false|0|Change to trigger data update.
Set this to current timestamp to inform component that data has been updated.
Helpful in situations when, for example, only values in array are changed.
See [https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats) 24 | |**dark**|boolean|false|false|Enable dark mode

`true,false` 25 | |**data**|array|false|() => []|Chart Data 26 | |**seriesHeight**|number|false|23|Height of each series in pixels. 27 | |**colorSteps**|number|false|7|Number of overlapping color steps, in range 1-9 28 | |**scheme**|string|false|'schemePuBuGn'|Color scheme
Use one of Discrete Diverging color schemes from d3-scale-chromatic:

`schemeBrBG,schemePRGn, ...`

See [https://github.com/d3/d3-scale-chromatic](https://github.com/d3/d3-scale-chromatic) 29 | 30 | ### Examples 31 |
32 |
33 | 34 | 35 | 36 | 37 | #### Code 38 | 39 | ```vue 40 | 73 | 74 | 109 | 110 | ``` 111 | -------------------------------------------------------------------------------- /docs/components/d3/DbSankey.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbSankey" 3 | --- 4 | # DbSankey 5 | 6 | DbSankey component 7 | 8 | 9 | ### Properties 10 | 11 | |Name |Type |Required|Default |Description 12 | |:--------------|:--------|:-------|:-------|:---------- 13 | |**data**||false|| 14 | |**colorScheme**|string|false|'interpolateRainbow'| 15 | 16 | ### Examples 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /docs/components/d3/DbSunburst.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbSunburstZ" 3 | --- 4 | # DbSunburstZ 5 | 6 | DbSunburstZ component 7 | 8 | 9 | ### Properties 10 | 11 | |Name |Type |Required|Default |Description 12 | |:--------------|:--------|:-------|:-------|:---------- 13 | |**wdata**||false|| 14 | |**wspec**||false|| 15 | |**dark**|boolean|false|false| 16 | |**colorScheme**|string|false|'interpolateRainbow'| 17 | 18 | ### Examples 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /docs/components/dygraphs/DbDygraphs.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbDygraphs" 3 | --- 4 | # DbDygraphs 5 | 6 | DbDygraphs component 7 | 8 | 9 | ### Properties 10 | 11 | |Name |Type |Required|Default |Description 12 | |:--------------|:--------|:-------|:-------|:---------- 13 | |**_updated**|number|false|0| 14 | |**data**|array|false|() => []| 15 | |**options**|object|false|| 16 | |**dark**|boolean|false|false| 17 | 18 | ### Examples 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /docs/components/dygraphs/DbDygraphsBar.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbDygraphsBar" 3 | --- 4 | # DbDygraphsBar 5 | 6 | Dygraphs Bar Chart. 7 | [http://dygraphs.com/](http://dygraphs.com/) 8 | 9 | Dygraphs accepts data in the following format: 10 | 11 | ```json 12 | [ 13 | [date:new Date(),1,1,1], 14 | [date:new Date(),1,2,2], 15 | [date:new Date(),1,3,3] 16 | ] 17 | ``` 18 | 19 | 20 | ### Properties 21 | 22 | |Name |Type |Required|Default |Description 23 | |:--------------|:--------|:-------|:-------|:---------- 24 | |**_updated**|number|false|0|Change to trigger data update.
Set this to current timestamp to inform component that data has been updated.
Helpful in situations when, for example, only values in array are changed.
See [https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats) 25 | |**dark**|boolean|false|false|Enable dark mode

`true,false` 26 | |**data**|array|false|() => []| 27 | |**options**|object|false|| 28 | 29 | ### Examples 30 |
31 |
32 | 33 | 34 | 35 | 36 | #### Code 37 | 38 | ```vue 39 | 57 | 58 | 96 | 103 | 104 | ``` 105 | -------------------------------------------------------------------------------- /docs/components/dygraphs/DbDygraphsLine.vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "DbDygraphsLine" 3 | --- 4 | # DbDygraphsLine 5 | 6 | DbDygraphsLine component 7 | 8 | 9 | ### Properties 10 | 11 | |Name |Type |Required|Default |Description 12 | |:--------------|:--------|:-------|:-------|:---------- 13 | |**_updated**|number|false|0| 14 | |**data**|array|false|() => []| 15 | |**options**|object|false|| 16 | |**dark**|boolean|false|false| 17 | 18 | ### Examples 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Guide 2 | 3 | 4 | Dashblocks aims to simplify enabling robust In-App Analytics: 5 | 6 | * Use declarative approach to define dashboard layout 7 | * Provide reasonable out of the box defaults for all chart types, such as colors 8 | * Support dark / light modes out of the box 9 | * Enable interactivity by providing event handling on dashboard level 10 | * Streamline dynamic updates of dashboard data, for example based on user interaction with dashboard 11 | * Even dynamically generate Dashboard itself based on the data - thanks to declarative approach 12 | 13 | 14 | ## Installation 15 | 16 | ```bash 17 | # 1. Install 18 | npm install dashblocks --save 19 | 20 | 21 | ``` 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/guide/firstdashboard.md: -------------------------------------------------------------------------------- 1 | # Your first dashboard 2 | 3 | Create Dashboard in your Vue app as a Vue Component. In Dashboard component you define: 4 | * Dashboard Layout - add widgets to your dashboard, specifying how many columns and rows 5 | each widget takes. Dashblocks provides 16-columns CSS Grid layout. Pass additional options to widgets to adjust appearance as needed. 6 | * Set Data for each widget on a dashboard 7 | 8 | 9 | 10 | 11 | 12 | #### Code 13 | 14 | <<< @/src/demo/views/SampleDashboard.vue 15 | -------------------------------------------------------------------------------- /docs/guide/gettingstarted.md: -------------------------------------------------------------------------------- 1 | # How to get started 2 | 3 | here are the instructions 4 | -------------------------------------------------------------------------------- /images/dblogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/images/dblogo.png -------------------------------------------------------------------------------- /images/dblogo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/images/dblogo.xcf -------------------------------------------------------------------------------- /images/logo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/images/logo.xcf -------------------------------------------------------------------------------- /public/data/superstore.arrow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/public/data/superstore.arrow -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/public/favicon.ico -------------------------------------------------------------------------------- /public/images/poster_grand_tour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/public/images/poster_grand_tour.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | dashblocks 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /screenshots/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/screenshots/dashboard.png -------------------------------------------------------------------------------- /screenshots/dblogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/screenshots/dblogo.png -------------------------------------------------------------------------------- /screenshots/sample_dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/screenshots/sample_dashboard.png -------------------------------------------------------------------------------- /scripts/buildComponentDocs.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Build Components documentation based on JSDoc comments in component files 3 | * 4 | */ 5 | const path = require('path'); 6 | const fs = require('fs'); 7 | const ejs = require('ejs'); 8 | const { parse } = require('vue-docgen-api'); 9 | const { pathOr } = require('ramda'); 10 | const linkify = require('markdown-linkify'); 11 | 12 | const basePath = path.join(__dirname, '..', 'src', 'components'); 13 | const baseDocsPath = path.join(__dirname, '..', 'docs', 'components'); 14 | 15 | const templateFN = path.join(__dirname, 'templates', 'component.md'); 16 | const templateString = fs.readFileSync(templateFN, 'utf-8'); 17 | 18 | function breakify(str) { 19 | return str.replace(/\r/g, '').replace(/\n/g, '
'); 20 | } 21 | 22 | const componentFiles = [ 23 | { folder: 'd3', name: 'DbHorizon.vue' }, 24 | { folder: 'd3', name: 'DbSankey.vue' }, 25 | { folder: 'd3', name: 'DbSunburst.vue' }, 26 | { folder: 'dygraphs', name: 'DbDygraphs.vue' }, 27 | { folder: 'dygraphs', name: 'DbDygraphsBar.vue' }, 28 | { folder: 'dygraphs', name: 'DbDygraphsLine.vue' } 29 | ]; 30 | 31 | function camelCaseToDash(str) { 32 | return str.replace(/([a-zA-Z])(?=[A-Z])/g, '$1-').toLowerCase(); 33 | } 34 | 35 | function parseComponentFile(componentFile) { 36 | // TODO Options ? 37 | let parseResult = parse(componentFile); 38 | return parseResult; 39 | } 40 | 41 | // Pre-process component properties 42 | function processProps(componentData) { 43 | let propsArray = []; 44 | for (let propName of Object.keys(componentData.props)) { 45 | let propData = componentData.props[propName]; 46 | let propInfo = { 47 | name: propName, 48 | type: pathOr('', ['type', 'name'], propData), 49 | required: pathOr('', ['required'], propData) === 'true' ? 'true' : 'false', 50 | description: linkify(breakify(pathOr('', ['description'], propData))), 51 | default: pathOr('', ['defaultValue', 'value'], propData) 52 | }; 53 | propsArray.push(propInfo); 54 | } 55 | return propsArray; 56 | } 57 | 58 | // Pre-process component examples 59 | // TODO Generate proper imports of sample components for vuepress ( enhanceApp.js ) 60 | function processExamples(componentData, filePath, fileName) { 61 | let result = []; 62 | 63 | let examplesData = pathOr(null, ['tags', 'examples'], componentData); 64 | if (!examplesData || !Array.isArray(examplesData) || examplesData.length <= 0) { 65 | return result; 66 | } 67 | 68 | for (let example of examplesData) { 69 | let exampleContent = pathOr(null, ['content'], example); 70 | if (exampleContent) { 71 | let exampleFileName = path.join(filePath, exampleContent); 72 | let exampleBaseName = path.basename(exampleFileName, '.vue'); 73 | let exampleComponent = camelCaseToDash(exampleBaseName); 74 | try { 75 | let exampleFileContent = fs.readFileSync(exampleFileName); 76 | let exampleCode = exampleFileContent.toString(); 77 | result.push({ 78 | code: exampleCode, 79 | component: exampleComponent, 80 | filePath: filePath, 81 | fileName: fileName 82 | }); 83 | } catch (e) { 84 | // NOOP // 85 | } 86 | } 87 | } 88 | 89 | return result; 90 | } 91 | 92 | function renderComponentDoc(componentData, filePath, fileName) { 93 | let renderData = { 94 | name: pathOr('', ['displayName'], componentData), 95 | description: linkify(pathOr('', ['description'], componentData)), 96 | props: processProps(componentData), 97 | examples: processExamples(componentData, filePath, fileName) 98 | }; 99 | 100 | let renderedDoc = ejs.render(templateString, renderData); 101 | return renderedDoc; 102 | } 103 | 104 | function processComponents() { 105 | for (let componentFile of componentFiles) { 106 | let filePath = path.join(basePath, componentFile.folder); 107 | 108 | let fullFN = path.join(filePath, componentFile.name); 109 | 110 | let parseResult = parseComponentFile(fullFN); 111 | 112 | let renderResult = renderComponentDoc(parseResult, filePath, componentFile.name); 113 | 114 | if (!fs.existsSync(path.join(baseDocsPath, componentFile.folder))) { 115 | fs.mkdirSync(path.join(baseDocsPath, componentFile.folder)); 116 | } 117 | 118 | let docFN = path.join(baseDocsPath, componentFile.folder, componentFile.name + '.md'); 119 | 120 | let defFS = fs.createWriteStream(docFN); 121 | defFS.write(renderResult); 122 | defFS.end(); 123 | } 124 | } 125 | 126 | processComponents(); 127 | 128 | //console.log('Test here!'); 129 | -------------------------------------------------------------------------------- /scripts/pagesdeploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # abort on errors 4 | set -e 5 | 6 | # navigate into the build output directory 7 | cd pages 8 | 9 | echo 'dashblocks.io' > CNAME 10 | 11 | git init 12 | git add -A 13 | git commit -m 'deploy for github pages' 14 | 15 | git push -f https://github.com/slanatech/dashblocks.git master:gh-pages 16 | 17 | cd - 18 | -------------------------------------------------------------------------------- /scripts/templates/component.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "<%= name%>" 3 | --- 4 | # <%= name%> 5 | 6 | <%- description ? description : name + ' component'%> 7 | 8 | 9 | ### Properties 10 | 11 | |Name |Type |Required|Default |Description 12 | |:--------------|:--------|:-------|:-------|:---------- 13 | <% 14 | for(let prop of props) { 15 | -%> 16 | |**<%- prop.name%>**|<%- prop.type%>|<%- prop.required%>|<%- prop.default%>|<%- prop.description%> 17 | <% 18 | } 19 | -%> 20 | 21 | ### Examples 22 |
23 |
24 | 25 | <% 26 | for(let example of examples) { 27 | -%> 28 | 29 | <<%- example.component%>>> 30 | 31 | #### Code 32 | 33 | ```vue 34 | <%- example.code%> 35 | ``` 36 | <% 37 | } 38 | -%> 39 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/scss/dashblocks.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | DashBlocks 3 | */ 4 | 5 | // Colors 6 | @import "dashblocks/material-colors"; 7 | 8 | 9 | // Variables 10 | @import "dashblocks/variables"; 11 | 12 | 13 | // Layouts 14 | @import "dashblocks/gridlayout"; 15 | @import "dashblocks/gridlayout12"; 16 | 17 | // Components 18 | @import "dashblocks/components/dbeasypie"; 19 | @import "dashblocks/components/dbnumber"; 20 | @import "dashblocks/components/dbdygraps"; 21 | 22 | // Themes 23 | @import 'dashblocks/themes/theme-default'; 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/_dbdashboard.scss: -------------------------------------------------------------------------------- 1 | // TODO Rename !! 2 | @mixin db-dashboard { 3 | font-family: $font-family; 4 | font-size: $font-size; 5 | color: $dark; 6 | 7 | .db-float-right { 8 | float: right; 9 | } 10 | 11 | .db-v-center { 12 | position: relative; 13 | top: 50%; 14 | transform: translateY(-50%); 15 | } 16 | 17 | .db-badge { 18 | background: $primary; 19 | color: $on-primary; 20 | font-size: 80%; 21 | padding: 2px 4px 2px 4px; 22 | border-radius: 4px; 23 | } 24 | 25 | 26 | & .db-grid-layout { 27 | column-gap: 0px; 28 | row-gap: 0px; 29 | } 30 | 31 | & .db-widget-container { 32 | margin: 4px; 33 | padding: 6px; 34 | border: 1px solid material-color('grey', '300'); 35 | border-radius: 6px; 36 | } 37 | 38 | & .text-primary { 39 | color: $primary; 40 | } 41 | & .bg-primary { 42 | background: $primary; 43 | } 44 | 45 | & .text-on-primary { 46 | color: $on-primary; 47 | } 48 | & .text-on-secondary { 49 | color: $on-secondary; 50 | } 51 | & .text-on-background { 52 | color: $on-background; 53 | } 54 | & .text-on-surface { 55 | color: $on-surface; 56 | } 57 | & .text-on-error { 58 | color: $on-error; 59 | } 60 | 61 | & .text-faded { 62 | color: $faded; 63 | } 64 | 65 | & .text-neutral { 66 | color: $neutral; 67 | } 68 | & .text-positive { 69 | color: $positive; 70 | } 71 | & .text-negative { 72 | color: $negative; 73 | } 74 | & .text-info { 75 | color: $info; 76 | } 77 | & .text-warning { 78 | color: $warning; 79 | } 80 | 81 | & .text-xxs { 82 | font-size: 70% 83 | } 84 | & .text-xs { 85 | font-size: 80% 86 | } 87 | & .text-sm { 88 | font-size: 90% 89 | } 90 | & .text-base { 91 | font-size: 100% 92 | } 93 | & .text-md { 94 | font-size: 110% 95 | } 96 | & .text-lg { 97 | font-size: 120% 98 | } 99 | & .text-xl { 100 | font-size: 150% 101 | } 102 | & .text-xxl { 103 | font-size: 250% 104 | } 105 | & .text-x3l { 106 | font-size: 300% 107 | } 108 | & .text-x4l { 109 | font-size: 400% 110 | } 111 | & .text-x5l { 112 | font-size: 400% 113 | } 114 | 115 | & .bg-good { 116 | background: $positive; 117 | } 118 | 119 | & .bg-neutral { 120 | background: $neutral; 121 | } 122 | & .bg-success { 123 | background: $success; 124 | } 125 | & .bg-warning { 126 | background: $warning; 127 | } 128 | & .bg-alarm { 129 | background: $alarm; 130 | } 131 | 132 | 133 | } 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/_gridlayout.scss: -------------------------------------------------------------------------------- 1 | /* 2 | TODO Just 3 versions 3 | - large - all columns - 12 ? 4 | - medium - half of columns - 6 ? 5 | - small - just 1 column 6 | */ 7 | 8 | .db-grid-layout { 9 | display: grid; 10 | grid-auto-rows: minmax(100px, auto); 11 | 12 | .rspan-1 { grid-row-end: span 1; } 13 | .rspan-2 { grid-row-end: span 2; } 14 | .rspan-3 { grid-row-end: span 3; } 15 | .rspan-4 { grid-row-end: span 4; } 16 | .rspan-5 { grid-row-end: span 5; } 17 | .rspan-6 { grid-row-end: span 6; } 18 | .rspan-7 { grid-row-end: span 7; } 19 | .rspan-8 { grid-row-end: span 8; } 20 | .rspan-9 { grid-row-end: span 9; } 21 | .rspan-10 { grid-row-end: span 10; } 22 | .rspan-11 { grid-row-end: span 11; } 23 | .rspan-12 { grid-row-end: span 12; } 24 | .rspan-13 { grid-row-end: span 13; } 25 | .rspan-14 { grid-row-end: span 14; } 26 | .rspan-15 { grid-row-end: span 15; } 27 | .rspan-16 { grid-row-end: span 16; } 28 | } 29 | 30 | /* Small devices (portrait tablets and large phones, 600px and up) */ 31 | @media only screen and (min-width: 600px) { 32 | .db-grid-layout { 33 | /* minmax(0px, 1fr) - very important, resizing (making window smaller) on Firefox does not work without it 34 | * See https://github.com/w3c/csswg-drafts/issues/1777 */ 35 | grid-template-columns: repeat(16, minmax(0px, 1fr)); 36 | .cspan-1 { grid-column-end: span 8; } 37 | .cspan-2 { grid-column-end: span 16; } 38 | .cspan-3 { grid-column-end: span 16; } 39 | .cspan-4 { grid-column-end: span 16; } 40 | .cspan-5 { grid-column-end: span 16; } 41 | .cspan-6 { grid-column-end: span 16; } 42 | .cspan-7 { grid-column-end: span 16; } 43 | .cspan-8 { grid-column-end: span 16; } 44 | .cspan-9 { grid-column-end: span 16; } 45 | .cspan-10 { grid-column-end: span 16; } 46 | .cspan-11 { grid-column-end: span 16; } 47 | .cspan-12 { grid-column-end: span 16; } 48 | .cspan-13 { grid-column-end: span 16; } 49 | .cspan-14 { grid-column-end: span 16; } 50 | .cspan-15 { grid-column-end: span 16; } 51 | .cspan-16 { grid-column-end: span 16; } 52 | } 53 | } 54 | 55 | /* Medium devices (landscape tablets, 768px and up) */ 56 | @media only screen and (min-width: 768px) { 57 | .db-grid-layout { 58 | grid-template-columns: repeat(16, minmax(0px, 1fr)); 59 | .cspan-1 { grid-column-end: span 4; } 60 | .cspan-2 { grid-column-end: span 8; } 61 | .cspan-3 { grid-column-end: span 12; } 62 | .cspan-4 { grid-column-end: span 16; } 63 | .cspan-5 { grid-column-end: span 16; } 64 | .cspan-6 { grid-column-end: span 16; } 65 | .cspan-7 { grid-column-end: span 16; } 66 | .cspan-8 { grid-column-end: span 16; } 67 | .cspan-9 { grid-column-end: span 16; } 68 | .cspan-10 { grid-column-end: span 16; } 69 | .cspan-11 { grid-column-end: span 16; } 70 | .cspan-12 { grid-column-end: span 16; } 71 | .cspan-13 { grid-column-end: span 16; } 72 | .cspan-14 { grid-column-end: span 16; } 73 | .cspan-15 { grid-column-end: span 16; } 74 | .cspan-16 { grid-column-end: span 16; } 75 | } 76 | } 77 | 78 | /* Large devices (laptops/desktops, 992px and up) */ 79 | @media only screen and (min-width: 992px) { 80 | .db-grid-layout { 81 | grid-template-columns: repeat(16, minmax(0px, 1fr)); 82 | .cspan-1 { grid-column-end: span 2; } 83 | .cspan-2 { grid-column-end: span 4; } 84 | .cspan-3 { grid-column-end: span 6; } 85 | .cspan-4 { grid-column-end: span 8; } 86 | .cspan-5 { grid-column-end: span 10; } 87 | .cspan-6 { grid-column-end: span 12; } 88 | .cspan-7 { grid-column-end: span 14; } 89 | .cspan-8 { grid-column-end: span 16; } 90 | .cspan-9 { grid-column-end: span 16; } 91 | .cspan-10 { grid-column-end: span 16; } 92 | .cspan-11 { grid-column-end: span 16; } 93 | .cspan-12 { grid-column-end: span 16; } 94 | .cspan-13 { grid-column-end: span 16; } 95 | .cspan-14 { grid-column-end: span 16; } 96 | .cspan-15 { grid-column-end: span 16; } 97 | .cspan-16 { grid-column-end: span 16; } 98 | } 99 | } 100 | 101 | /* Extra large devices (large laptops and desktops, 1200px and up) */ 102 | @media only screen and (min-width: 1200px) { 103 | .db-grid-layout { 104 | /* minmax(0px, 1fr) - very important, resizing (making window smaller) on Firefox does not work without it */ 105 | grid-template-columns: repeat(16, minmax(0px, 1fr)); 106 | .cspan-1 { grid-column-end: span 1; } 107 | .cspan-2 { grid-column-end: span 2; } 108 | .cspan-3 { grid-column-end: span 3; } 109 | .cspan-4 { grid-column-end: span 4; } 110 | .cspan-5 { grid-column-end: span 5; } 111 | .cspan-6 { grid-column-end: span 6; } 112 | .cspan-7 { grid-column-end: span 7; } 113 | .cspan-8 { grid-column-end: span 8; } 114 | .cspan-9 { grid-column-end: span 9; } 115 | .cspan-10 { grid-column-end: span 10; } 116 | .cspan-11 { grid-column-end: span 11; } 117 | .cspan-12 { grid-column-end: span 12; } 118 | .cspan-13 { grid-column-end: span 13; } 119 | .cspan-14 { grid-column-end: span 14; } 120 | .cspan-15 { grid-column-end: span 15; } 121 | .cspan-16 { grid-column-end: span 16; } 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/_gridlayout12.scss: -------------------------------------------------------------------------------- 1 | /* CSS Grid layout - 12 columns */ 2 | 3 | .db-grid-layout-12 { 4 | display: grid; 5 | grid-auto-rows: minmax(100px, auto); 6 | .rspan-1 { grid-row-end: span 1; } 7 | .rspan-2 { grid-row-end: span 2; } 8 | .rspan-3 { grid-row-end: span 3; } 9 | .rspan-4 { grid-row-end: span 4; } 10 | .rspan-5 { grid-row-end: span 5; } 11 | .rspan-6 { grid-row-end: span 6; } 12 | .rspan-7 { grid-row-end: span 7; } 13 | .rspan-8 { grid-row-end: span 8; } 14 | .rspan-9 { grid-row-end: span 9; } 15 | .rspan-10 { grid-row-end: span 10; } 16 | .rspan-11 { grid-row-end: span 11; } 17 | .rspan-12 { grid-row-end: span 12; } 18 | .rspan-13 { grid-row-end: span 13; } 19 | .rspan-14 { grid-row-end: span 14; } 20 | .rspan-15 { grid-row-end: span 15; } 21 | .rspan-16 { grid-row-end: span 16; } 22 | } 23 | 24 | /* Small devices (portrait tablets and large phones, 600px and up) */ 25 | @media only screen and (min-width: 600px) { 26 | .db-grid-layout-12 { 27 | /* minmax(0px, 1fr) - very important, resizing (making window smaller) on Firefox does not work without it 28 | * See https://github.com/w3c/csswg-drafts/issues/1777 */ 29 | grid-template-columns: repeat(12, minmax(0px, 1fr)); 30 | .cspan-1 { grid-column-end: span 6; } 31 | .cspan-2 { grid-column-end: span 12; } 32 | .cspan-3 { grid-column-end: span 12; } 33 | .cspan-4 { grid-column-end: span 12; } 34 | .cspan-5 { grid-column-end: span 12; } 35 | .cspan-6 { grid-column-end: span 12; } 36 | .cspan-7 { grid-column-end: span 12; } 37 | .cspan-8 { grid-column-end: span 12; } 38 | .cspan-9 { grid-column-end: span 12; } 39 | .cspan-10 { grid-column-end: span 12; } 40 | .cspan-11 { grid-column-end: span 12; } 41 | .cspan-12 { grid-column-end: span 12; } 42 | } 43 | } 44 | 45 | /* Medium devices (landscape tablets, 768px and up) */ 46 | @media only screen and (min-width: 768px) { 47 | .db-grid-layout-12 { 48 | grid-template-columns: repeat(12, minmax(0px, 1fr)); 49 | .cspan-1 { grid-column-end: span 4; } 50 | .cspan-2 { grid-column-end: span 6; } 51 | .cspan-3 { grid-column-end: span 8; } 52 | .cspan-4 { grid-column-end: span 10; } 53 | .cspan-5 { grid-column-end: span 12; } 54 | .cspan-6 { grid-column-end: span 12; } 55 | .cspan-7 { grid-column-end: span 12; } 56 | .cspan-8 { grid-column-end: span 12; } 57 | .cspan-9 { grid-column-end: span 12; } 58 | .cspan-10 { grid-column-end: span 12; } 59 | .cspan-11 { grid-column-end: span 12; } 60 | .cspan-12 { grid-column-end: span 12; } 61 | } 62 | } 63 | 64 | /* Large devices (laptops/desktops, 992px and up) */ 65 | @media only screen and (min-width: 992px) { 66 | .db-grid-layout-12 { 67 | grid-template-columns: repeat(12, minmax(0px, 1fr)); 68 | .cspan-1 { grid-column-end: span 2; } 69 | .cspan-2 { grid-column-end: span 4; } 70 | .cspan-3 { grid-column-end: span 6; } 71 | .cspan-4 { grid-column-end: span 8; } 72 | .cspan-5 { grid-column-end: span 10; } 73 | .cspan-6 { grid-column-end: span 12; } 74 | .cspan-7 { grid-column-end: span 12; } 75 | .cspan-8 { grid-column-end: span 12; } 76 | .cspan-9 { grid-column-end: span 12; } 77 | .cspan-10 { grid-column-end: span 12; } 78 | .cspan-11 { grid-column-end: span 12; } 79 | .cspan-12 { grid-column-end: span 12; } 80 | } 81 | } 82 | 83 | /* Extra large devices (large laptops and desktops, 1200px and up) */ 84 | @media only screen and (min-width: 1200px) { 85 | .db-grid-layout-12 { 86 | /* minmax(0px, 1fr) - very important, resizing (making window smaller) on Firefox does not work without it */ 87 | grid-template-columns: repeat(12, minmax(0px, 1fr)); 88 | .cspan-1 { grid-column-end: span 1; } 89 | .cspan-2 { grid-column-end: span 2; } 90 | .cspan-3 { grid-column-end: span 3; } 91 | .cspan-4 { grid-column-end: span 4; } 92 | .cspan-5 { grid-column-end: span 5; } 93 | .cspan-6 { grid-column-end: span 6; } 94 | .cspan-7 { grid-column-end: span 7; } 95 | .cspan-8 { grid-column-end: span 8; } 96 | .cspan-9 { grid-column-end: span 9; } 97 | .cspan-10 { grid-column-end: span 10; } 98 | .cspan-11 { grid-column-end: span 11; } 99 | .cspan-12 { grid-column-end: span 12; } 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/_variables.scss: -------------------------------------------------------------------------------- 1 | 2 | // Dashblocks Variables 3 | 4 | $primary : #027BE3; 5 | $secondary : #26A69A; 6 | $accent : #9C27B0; 7 | 8 | $positive : #21BA45; 9 | $negative : #C10015; 10 | $info : #31CCEC; 11 | $warning : #F2C037; 12 | 13 | $light : #bdbdbd; 14 | $dark : #424242; 15 | $faded : #777; 16 | 17 | $white : #FFFFFF; 18 | $black : #000000; 19 | 20 | 21 | // Colors for ranges 22 | $neutral : material-color('light-blue', '900'); 23 | $success : material-color('light-green', '900'); 24 | $warning : material-color('orange', '900'); 25 | $alarm : material-color('red', '900'); 26 | 27 | // TODO - is this needed ? 28 | $dimmed-background : rgba(0, 0, 0, .4); 29 | $light-dimmed-background : rgba(255, 255, 255, .6); 30 | $separator-color : rgba(0, 0, 0, .12); 31 | $separator-dark-color : rgba(255, 255, 255, .48); 32 | 33 | 34 | // Fonts 35 | $font-family: 'Roboto', sans-serif; 36 | $font-size: 14px; 37 | 38 | // Text - TODO - is it needed ? 39 | $on-primary: white; 40 | $on-secondary: black; 41 | $on-background: material-color('grey', '800'); 42 | $on-surface: $faded; 43 | $on-error: white; 44 | 45 | 46 | 47 | 48 | // Sidebar variables 49 | 50 | $primaryColor: #4285f4 !default; 51 | $baseBg: #2a2a2e !default; 52 | $baseIconBg: red !default; 53 | $darkenBg: darken( $baseBg, 5% ) !default; 54 | $lightenBg: lighten( $baseBg, 5% ) !default; 55 | 56 | $itemColor: #fff !default; 57 | 58 | $itemOpenColor: #fff !default; 59 | $itemOpenBg: $primaryColor !default; 60 | 61 | $itemHoverColor: #fff !default; 62 | $itemHoverBg: rgba($darkenBg, 0.5) !default; 63 | 64 | $iconColor: #fff !default; 65 | $iconBg: darken( $baseIconBg, 25% ) !default; 66 | 67 | $iconActiveColor: #fff !default; 68 | $iconActiveBg: lighten( $baseIconBg, 10% ) !default; 69 | 70 | $iconOpenColor: #fff !default; 71 | $iconOpenBg: transparent !default; 72 | 73 | $mobileItemColor: #fff !default; 74 | $mobileItemBg: $primaryColor !default; 75 | $mobileIconBg: transparent !default; 76 | $mobileIconColor: #fff !default; 77 | 78 | $dropDownColor: #fff !default; 79 | $dropDownBg: $lightenBg !default; 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/components/_dbdygraps.scss: -------------------------------------------------------------------------------- 1 | .db-dygraphs { 2 | width: 100%; 3 | height: 100%; 4 | 5 | & .dygraph-axis-label { 6 | font-size: 12px; 7 | } 8 | 9 | & .dygraph-ylabel { 10 | font-size: 16px; 11 | } 12 | 13 | & .dygraph-title { 14 | font-size: 16px; 15 | font-weight: normal; 16 | text-align: left; 17 | } 18 | 19 | & .dygraph-legend { 20 | background-color: rgba(255, 255, 255, 0.85); 21 | padding: 4px; 22 | border: 1px solid #e0e0e0; 23 | border-radius: 2px; 24 | pointer-events: none; 25 | min-width: 250px; 26 | max-width: 600px; 27 | width: fit-content; 28 | font-size: 12px; 29 | position: relative; 30 | } 31 | } 32 | 33 | .db-dark { 34 | & .db-dygraphs { 35 | & .dygraph-legend { 36 | color: #e0e0e0; 37 | background-color: rgba(69, 90, 100, 0.5); 38 | padding: 4px; 39 | border: 1px solid #263238; 40 | border-radius: 2px; 41 | pointer-events: none; 42 | min-width: 250px; 43 | max-width: 600px; 44 | width: fit-content; 45 | font-size: 12px; 46 | position: relative; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/components/_dbeasypie.scss: -------------------------------------------------------------------------------- 1 | .db-easy-pie { 2 | position: relative; 3 | text-align: center; 4 | width: 100%; 5 | height: 100%; 6 | 7 | .inner-text { 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | right: 0; 12 | bottom: 0; 13 | text-align: center; 14 | display: block; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/components/_dbnumber.scss: -------------------------------------------------------------------------------- 1 | .db-number { 2 | width: 100%; 3 | height: 100%; 4 | display: flex; 5 | flex-flow: column; 6 | 7 | .db-n-content { 8 | width: 100%; 9 | flex: 2; 10 | position: relative; 11 | } 12 | 13 | .db-n-layer { 14 | position: absolute; 15 | width: 100%; 16 | height: 100%; 17 | } 18 | 19 | .db-n-main { 20 | position: relative; 21 | width: 100%; 22 | height: 100%; 23 | } 24 | 25 | .db-n-value { 26 | font-size: 210%; 27 | } 28 | .db-n-footer { 29 | height: 18px; 30 | } 31 | 32 | .db-n-subtitle { 33 | font-size: 100%; 34 | } 35 | 36 | .db-n-icon { 37 | font-size: 180%; 38 | padding: 2px; 39 | border-radius: 4px; 40 | color: white; 41 | opacity: 0.4; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/themes/_theme-dark.scss: -------------------------------------------------------------------------------- 1 | @import "../dbdashboard"; 2 | 3 | $accent: red; 4 | 5 | .db-dashboard.db-theme-dark { 6 | @include db-dashboard; 7 | color: white; 8 | 9 | & .db-widget-container { 10 | border: 1px solid material-color('red', '600'); 11 | } 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/assets/scss/dashblocks/themes/_theme-default.scss: -------------------------------------------------------------------------------- 1 | @import '../dbdashboard'; 2 | 3 | 4 | // TODO How to override variables for dark scheme ? 5 | 6 | .db-dashboard.db-theme-default { 7 | @include db-dashboard; 8 | 9 | & .db-txt-faded { 10 | color: material-color('grey', '700'); 11 | } 12 | 13 | & .db-txt-highlight { 14 | color: material-color('grey', '800'); 15 | } 16 | 17 | } 18 | 19 | .db-dashboard.db-theme-default.db-dark { 20 | color: $faded; 21 | 22 | & .db-txt-faded { 23 | color: material-color('grey', '700'); 24 | } 25 | 26 | & .db-txt-highlight { 27 | color: material-color('grey', '500'); 28 | } 29 | 30 | & .db-widget-container { 31 | border: 0px; 32 | background: material-color('grey', '900'); 33 | } 34 | 35 | & .dygraph-axis-label { 36 | color: $light; 37 | } 38 | } 39 | 40 | .db-dashboard.db-transparent.db-theme-default { 41 | & .db-widget-container { 42 | background: none; 43 | } 44 | } 45 | 46 | .db-rsb { 47 | display: grid; 48 | grid-template-columns: 1fr minmax(100px, 25%); 49 | } 50 | -------------------------------------------------------------------------------- /src/components.js: -------------------------------------------------------------------------------- 1 | export * from './components/dashboard/index.js'; 2 | export * from './components/dygraphs/index.js'; 3 | export * from './components/chartjs/index.js'; 4 | export * from './components/db/index.js'; 5 | export * from './components/funnel/index.js'; 6 | export * from './components/d3/index.js'; 7 | export * from './components/perspective/index.js'; 8 | export * from './components/geo/index.js'; 9 | -------------------------------------------------------------------------------- /src/components/chartjs/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | DbChartjsBar, 3 | DbChartjsHorizontalBar, 4 | DbChartjsDoughnut, 5 | DbChartjsLine, 6 | DbChartjsPie, 7 | DbChartjsPolarArea, 8 | DbChartjsRadar, 9 | DbChartjsBubble, 10 | DbChartjsScatter, 11 | DbChartjsFunnel 12 | } from './DbChartjs'; 13 | 14 | export { 15 | DbChartjsBar, 16 | DbChartjsHorizontalBar, 17 | DbChartjsDoughnut, 18 | DbChartjsLine, 19 | DbChartjsPie, 20 | DbChartjsPolarArea, 21 | DbChartjsRadar, 22 | DbChartjsBubble, 23 | DbChartjsScatter, 24 | DbChartjsFunnel 25 | }; 26 | -------------------------------------------------------------------------------- /src/components/d3/domuid.js: -------------------------------------------------------------------------------- 1 | let count = 0; 2 | 3 | export default function(name) { 4 | return new Id('O-' + (name == null ? '' : name + '-') + ++count); 5 | } 6 | 7 | function Id(id) { 8 | this.id = id; 9 | //this.href = window.location.href + "#" + id; 10 | this.href = '#' + id; 11 | } 12 | 13 | Id.prototype.toString = function() { 14 | return 'url(' + this.href + ')'; 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/d3/index.js: -------------------------------------------------------------------------------- 1 | import DbHorizon from './DbHorizon'; 2 | import DbSunburst from './DbSunburst'; 3 | import DbSankey from './DbSankey'; 4 | import DbRidgeline from './DbRidgeline'; 5 | 6 | export { DbHorizon, DbSunburst, DbSankey, DbRidgeline }; 7 | -------------------------------------------------------------------------------- /src/components/dashboard/DbDashboard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 80 | 81 | /* Notes ** That works: components: { 'WidgetOne': () => import('./WidgetOne.vue') }, */ 82 | -------------------------------------------------------------------------------- /src/components/dashboard/index.js: -------------------------------------------------------------------------------- 1 | import DbDashboard from './DbDashboard'; 2 | 3 | export { DbDashboard }; 4 | -------------------------------------------------------------------------------- /src/components/db/DbEasyPie.vue: -------------------------------------------------------------------------------- 1 | 8 | 162 | -------------------------------------------------------------------------------- /src/components/db/DbMarkup.vue: -------------------------------------------------------------------------------- 1 | 4 | 15 | -------------------------------------------------------------------------------- /src/components/db/DbMultiProgress.vue: -------------------------------------------------------------------------------- 1 | /* DashBlocks: Multi-Progress 2 | * Shows multiple progress values simultaneously */ 3 | 15 | 16 | 157 | -------------------------------------------------------------------------------- /src/components/db/DbNone.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/components/db/DbNumber.vue: -------------------------------------------------------------------------------- 1 | /* DashBlocks: Number widget */ 2 | 32 | 33 | 151 | -------------------------------------------------------------------------------- /src/components/db/DbProgress.vue: -------------------------------------------------------------------------------- 1 | /* DashBlocks: Number widget */ 2 | 38 | 39 | 158 | 184 | -------------------------------------------------------------------------------- /src/components/db/DbSparkline.vue: -------------------------------------------------------------------------------- 1 | 6 | 134 | -------------------------------------------------------------------------------- /src/components/db/DbTrendBar.vue: -------------------------------------------------------------------------------- 1 | /* DbTrendLine: Trend Line using https://github.com/QingWei-Li/vue-trend */ 2 | 20 | 102 | -------------------------------------------------------------------------------- /src/components/db/DbTrendLine.vue: -------------------------------------------------------------------------------- 1 | /* DbTrendLine: Trend Line using https://github.com/QingWei-Li/vue-trend */ 2 | 23 | 116 | -------------------------------------------------------------------------------- /src/components/db/index.js: -------------------------------------------------------------------------------- 1 | import DbNumber from './DbNumber'; 2 | import DbEasyPie from './DbEasyPie'; 3 | import DbTrendLine from './DbTrendLine'; 4 | import DbTrendBar from './DbTrendBar'; 5 | import DbSparkline from './DbSparkline'; 6 | import DbSparkLineMap from './DbSparkLinemap'; 7 | import DbSparkHeatMap from './DbSparkHeatmap'; 8 | import DbNone from './DbNone'; 9 | import DbMarkup from './DbMarkup'; 10 | import DbLinearProgress from './DbLinearProgress'; 11 | import DbProgress from './DbProgress'; 12 | import DbMultiProgress from './DbMultiProgress'; 13 | //import DbSparkRidgeline from './DbSparkRidgeline'; 14 | 15 | export { DbNumber, DbEasyPie, DbTrendLine, DbTrendBar, DbSparkline, DbSparkLineMap, DbSparkHeatMap, DbNone, DbMarkup, DbLinearProgress, DbProgress, DbMultiProgress}; 16 | -------------------------------------------------------------------------------- /src/components/dbdata.js: -------------------------------------------------------------------------------- 1 | /* DashBlocks Data */ 2 | 3 | import Vue from 'vue'; 4 | import pathOr from 'ramda/es/pathOr'; 5 | 6 | // TODO Support different kinds of data 7 | // - plain hash by widget name 8 | // - tabular data - i.e. query result from SQL 9 | // - support "query" in widgets to get data from table 10 | // - dataframes 11 | 12 | /* DashBlocks Data holder */ 13 | class DbData { 14 | constructor() { 15 | // TODO accept widgets data set here 16 | // go through each key and add _updated 17 | this._updated = Date.now(); 18 | } 19 | 20 | // TODO Get 21 | 22 | // TODO Set / Update 23 | setWData(key, data) { 24 | /* 25 | if (!(key in this)) { 26 | Vue.set(this, key, {d:data}); 27 | Vue.set(this[key], '_updated', Date.now()); 28 | } else { 29 | //Vue.set(this, key, data); 30 | this[key].d = data; 31 | this[key]['_updated'] = Date.now(); 32 | }*/ 33 | Vue.set(this, key, data); 34 | Vue.set(this[key], '_updated', Date.now()); 35 | this['_updated'] = Date.now(); 36 | } 37 | 38 | setUpdated(key) { 39 | Vue.set(this[key], '_updated', Date.now()); 40 | Vue.set(this, '_updated', Date.now()); 41 | } 42 | 43 | touch(key) { 44 | Vue.set(this[key], '_updated', Date.now()); 45 | Vue.set(this, '_updated', Date.now()); 46 | } 47 | 48 | getWData(key) { 49 | return pathOr(null, [key], this); 50 | } 51 | 52 | // TODO in setters, modify property like _updated = Date.now(), to trigger prop watch 53 | } 54 | 55 | export default DbData; 56 | -------------------------------------------------------------------------------- /src/components/dblayouts.js: -------------------------------------------------------------------------------- 1 | // Import all Db Layouts 2 | import DbGridLayout from './layout/DbGridLayout.vue'; 3 | 4 | // Mapping of layout name to layout component name 5 | const DB_LAYOUT = Object.freeze({ 6 | grid: 'DbGridLayout' 7 | }); 8 | 9 | // Resolve layout component by layout name 10 | function resolveLayout(layoutname) { 11 | // grid is default 12 | if (!(layoutname in DB_LAYOUT)) { 13 | return 'DbGridLayout'; 14 | } 15 | return DB_LAYOUT[layoutname]; 16 | } 17 | 18 | export default { 19 | DB_LAYOUT: DB_LAYOUT, 20 | components: { 21 | DbGridLayout 22 | }, 23 | resolve: resolveLayout 24 | }; 25 | -------------------------------------------------------------------------------- /src/components/dbwidgets.js: -------------------------------------------------------------------------------- 1 | // Import all Db Widgets 2 | import DbHorizon from './d3/DbHorizon'; 3 | import DbSunburst from './d3/DbSunburst'; 4 | import DbSankey from './d3/DbSankey'; 5 | import DbRidgeline from './d3/DbRidgeline'; 6 | import { 7 | DbChartjsBar, 8 | DbChartjsHorizontalBar, 9 | DbChartjsDoughnut, 10 | DbChartjsLine, 11 | DbChartjsPie, 12 | DbChartjsPolarArea, 13 | DbChartjsRadar, 14 | DbChartjsBubble, 15 | DbChartjsScatter 16 | } from './chartjs/DbChartjs'; 17 | import DbNumber from './db/DbNumber'; 18 | import DbEasyPie from './db/DbEasyPie'; 19 | import DbTrendLine from './db/DbTrendLine'; 20 | import DbTrendBar from './db/DbTrendBar'; 21 | import DbSparkline from './db/DbSparkline'; 22 | /* TODO Revisit Plotly 23 | import DbPlotly from './plotly/DbPlotly'; 24 | import DbPlotlyLine from './plotly/DbPlotlyLine'; 25 | import DbPlotlyPie from './plotly/DbPlotlyPie'; 26 | */ 27 | import DbDygraphsBar from './dygraphs/DbDygraphsBar'; 28 | import DbDygraphsLine from './dygraphs/DbDygraphsLine'; 29 | import DbDygraphsSparkLine from './dygraphs/DbDygraphsSparkLine'; 30 | import DbDygraphsDateTimeHistogram from './dygraphs/DbDygraphsDateTimeHistogram'; 31 | 32 | export { 33 | DbHorizon, 34 | DbSunburst, 35 | DbSankey, 36 | DbRidgeline, 37 | DbChartjsBar, 38 | DbChartjsHorizontalBar, 39 | DbChartjsDoughnut, 40 | DbChartjsLine, 41 | DbChartjsPie, 42 | DbChartjsPolarArea, 43 | DbChartjsRadar, 44 | DbChartjsBubble, 45 | DbChartjsScatter, 46 | DbNumber, 47 | DbEasyPie, 48 | DbTrendLine, 49 | DbTrendBar, 50 | DbSparkline, 51 | /* 52 | DbPlotly, 53 | DbPlotlyLine, 54 | DbPlotlyPie, 55 | */ 56 | DbDygraphsBar, 57 | DbDygraphsLine, 58 | DbDygraphsSparkLine, 59 | DbDygraphsDateTimeHistogram 60 | }; 61 | -------------------------------------------------------------------------------- /src/components/dygraphs/DbDygraphsBar.vue: -------------------------------------------------------------------------------- 1 | 4 | 114 | -------------------------------------------------------------------------------- /src/components/dygraphs/DbDygraphsDateTimeHistogram.vue: -------------------------------------------------------------------------------- 1 | 6 | 136 | 153 | -------------------------------------------------------------------------------- /src/components/dygraphs/DbDygraphsLine.vue: -------------------------------------------------------------------------------- 1 | 4 | 70 | 98 | -------------------------------------------------------------------------------- /src/components/dygraphs/index.js: -------------------------------------------------------------------------------- 1 | import DbDygraphs from './DbDygraphs'; 2 | import DbDygraphsBar from './DbDygraphsBar'; 3 | import DbDygraphsLine from './DbDygraphsLine'; 4 | import DbDygraphsSparkLine from './DbDygraphsSparkLine'; 5 | import DbDygraphsDateTimeHistogram from './DbDygraphsDateTimeHistogram'; 6 | 7 | export { DbDygraphs, DbDygraphsBar, DbDygraphsLine, DbDygraphsSparkLine, DbDygraphsDateTimeHistogram }; 8 | -------------------------------------------------------------------------------- /src/components/funnel/index.js: -------------------------------------------------------------------------------- 1 | import DbFunnel from './DbFunnel'; 2 | 3 | export { DbFunnel }; 4 | -------------------------------------------------------------------------------- /src/components/geo/index.js: -------------------------------------------------------------------------------- 1 | import DbGeoMapbox from './DbGeoMapbox'; 2 | 3 | export { DbGeoMapbox }; 4 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import DbData from './dbdata'; 2 | import DbColors from './dbcolors'; 3 | import DbUtils from './dbutils'; 4 | import DbDashboard from './dashboard/DbDashboard'; 5 | import { dbStdProps } from './mixins/dbstdprops'; 6 | //import DbDygraphsBar from './dygraphs/DbDygraphsBar'; 7 | // ??? 8 | import * as dbComponents from './dbwidgets'; 9 | import '../assets/scss/dashblocks.scss'; 10 | 11 | const DashBlocks = { 12 | install(Vue) { 13 | Vue.component('DbDashboard', DbDashboard); 14 | 15 | Object.keys(dbComponents).forEach(key => { 16 | const c = dbComponents[key]; 17 | Vue.component(key, c); 18 | }); 19 | 20 | //Vue.component('DbDygraphsBar', DbDygraphsBar); 21 | /* 22 | Vue.component('db-dygraphs-bundle', function(resolve) { 23 | // This special require syntax will instruct Webpack to 24 | // automatically split your built code into bundles which 25 | // are loaded over Ajax requests. 26 | require(['./dygraphs/DbDygraphsBar'], resolve); 27 | }); 28 | */ 29 | } 30 | }; 31 | 32 | export { DbData, DbColors, DbUtils, DbDashboard, DashBlocks, dbStdProps }; 33 | 34 | //export default DashBlocks; 35 | 36 | /* TODO Consider this, make reasonable bundles of components based on underlying library 37 | 38 | Vue.component('async-webpack-example', function (resolve) { 39 | // This special require syntax will instruct Webpack to 40 | // automatically split your built code into bundles which 41 | // are loaded over Ajax requests. 42 | require(['./my-async-component'], resolve) 43 | }) 44 | 45 | */ 46 | 47 | /* 48 | const DashBlocks = { 49 | install(Vue) { 50 | Object.keys(dbComponents).forEach(name => { 51 | Vue.component(name, dbComponents[name]); 52 | }); 53 | } 54 | }; 55 | */ 56 | 57 | /* 58 | Object.keys(DashBlocks).forEach(name => { 59 | console.log('Registergin component: ' + name); 60 | Vue.component(name, DashBlocks[name]); 61 | }); 62 | 63 | export default DashBlocks; 64 | */ 65 | -------------------------------------------------------------------------------- /src/components/layout/DbGridLayout.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 76 | 81 | -------------------------------------------------------------------------------- /src/components/layout/DbWidgetContainer.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 99 | 100 | -------------------------------------------------------------------------------- /src/components/log.js: -------------------------------------------------------------------------------- 1 | import * as log from 'loglevel'; 2 | import moment from 'moment'; 3 | 4 | let LOG_LEVEL = 'info'; 5 | 6 | let origFactory = log.methodFactory; 7 | log.methodFactory = function(methodName, logLevel, loggerName) { 8 | let origMethod = origFactory(methodName, logLevel, loggerName); 9 | return function(message) { 10 | const timestamp = moment([]).format('hh:mm:ss'); 11 | const msg = `${timestamp} [${methodName.toUpperCase()}] [DB]: ${message}`; 12 | origMethod(msg); 13 | }; 14 | }; 15 | 16 | //log.setLevel(log.getLevel()); 17 | log.setLevel(LOG_LEVEL); 18 | 19 | export default log; 20 | -------------------------------------------------------------------------------- /src/components/mixins/dbstdprops.js: -------------------------------------------------------------------------------- 1 | // Standard properties for Dashblocks components 2 | export const dbStdProps = { 3 | props: { 4 | /** 5 | * Change to trigger data update. 6 | * Set this to current timestamp to inform component that data has been updated. 7 | * Helpful in situations when, for example, only values in array are changed. 8 | * See https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats 9 | */ 10 | _updated: { 11 | type: Number, 12 | default: 0 13 | }, 14 | /** 15 | * Enable dark mode 16 | * 17 | * `true,false` 18 | */ 19 | dark: { 20 | type: Boolean, 21 | default: false 22 | }, 23 | /** 24 | * Color Scheme Name 25 | * App may define multiple color schemes for different charts 26 | * and use this prop to specify which colorScheme to use 27 | * default: "default" - refers to default dashblocks colorScheme which is always defined 28 | */ 29 | colorScheme: { 30 | type: String, 31 | default: 'default' 32 | } 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/perspective/DbPerspective.vue: -------------------------------------------------------------------------------- 1 | /* DbPerspective * Perspective viewer: https://perspective.finos.org/ */ 2 | 5 | 61 | -------------------------------------------------------------------------------- /src/components/perspective/index.js: -------------------------------------------------------------------------------- 1 | import DbPerspective from './DbPerspective'; 2 | 3 | export { DbPerspective }; 4 | -------------------------------------------------------------------------------- /src/components/plotly/DbPlotly.vue: -------------------------------------------------------------------------------- 1 | 4 | 78 | 79 | -------------------------------------------------------------------------------- /src/components/plotly/DbPlotlyLine.vue: -------------------------------------------------------------------------------- 1 | 4 | 47 | 48 | -------------------------------------------------------------------------------- /src/components/plotly/DbPlotlyPie.vue: -------------------------------------------------------------------------------- 1 | 4 | 45 | -------------------------------------------------------------------------------- /src/components/utils/colors.js: -------------------------------------------------------------------------------- 1 | import map from 'lodash/map'; 2 | import sortBy from 'lodash/sortBy'; 3 | import flattenDeep from 'lodash/flattenDeep'; 4 | import chunk from 'lodash/chunk'; 5 | import zip from 'lodash/zip'; 6 | import tinycolor from 'tinycolor2'; 7 | 8 | export const PALETTE_ROWS = 4; 9 | export const PALETTE_COLUMNS = 14; 10 | export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)'; 11 | export const OK_COLOR = 'rgba(11, 237, 50, 1)'; 12 | export const ALERTING_COLOR = 'rgba(237, 46, 24, 1)'; 13 | export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; 14 | export const PENDING_COLOR = 'rgba(247, 149, 32, 1)'; 15 | export const REGION_FILL_ALPHA = 0.09; 16 | export const colors = [ 17 | '#7EB26D', // 0: pale green 18 | '#EAB839', // 1: mustard 19 | '#6ED0E0', // 2: light blue 20 | '#EF843C', // 3: orange 21 | '#E24D42', // 4: red 22 | '#1F78C1', // 5: ocean 23 | '#BA43A9', // 6: purple 24 | '#705DA0', // 7: violet 25 | '#508642', // 8: dark green 26 | '#CCA300', // 9: dark sand 27 | '#447EBC', 28 | '#C15C17', 29 | '#890F02', 30 | '#0A437C', 31 | '#6D1F62', 32 | '#584477', 33 | '#B7DBAB', 34 | '#F4D598', 35 | '#70DBED', 36 | '#F9BA8F', 37 | '#F29191', 38 | '#82B5D8', 39 | '#E5A8E2', 40 | '#AEA2E0', 41 | '#629E51', 42 | '#E5AC0E', 43 | '#64B0C8', 44 | '#E0752D', 45 | '#BF1B00', 46 | '#0A50A1', 47 | '#962D82', 48 | '#614D93', 49 | '#9AC48A', 50 | '#F2C96D', 51 | '#65C5DB', 52 | '#F9934E', 53 | '#EA6460', 54 | '#5195CE', 55 | '#D683CE', 56 | '#806EB7', 57 | '#3F6833', 58 | '#967302', 59 | '#2F575E', 60 | '#99440A', 61 | '#58140C', 62 | '#052B51', 63 | '#511749', 64 | '#3F2B5B', 65 | '#E0F9D7', 66 | '#FCEACA', 67 | '#CFFAFF', 68 | '#F9E2D2', 69 | '#FCE2DE', 70 | '#BADFF4', 71 | '#F9D9F9', 72 | '#DEDAF7' 73 | ]; 74 | 75 | function sortColorsByHue(hexColors) { 76 | const hslColors = map(hexColors, hexToHsl); 77 | 78 | const sortedHSLColors = sortBy(hslColors, ['h']); 79 | const chunkedHSLColors = chunk(sortedHSLColors, PALETTE_ROWS); 80 | const sortedChunkedHSLColors = map(chunkedHSLColors, chunk => { 81 | return sortBy(chunk, 'l'); 82 | }); 83 | const flattenedZippedSortedChunkedHSLColors = flattenDeep(zip(...sortedChunkedHSLColors)); 84 | 85 | return map(flattenedZippedSortedChunkedHSLColors, hslToHex); 86 | } 87 | 88 | function hexToHsl(color) { 89 | return tinycolor(color).toHsl(); 90 | } 91 | 92 | function hslToHex(color) { 93 | return tinycolor(color).toHexString(); 94 | } 95 | 96 | let sortedColors = sortColorsByHue(colors); 97 | export default sortedColors; 98 | -------------------------------------------------------------------------------- /src/css.js: -------------------------------------------------------------------------------- 1 | // TODO Consider if needed 2 | //import '../assets/vendor/nucleo/css/nucleo.css'; 3 | //import '../assets/vendor/font-awesome/css/font-awesome.css'; 4 | import './assets/scss/dashblocks.scss'; 5 | import './demo/themes/_theme_custom.scss'; 6 | -------------------------------------------------------------------------------- /src/demo/assets/images/poster_grand_tour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slanatech/dashblocks/313aa29d14a23c5d50389ba3e1bb447c33ab1aa9/src/demo/assets/images/poster_grand_tour.png -------------------------------------------------------------------------------- /src/demo/dashboards/ChartJsShowcase.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": { 3 | "type": "grid" 4 | }, 5 | "widgets": [ 6 | { 7 | "id": "w1", 8 | "type": "DbChartjsLine", 9 | "cspan": 4, 10 | "height": 250, 11 | "properties": { 12 | "options": { 13 | "maintainAspectRatio": false, 14 | "legend": { 15 | "labels": { 16 | "fontColor": "red" 17 | } 18 | } 19 | } 20 | } 21 | }, 22 | { 23 | "id": "w2", 24 | "type": "DbChartjsBar", 25 | "cspan": 4, 26 | "height": 250 27 | }, 28 | { 29 | "id": "w3", 30 | "type": "DbChartjsHorizontalBar", 31 | "cspan": 4 32 | }, 33 | { 34 | "id": "w4", 35 | "type": "DbChartjsPie", 36 | "cspan": 4 37 | }, 38 | { 39 | "id": "w5", 40 | "type": "DbChartjsDoughnut", 41 | "cspan": 4, 42 | "height": 250 43 | }, 44 | { 45 | "id": "w6", 46 | "type": "DbChartjsPolarArea", 47 | "cspan": 4, 48 | "height": 250 49 | }, 50 | { 51 | "id": "w7", 52 | "type": "DbChartjsRadar", 53 | "cspan": 4, 54 | "height": 250 55 | }, 56 | { 57 | "id": "w8", 58 | "type": "DbChartjsBar", 59 | "cspan": 4, 60 | "height": 250 61 | }, 62 | { 63 | "id": "w9", 64 | "type": "DbChartjsBubble", 65 | "cspan": 8, 66 | "height": 300 67 | }, 68 | { 69 | "id": "w10", 70 | "type": "DbChartjsScatter", 71 | "cspan": 8, 72 | "height": 300, 73 | "properties": { 74 | "options": { 75 | "scales": { 76 | "xAxes": [{ 77 | "type": "linear", 78 | "position": "bottom" 79 | }] 80 | } 81 | } 82 | } 83 | }, 84 | { 85 | "id": "w11", 86 | "type": "DbChartjsFunnel", 87 | "cspan": 8, 88 | "height": 300, 89 | "properties": { 90 | "options": { 91 | "sort": "desc", 92 | "keep": "auto", 93 | "legend": { 94 | "display": true 95 | } 96 | } 97 | } 98 | } 99 | ] 100 | } 101 | -------------------------------------------------------------------------------- /src/demo/dashboards/dashfive.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": { 3 | "type": "grid" 4 | }, 5 | "widgets": [ 6 | { 7 | "id": "wa", 8 | "type": "DbDygraphsBar", 9 | "cspan": 16, 10 | "height": 250, 11 | "properties": { 12 | "options": { 13 | "stackedGraph": true 14 | } 15 | } 16 | }, 17 | { 18 | "id": "w0", 19 | "type": "DbTrendLine", 20 | "cspan": 4, 21 | "properties": { 22 | "smooth": false, 23 | "strokeWidth": 1 24 | } 25 | }, 26 | { 27 | "id": "w0", 28 | "type": "DbTrendLine", 29 | "cspan": 4 30 | }, 31 | { 32 | "id": "w1", 33 | "type": "DbTrendBar", 34 | "cspan": 4 35 | }, 36 | { 37 | "id": "w2", 38 | "type": "DbTrendBar", 39 | "cspan": 4 40 | }, 41 | { 42 | "id": "w4", 43 | "type": "DbNumber", 44 | "cspan": 4, 45 | "properties": { 46 | "title": "Test OK", 47 | "badge": "req/s", 48 | "icon" : "fa fa-signal", 49 | "ranges": [1000,2000] 50 | } 51 | }, 52 | { 53 | "id": "w5", 54 | "type": "DbNumber", 55 | "cspan": 4, 56 | "properties": { 57 | "title": "Test Warning", 58 | "badge": "req/s", 59 | "icon" : "fa fa-clock", 60 | "ranges": [1000,2000] 61 | } 62 | }, 63 | { 64 | "id": "w6", 65 | "type": "DbNumber", 66 | "cspan": 4, 67 | "properties": { 68 | "title": "Test Alarm", 69 | "badge": "req/s", 70 | "icon" : "fa fa-chart-bar", 71 | "ranges": [1000,2000] 72 | } 73 | }, 74 | { 75 | "id": "w7", 76 | "type": "DbPlotly", 77 | "cspan": 16, 78 | "rspan": 2, 79 | "properties": { 80 | "layout": { 81 | "paper_bgcolor":"rgba(0,0,0,0)", 82 | "plot_bgcolor":"rgba(0,0,0,0)", 83 | "modebar": { 84 | "bgcolor": "rgba(0,0,0,0)", 85 | "color": "rgba(0,0,0,0.5)" 86 | }, 87 | "title": "reactive charts", 88 | "xaxis": { 89 | "title": "xaxis title" 90 | }, 91 | "yaxis": { 92 | "title": "yaxis title" 93 | }, 94 | "margin": { 95 | "l": 60, 96 | "r": 40, 97 | "b": 40, 98 | "t": 40, 99 | "pad": 5 100 | } 101 | } 102 | } 103 | }, 104 | { 105 | "id": "w8", 106 | "type": "DbPlotlyLine", 107 | "cspan": 10, 108 | "height": 300, 109 | "properties": { 110 | "layout": { 111 | "template": "plotly_dark", 112 | "paper_bgcolor":"rgba(0,0,0,0)", 113 | "plot_bgcolor":"rgba(0,0,0,0)", 114 | "modebar": { 115 | "bgcolor": "rgba(0,0,0,0)", 116 | "color": "rgba(0,0,0,0.5)" 117 | }, 118 | "margin": { 119 | "l": 60, 120 | "r": 40, 121 | "b": 40, 122 | "t": 40, 123 | "pad": 5 124 | } 125 | } 126 | } 127 | }, 128 | { 129 | "id": "w9", 130 | "type": "DbPlotlyPie", 131 | "cspan": 6, 132 | "height": 300, 133 | "properties": { 134 | "layout": { 135 | "legend": { 136 | "orientation": "h" 137 | }, 138 | "paper_bgcolor":"rgba(0,0,0,0)", 139 | "plot_bgcolor":"rgba(0,0,0,0)", 140 | "modebar": { 141 | "bgcolor": "rgba(0,0,0,0)", 142 | "color": "rgba(0,0,0,0.5)" 143 | }, 144 | "margin": { 145 | "l": 60, 146 | "r": 40, 147 | "b": 40, 148 | "t": 40, 149 | "pad": 5 150 | } 151 | } 152 | } 153 | } 154 | 155 | 156 | ] 157 | } 158 | -------------------------------------------------------------------------------- /src/demo/dashboards/dashsix.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": { 3 | "type": "grid" 4 | }, 5 | "widgets": [ 6 | { 7 | "id": "w1", 8 | "type": "DbDygraphsBar", 9 | "cspan": 16, 10 | "height": 250, 11 | "properties": { 12 | "options": { 13 | "stackedGraph": true 14 | } 15 | } 16 | }, 17 | { 18 | "id": "w2", 19 | "type": "DbDygraphsLine", 20 | "cspan": 8, 21 | "height": 300, 22 | "properties": { 23 | "options": { 24 | "stackedGraph": false, 25 | "title": "Random value Chart", 26 | "ylabel": "Probability", 27 | "labels" : ["Date","AAA","BBB"], 28 | "legend": "always" 29 | } 30 | } 31 | }, 32 | { 33 | "id": "w6", 34 | "type": "DbDygraphsLine", 35 | "cspan": 8, 36 | "height": 300, 37 | "properties": { 38 | "options": { 39 | "showRangeSelector": true, 40 | "stackedGraph": false, 41 | "title": "Random value Chart", 42 | "ylabel": "Probability", 43 | "labels" : ["Date","AAA","BBB"], 44 | "legend": "always" 45 | } 46 | } 47 | }, 48 | { 49 | "id": "w3", 50 | "type": "DbDygraphsSparkLine", 51 | "cspan": 4, 52 | "properties": { 53 | "smoothing": 0.5 54 | } 55 | }, 56 | { 57 | "id": "w4", 58 | "type": "DbDygraphsSparkLine", 59 | "cspan": 4, 60 | "properties": { 61 | "options": { 62 | "colors": ["gray"], 63 | "strokeWidth": 0, 64 | "fillGraph": true, 65 | "fillAlpha": 0.2 66 | } 67 | } 68 | }, 69 | { 70 | "id": "w5", 71 | "type": "DbDygraphsSparkLine", 72 | "cspan": 4, 73 | "properties": { 74 | "smoothing": 0.5 75 | } 76 | } 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /src/demo/dashboards/dashthree.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": { 3 | "type": "grid" 4 | }, 5 | "widgets": [ 6 | { 7 | "id": "w1", 8 | "type": "DbHorizon", 9 | "cspan": 16 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/demo/data/testdata.js: -------------------------------------------------------------------------------- 1 | /* DashBlocks - Test data for demo dashboards */ 2 | 3 | import dl from 'datalib'; 4 | //import pathOr from 'ramda/es/pathOr'; 5 | 6 | /* DashBlocks - Test data for demo dashboards */ 7 | class TestData { 8 | constructor() { 9 | this.stockdata = null; 10 | } 11 | 12 | init() { 13 | // Load test data 14 | this.stockdata = dl.csv('https://vega.github.io/datalib/data/stocks.csv'); 15 | } 16 | 17 | // TODO Methods 18 | } 19 | 20 | export default TestData; 21 | -------------------------------------------------------------------------------- /src/demo/mixins/demodashboard.js: -------------------------------------------------------------------------------- 1 | export const demodashboard = { 2 | computed: { 3 | isDark() { 4 | return this.$store.state.dark; 5 | }, 6 | dbSpecText() { 7 | return this.$store.state.dashboardSpec; 8 | } 9 | }, 10 | watch: { 11 | dbSpecText: function(val) { 12 | this.dbspec = JSON.parse(val); 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/demo/themes/README.md: -------------------------------------------------------------------------------- 1 | # Custom themes 2 | 3 | Examples of custom themes 4 | -------------------------------------------------------------------------------- /src/demo/themes/_theme_custom.scss: -------------------------------------------------------------------------------- 1 | // We need colors and variables 2 | @import "../../assets/scss/dashblocks/material-colors"; 3 | @import "../../assets/scss/dashblocks/variables"; 4 | 5 | // We need base dashboard style 6 | @import '../../assets/scss/dashblocks/dbdashboard'; 7 | 8 | // We override what is needed in out theme 9 | .db-dashboard.db-theme-custom { 10 | @include db-dashboard; 11 | 12 | color: red; 13 | 14 | background: #0f2027; /* fallback for old browsers */ 15 | background: -webkit-linear-gradient(to bottom, #0f2027, #203a43, #2c5364); /* Chrome 10-25, Safari 5.1-6 */ 16 | background: linear-gradient( 17 | to bottom, 18 | #0f2027, 19 | #203a43, 20 | #2c5364 21 | ); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ 22 | 23 | } 24 | 25 | // Dark mode 26 | .db-dashboard.db-theme-custom.db-dark { 27 | color: yellow; 28 | & .db-widget-container { 29 | border: 1px solid material-color('red', '800'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/demo/views/About.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | -------------------------------------------------------------------------------- /src/demo/views/ChartJsShowcase.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 152 | -------------------------------------------------------------------------------- /src/demo/views/CodeViewer.vue: -------------------------------------------------------------------------------- 1 | 17 | 84 | 85 | -------------------------------------------------------------------------------- /src/demo/views/DashFive.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 155 | -------------------------------------------------------------------------------- /src/demo/views/DashFour.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 143 | -------------------------------------------------------------------------------- /src/demo/views/DashRidgeline.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 65 | -------------------------------------------------------------------------------- /src/demo/views/DashSix.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 81 | -------------------------------------------------------------------------------- /src/demo/views/DashThree.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 58 | -------------------------------------------------------------------------------- /src/demo/views/DygraphsDynamic.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 139 | -------------------------------------------------------------------------------- /src/demo/views/GeoMapboxUS.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 49 | -------------------------------------------------------------------------------- /src/demo/views/Home.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | -------------------------------------------------------------------------------- /src/demo/views/Perspective.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 56 | -------------------------------------------------------------------------------- /src/demo/views/Playground.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 72 | -------------------------------------------------------------------------------- /src/demo/views/ProgressDashboard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 136 | -------------------------------------------------------------------------------- /src/demo/views/SalesFunnelDashboard.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 154 | -------------------------------------------------------------------------------- /src/demo/views/SampleDashboard.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 127 | -------------------------------------------------------------------------------- /src/demo/views/SankeyDashboard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 149 | -------------------------------------------------------------------------------- /src/demo/views/SparkHeatMap.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 157 | -------------------------------------------------------------------------------- /src/demo/views/samples/DbDygraphsBarSamples.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 58 | 65 | -------------------------------------------------------------------------------- /src/demo/views/samples/DbHorizonSamples.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 70 | -------------------------------------------------------------------------------- /src/demo/views/samples/ProgressSamples.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 94 | -------------------------------------------------------------------------------- /src/index.esm.js: -------------------------------------------------------------------------------- 1 | import DbData from './components/dbdata'; 2 | import dbColors from './components/dbcolors'; 3 | import dbUtils from './components/dbutils'; 4 | 5 | export * from './components.js'; 6 | 7 | function installPlugin(Vue, opts) {} 8 | 9 | // DashBlocks Vue plugin 10 | const DashBlocks = { 11 | install(Vue, opts) { 12 | // Register specified components 13 | if (opts.components) { 14 | Object.keys(opts.components).forEach(key => { 15 | if (!(key in ['DashBlocks', 'DbData', 'dbColors', 'dbUtils'])) { 16 | const c = opts.components[key]; 17 | Vue.component(key, c); 18 | } 19 | }); 20 | } 21 | /* 22 | Vue.component('db-dygraphs-bundle', function(resolve) { 23 | // This special require syntax will instruct Webpack to 24 | // automatically split your built code into bundles which 25 | // are loaded over Ajax requests. 26 | require(['./dygraphs/DbDygraphsBar'], resolve); 27 | }); 28 | */ 29 | } 30 | }; 31 | 32 | export { DashBlocks, DbData, dbColors, dbUtils }; 33 | 34 | /* 35 | import DbColors from './components/dbcolors'; 36 | import DbUtils from './components/dbutils'; 37 | import DbData from './components/dbdata'; 38 | import DbDashboard from './components/dashboard/DbDashboard'; 39 | import DbHorizon from './components/d3/DbHorizon'; 40 | import DbSunburst from './components/d3/DbSunburst'; 41 | import DbSankey from './components/d3/DbSankey'; 42 | import DbRidgeline from './components/d3/DbRidgeline'; 43 | import { 44 | DbChartjsBar, 45 | DbChartjsHorizontalBar, 46 | DbChartjsDoughnut, 47 | DbChartjsLine, 48 | DbChartjsPie, 49 | DbChartjsPolarArea, 50 | DbChartjsRadar, 51 | DbChartjsBubble, 52 | DbChartjsScatter 53 | } from './components/chartjs/DbChartjs'; 54 | import DbNumber from './components/db/DbNumber'; 55 | import DbEasyPie from './components/db/DbEasyPie'; 56 | import DbTrendLine from './components/db/DbTrendLine'; 57 | import DbTrendBar from './components/db/DbTrendBar'; 58 | import DbSparkline from './components/db/DbSparkline'; 59 | import DbDygraphsBar from './components/dygraphs/DbDygraphsBar'; 60 | import DbDygraphsLine from './components/dygraphs/DbDygraphsLine'; 61 | import DbDygraphsSparkLine from './components/dygraphs/DbDygraphsSparkLine'; 62 | import DbDygraphsDateTimeHistogram from './components/dygraphs/DbDygraphsDateTimeHistogram'; 63 | 64 | export { 65 | DbColors, 66 | DbUtils, 67 | DbData, 68 | DbDashboard, 69 | DbHorizon, 70 | DbSunburst, 71 | DbSankey, 72 | DbRidgeline, 73 | DbChartjsBar, 74 | DbChartjsHorizontalBar, 75 | DbChartjsDoughnut, 76 | DbChartjsLine, 77 | DbChartjsPie, 78 | DbChartjsPolarArea, 79 | DbChartjsRadar, 80 | DbChartjsBubble, 81 | DbChartjsScatter, 82 | DbNumber, 83 | DbEasyPie, 84 | DbTrendLine, 85 | DbTrendBar, 86 | DbSparkline, 87 | DbDygraphsBar, 88 | DbDygraphsLine, 89 | DbDygraphsSparkLine, 90 | DbDygraphsDateTimeHistogram 91 | }; 92 | */ 93 | 94 | /* 95 | export default { 96 | DbColors, 97 | DbUtils, 98 | DbHorizon, 99 | DbSunburst, 100 | DbSankey, 101 | DbRidgeline, 102 | DbChartjsBar, 103 | DbChartjsHorizontalBar, 104 | DbChartjsDoughnut, 105 | DbChartjsLine, 106 | DbChartjsPie, 107 | DbChartjsPolarArea, 108 | DbChartjsRadar, 109 | DbChartjsBubble, 110 | DbChartjsScatter, 111 | DbNumber, 112 | DbEasyPie, 113 | DbTrendLine, 114 | DbTrendBar, 115 | DbSparkline, 116 | DbDygraphsBar, 117 | DbDygraphsLine, 118 | DbDygraphsSparkLine, 119 | DbDygraphsDateTimeHistogram 120 | }; 121 | */ 122 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | 6 | // Import all 7 | import { DashBlocks, dbColors } from 'dashblocks'; 8 | import * as dashblocksComponents from 'dashblocks'; 9 | 10 | Vue.use(DashBlocks, { 11 | components: dashblocksComponents 12 | }); 13 | 14 | // DashBlocks Showcase app css 15 | import './css.js'; 16 | import './quasar'; 17 | 18 | Vue.config.productionTip = false; 19 | 20 | // Set up Color Schemes for Dashblocks 21 | function setupColorSchemes() { 22 | dbColors.setColorScheme('barChartDiverging', { 23 | light: dbColors.d3ScaleChromatic.schemeSpectral[4], 24 | dark: dbColors.d3ScaleChromatic.schemeRdYlBu[6] 25 | }); 26 | } 27 | 28 | setupColorSchemes(); 29 | 30 | new Vue({ 31 | router, 32 | store, 33 | render: h => h(App) 34 | }).$mount('#app'); 35 | -------------------------------------------------------------------------------- /src/quasar.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | import './styles/quasar.scss'; 4 | import '@quasar/extras/roboto-font/roboto-font.css'; 5 | import '@quasar/extras/material-icons/material-icons.css'; 6 | //import '@quasar/extras/material-icons-outlined/material-icons-outlined.css'; 7 | //import '@quasar/extras/material-icons-round/material-icons-round.css'; 8 | //import '@quasar/extras/material-icons-sharp/material-icons-sharp.css'; 9 | //import '@quasar/extras/fontawesome-v5/fontawesome-v5.css'; 10 | //import '@quasar/extras/ionicons-v4/ionicons-v4.css'; 11 | 12 | import { 13 | Quasar, 14 | Ripple, 15 | LoadingBar, 16 | QLayout, 17 | QHeader, 18 | QDrawer, 19 | QPageContainer, 20 | QPage, 21 | QPageSticky, 22 | QToolbar, 23 | QToolbarTitle, 24 | QBtn, 25 | QIcon, 26 | QList, 27 | QItem, 28 | QItemSection, 29 | QItemLabel, 30 | QSplitter, 31 | QScrollArea, 32 | QExpansionItem, 33 | QAvatar, 34 | QBtnToggle, 35 | QSeparator, 36 | QTooltip, 37 | QTable, 38 | QCard, 39 | QCardSection, 40 | QSelect, 41 | QToggle, 42 | QBadge, 43 | QSpace 44 | } from 'quasar'; 45 | 46 | Vue.use(Quasar, { 47 | config: {}, 48 | components: { 49 | QLayout, 50 | QHeader, 51 | QDrawer, 52 | QPageContainer, 53 | QPage, 54 | QPageSticky, 55 | QToolbar, 56 | QToolbarTitle, 57 | QBtn, 58 | QIcon, 59 | QList, 60 | QItem, 61 | QItemSection, 62 | QItemLabel, 63 | QSplitter, 64 | QScrollArea, 65 | QExpansionItem, 66 | QAvatar, 67 | QBtnToggle, 68 | QSeparator, 69 | QTooltip, 70 | QTable, 71 | QCard, 72 | QCardSection, 73 | QSelect, 74 | QToggle, 75 | QBadge, 76 | QSpace 77 | }, 78 | directives: { 79 | Ripple 80 | }, 81 | plugins: { 82 | LoadingBar 83 | } 84 | }); 85 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | 4 | Vue.use(Vuex); 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | dark: (localStorage['db-dark-mode'] || 'false') === 'true', 9 | refreshTrigger: 0, 10 | refreshTimeout: 5000, 11 | refreshLast: 0, 12 | intervalId: null, 13 | rotateTrigger: 0, 14 | rotateLast: 0, 15 | rotateTimeout: 15000, 16 | dashboardSpec: '' 17 | }, 18 | mutations: { 19 | SET_DARK(state, { dark }) { 20 | localStorage['db-dark-mode'] = dark; 21 | state.dark = dark; 22 | }, 23 | SET_INTERVAL_ID(state, { id }) { 24 | state.intervalId = id; 25 | }, 26 | SET_REFRESH_TIMEOUT(state, { timeout }) { 27 | state.refreshTimeout = timeout; 28 | }, 29 | PERFORM_REFRESH(state) { 30 | state.refreshLast = Date.now(); 31 | state.refreshTrigger = state.refreshLast; 32 | }, 33 | PERFORM_ROTATE(state) { 34 | state.rotateLast = Date.now(); 35 | state.rotateTrigger = state.rotateLast; 36 | }, 37 | SET_DB_SPEC(state, { spec }) { 38 | state.dashboardSpec = spec; 39 | } 40 | }, 41 | actions: { 42 | setDark({ commit }, { dark }) { 43 | commit('SET_DARK', { dark: dark }); 44 | }, 45 | initRefresh({ commit, state }) { 46 | if (state.intervalId) { 47 | return; // Already set up 48 | } 49 | let intervalId = setInterval(() => { 50 | if (state.refreshTimeout === 0) { 51 | return; 52 | } 53 | let tsNow = Date.now(); 54 | let elapsed = tsNow - state.refreshLast; 55 | // If we're almost at refresh interval, refresh 56 | if (elapsed >= state.refreshTimeout - 100) { 57 | console.log(`Need to refresh: ${tsNow} - ${elapsed}`); 58 | commit('PERFORM_REFRESH'); 59 | } 60 | // If we're almost at rotate interval, rotate 61 | let rotateElapsed = tsNow - state.rotateLast; 62 | if (rotateElapsed >= state.rotateTimeout - 100) { 63 | console.log(`Need to rotate: ${tsNow} - ${rotateElapsed}`); 64 | commit('PERFORM_ROTATE'); 65 | } 66 | }, 1000); 67 | commit('SET_INTERVAL_ID', { id: intervalId }); 68 | }, 69 | setRefreshTimeout({ commit }, { timeout }) { 70 | commit('SET_REFRESH_TIMEOUT', { timeout: timeout }); 71 | }, 72 | performRefresh({ commit }) { 73 | commit('PERFORM_REFRESH'); 74 | }, 75 | setDashboardSpec({ commit }, { spec }) { 76 | commit('SET_DB_SPEC', { spec: spec }); 77 | } 78 | } 79 | }); 80 | -------------------------------------------------------------------------------- /src/styles/quasar.variables.scss: -------------------------------------------------------------------------------- 1 | // It's highly recommended to change the default colors 2 | // to match your app's branding. 3 | 4 | $primary : #027BE3; 5 | $secondary : #26A69A; 6 | $accent : #9C27B0; 7 | 8 | $dark : #1D1D1D; 9 | 10 | $positive : #21BA45; 11 | $negative : #C10015; 12 | $info : #31CCEC; 13 | $warning : #F2C037; 14 | 15 | @import '~quasar-variables-styl'; 16 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /src/webcomponents/dashboard.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 41 | -------------------------------------------------------------------------------- /src/webcomponents/dygraphs.vue: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /tests/e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ["cypress"], 3 | env: { 4 | mocha: true, 5 | "cypress/globals": true 6 | }, 7 | rules: { 8 | strict: "off" 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/guides/guides/plugins-guide.html 2 | 3 | module.exports = (on, config) => { 4 | return Object.assign({}, config, { 5 | fixturesFolder: "tests/e2e/fixtures", 6 | integrationFolder: "tests/e2e/specs", 7 | screenshotsFolder: "tests/e2e/screenshots", 8 | videosFolder: "tests/e2e/videos", 9 | supportFile: "tests/e2e/support/index.js" 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe("My First Test", () => { 4 | it("Visits the app root url", () => { 5 | cy.visit("/"); 6 | cy.contains("h1", "Welcome to Your Vue.js App"); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import "./commands"; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from "@vue/test-utils"; 2 | //import HelloWorld from "@/components/HelloDash.vue"; 3 | 4 | describe("HelloWorld.vue", () => { 5 | it("renders props.msg when passed", () => { 6 | const msg = "new message"; 7 | //const wrapper = shallowMount(HelloWorld, { 8 | // propsData: { msg } 9 | //}); 10 | //expect(wrapper.text()).toMatch(msg); 11 | expect(true).toBeTruthy(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/wc/db.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | db demo 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 |
14 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /tests/wc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | db demo 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | Dygraphs 14 | 15 | 16 |
17 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | const path = require('path'); 3 | const webpack = require('webpack'); 4 | const PerspectivePlugin = require('@finos/perspective-webpack-plugin'); 5 | 6 | // We will not include plotly.js-dist into lib bundle, to keep lib size reasonable. 7 | // plotly.js-dist is ~6M 8 | // App that uses dashblocks should have plotly.js-dist in it's dependencies 9 | // Also not including dygraphs as it must be loaded on demand 10 | // TODO Enable for Demo app build 11 | function getProdExternals() { 12 | return { 13 | 'plotly.js-dist': { 14 | commonjs: 'plotly.js-dist', 15 | commonjs2: 'plotly.js-dist' 16 | } 17 | /* 18 | dygraphs: { 19 | commonjs: 'dygraphs', 20 | commonjs2: 'dygraphs' 21 | } 22 | */ 23 | }; 24 | } 25 | 26 | module.exports = { 27 | publicPath: '/demo/', 28 | 29 | devServer: { 30 | proxy: 'http://localhost:3400' 31 | }, 32 | 33 | configureWebpack: { 34 | //externals: process.env.NODE_ENV === 'production' ? getProdExternals() : {}, 35 | plugins: [ 36 | // Ignore all locale files of moment.js 37 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), 38 | new PerspectivePlugin() 39 | ], 40 | resolve: { 41 | alias: { 42 | dashblocks: path.resolve(__dirname, 'src/index.esm.js') 43 | } 44 | }, 45 | module: { 46 | rules: [ 47 | { 48 | sideEffects: true 49 | } 50 | ] 51 | } 52 | }, 53 | 54 | pluginOptions: { 55 | quasar: { 56 | importStrategy: 'manual', 57 | treeShake: true 58 | } 59 | } 60 | 61 | //transpileDependencies: ['quasar'] 62 | }; 63 | --------------------------------------------------------------------------------