├── .gitignore
├── .gitmodules
├── Gruntfile.coffee
├── LICENSE
├── README.md
├── cairo.py
├── common
├── favicon.ico
├── homepage
│ └── Icon_Data.png
├── logo_header.png
└── settings.png
├── deployTools
└── install.py
├── docs
├── csv.md
├── oem.md
└── sample_onprem_nginx.txt
├── images
├── common
│ ├── favicon.ico
│ ├── homepage
│ │ └── Icon_Data.png
│ ├── logo_header.png
│ └── settings.png
└── main
│ ├── anim_loading_0.svg
│ ├── anim_loading_1.svg
│ ├── anim_loading_2.svg
│ ├── bg_arrow_left.svg
│ ├── broken_chart.svg
│ ├── csv.svg
│ ├── csv_gray.svg
│ ├── dashboard-preview.png
│ ├── drag.png
│ ├── google_analytics.svg
│ ├── google_analytics_gray.svg
│ ├── gridtile.svg
│ ├── icon_arrow_left.svg
│ ├── icon_arrow_right.svg
│ ├── icon_back_white.svg
│ ├── icon_chart_types.svg
│ ├── icon_chart_types_white.svg
│ ├── icon_close.png
│ ├── icon_close_black.svg
│ ├── icon_close_red.svg
│ ├── icon_delete.svg
│ ├── icon_delete_white.svg
│ ├── icon_edit.png
│ ├── icon_export_white.svg
│ ├── icon_minus.svg
│ ├── icon_plus.png
│ ├── icon_type_cat.svg
│ ├── icon_type_date.svg
│ ├── icon_type_green_cat.svg
│ ├── icon_type_green_date.svg
│ ├── icon_type_green_num.svg
│ ├── icon_type_num.svg
│ ├── icon_view.png
│ ├── infobright.svg
│ ├── infobright_gray.svg
│ ├── logo.svg
│ ├── mysql.svg
│ ├── mysql_gray.svg
│ ├── nux_arrow.svg
│ ├── nux_arrow2.svg
│ ├── nux_arrow_right.svg
│ ├── postgresql.svg
│ └── postgresql_gray.svg
├── lib
├── cookies.js
├── jquery-1.7.1.js
├── jquery-toast
│ ├── javascript
│ │ └── jquery.toastmessage.js
│ └── resources
│ │ ├── css
│ │ └── jquery.toastmessage.css
│ │ └── images
│ │ ├── close.gif
│ │ ├── error.png
│ │ ├── notice.png
│ │ ├── success.png
│ │ └── warning.png
├── jquery.caret.js
├── jquery.event.drag-2.0.js
├── jquery.simple-color.js
├── jqueryui
│ ├── jquery-ui-1.10.3.custom.min.js
│ ├── jquery.ui.polychart.less
│ └── jquery.ui.touch-punch.min.js
├── json2.js
├── knockout.js
├── moment.js
├── polychart2.js
├── polychart2.standalone.js
├── raphael.js
├── shjs
│ ├── sh_javascript.js
│ ├── sh_main.js
│ └── sh_style.css
├── slickgrid
│ ├── slick.core.js
│ ├── slick.grid.js
│ └── slick.grid.polychart.css
├── sourcesanspro
│ ├── LICENSE.txt
│ ├── OTF
│ │ ├── SourceSansPro-Black.otf
│ │ ├── SourceSansPro-BlackIt.otf
│ │ ├── SourceSansPro-Bold.otf
│ │ ├── SourceSansPro-BoldIt.otf
│ │ ├── SourceSansPro-ExtraLight.otf
│ │ ├── SourceSansPro-ExtraLightIt.otf
│ │ ├── SourceSansPro-It.otf
│ │ ├── SourceSansPro-Light.otf
│ │ ├── SourceSansPro-LightIt.otf
│ │ ├── SourceSansPro-Regular.otf
│ │ ├── SourceSansPro-Semibold.otf
│ │ └── SourceSansPro-SemiboldIt.otf
│ ├── ReadMe.html
│ ├── SourceSansProReadMe.html
│ └── TTF
│ │ ├── SourceSansPro-Black.ttf
│ │ ├── SourceSansPro-BlackIt.ttf
│ │ ├── SourceSansPro-Bold.ttf
│ │ ├── SourceSansPro-BoldIt.ttf
│ │ ├── SourceSansPro-ExtraLight.ttf
│ │ ├── SourceSansPro-ExtraLightIt.ttf
│ │ ├── SourceSansPro-It.ttf
│ │ ├── SourceSansPro-Light.ttf
│ │ ├── SourceSansPro-LightIt.ttf
│ │ ├── SourceSansPro-Regular.ttf
│ │ ├── SourceSansPro-Semibold.ttf
│ │ └── SourceSansPro-SemiboldIt.ttf
└── underscore.js
├── main
├── anim_loading_0.svg
├── anim_loading_1.svg
├── anim_loading_2.svg
├── bg_arrow_left.svg
├── broken_chart.svg
├── csv.svg
├── csv_gray.svg
├── dashboard-preview.png
├── drag.png
├── google_analytics.svg
├── google_analytics_gray.svg
├── gridtile.svg
├── icon_arrow_left.svg
├── icon_arrow_right.svg
├── icon_back_white.svg
├── icon_chart_types.svg
├── icon_chart_types_white.svg
├── icon_close.png
├── icon_close_black.svg
├── icon_close_red.svg
├── icon_delete.svg
├── icon_delete_white.svg
├── icon_edit.png
├── icon_export_white.svg
├── icon_minus.svg
├── icon_plus.png
├── icon_type_cat.svg
├── icon_type_date.svg
├── icon_type_green_cat.svg
├── icon_type_green_date.svg
├── icon_type_green_num.svg
├── icon_type_num.svg
├── icon_view.png
├── infobright.svg
├── infobright_gray.svg
├── logo.svg
├── mysql.svg
├── mysql_gray.svg
├── nux_arrow.svg
├── nux_arrow2.svg
├── nux_arrow_right.svg
├── postgresql.svg
└── postgresql_gray.svg
├── makeTools
├── parseTemplates.py
├── runServerTask.coffee
└── stitchTask.coffee
├── manage.py
├── package.json
├── packageData
├── README
├── dashstate.json
├── state.json
└── test.csv
├── packageExamples
├── README
├── chartbuilder_example.html
├── chartviewer_example.html
├── custom_backend_example.coffee
├── custom_backend_example.html
├── dashbuilder_example.html
└── tutorial.html
├── poly.coffee
├── poly
├── README.md
├── common
│ ├── bootstrapMixins.less
│ ├── events.coffee
│ ├── fonts.less
│ ├── goldilocks.css
│ ├── oldLayout.less
│ ├── oldMixins.less
│ ├── serverApi.coffee
│ └── toast.less
├── demoData
│ ├── content.js
│ ├── email.js
│ ├── sales.js
│ └── users.js
├── dsform.coffee
├── dsform.tmpl
├── home.coffee
├── home.less
├── main
│ ├── README.md
│ ├── anim.coffee
│ ├── bindings.coffee
│ ├── builder.coffee
│ ├── chart
│ │ ├── advanced.tmpl
│ │ ├── advancedPanel.coffee
│ │ ├── aes
│ │ │ ├── base.coffee
│ │ │ ├── base.tmpl
│ │ │ ├── color.coffee
│ │ │ ├── color.tmpl
│ │ │ ├── size.coffee
│ │ │ └── size.tmpl
│ │ ├── chart.less
│ │ ├── chartbuilder.coffee
│ │ ├── chartbuilder.tmpl
│ │ ├── filters.coffee
│ │ ├── filters.tmpl
│ │ ├── icon.less
│ │ ├── joins.coffee
│ │ ├── joins.less
│ │ ├── joins.tmpl
│ │ ├── layer.coffee
│ │ ├── layer.tmpl
│ │ └── selector.less
│ ├── const.coffee
│ ├── dash
│ │ ├── aes.coffee
│ │ ├── aes.tmpl
│ │ ├── dash.less
│ │ ├── dash.tmpl
│ │ ├── dashboard.coffee
│ │ ├── item
│ │ │ ├── base.coffee
│ │ │ ├── chart.coffee
│ │ │ ├── chart.tmpl
│ │ │ ├── comment.coffee
│ │ │ ├── comment.tmpl
│ │ │ ├── numeral.coffee
│ │ │ ├── numeral.tmpl
│ │ │ ├── pivottable.coffee
│ │ │ ├── pivottable.tmpl
│ │ │ ├── polyjs.coffee
│ │ │ ├── text.coffee
│ │ │ └── text.tmpl
│ │ ├── quickadd.coffee
│ │ ├── quickadd.tmpl
│ │ ├── workspace.coffee
│ │ └── workspace.tmpl
│ ├── data
│ │ ├── autocomplete.coffee
│ │ ├── columnInfo.coffee
│ │ ├── data.less
│ │ ├── data.tmpl
│ │ ├── dataSource.coffee
│ │ ├── dataView.coffee
│ │ ├── datatableView.coffee
│ │ ├── datatableView.tmpl
│ │ ├── metric
│ │ │ ├── attached.coffee
│ │ │ ├── attached.tmpl
│ │ │ ├── base.coffee
│ │ │ ├── base.tmpl
│ │ │ ├── dropdown.coffee
│ │ │ ├── dropdown.tmpl
│ │ │ ├── facet.coffee
│ │ │ ├── layer.coffee
│ │ │ ├── quickadd.coffee
│ │ │ └── quickaddtable.coffee
│ │ ├── table.tmpl
│ │ └── tableView.coffee
│ ├── dnd.coffee
│ ├── error
│ │ ├── toast.coffee
│ │ └── toast.less
│ ├── events.coffee
│ ├── header.coffee
│ ├── header.tmpl
│ ├── init.coffee
│ ├── main
│ │ ├── builder.coffee
│ │ ├── chartbuilder.coffee
│ │ ├── chartbuilder.tmpl
│ │ ├── chartviewer.coffee
│ │ ├── chartviewer.tmpl
│ │ ├── dashbuilder.coffee
│ │ ├── dashbuilder.tmpl
│ │ ├── dashviewer.coffee
│ │ ├── dashviewer.tmpl
│ │ ├── tutorial.coffee
│ │ └── viewer.coffee
│ ├── mixins.less
│ ├── numeral
│ │ ├── numeralbuilder.coffee
│ │ └── numeralbuilder.tmpl
│ ├── overlay.coffee
│ ├── overlay.tmpl
│ ├── parser.coffee
│ ├── polychart.less
│ ├── reset.less
│ ├── share.coffee
│ ├── share.tmpl
│ ├── table
│ │ ├── aesGroup.coffee
│ │ ├── aesGroup.tmpl
│ │ ├── table.less
│ │ ├── tablebuilder.coffee
│ │ └── tablebuilder.tmpl
│ ├── template.coffee
│ └── ui.less
├── nux.coffee
├── nux.tmpl
├── signup.coffee
└── verifyPendingDs.coffee
├── polychart
├── README.md
├── __init__.py
├── config
│ ├── README.md
│ ├── __init__.py
│ ├── deploy.py
│ ├── local.py
│ ├── localOverrides.py
│ └── shared.py
├── main
│ ├── README.md
│ ├── __init__.py
│ ├── management
│ │ ├── __init__.py
│ │ └── commands
│ │ │ ├── __init__.py
│ │ │ └── createuser.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto__add_field_userinfo_global_unique_id.py
│ │ ├── 0003_auto__add_localdatasource__add_field_pendingdatasource_user__chg_field.py
│ │ ├── 0004_auto__del_event.py
│ │ ├── 0005_normalize_spec.py
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ ├── __init__.py
│ │ ├── base.tmpl
│ │ ├── callback.tmpl
│ │ ├── dashEdit.tmpl
│ │ ├── dashView.tmpl
│ │ ├── demo.tmpl
│ │ ├── forgotPassword.tmpl
│ │ ├── home.tmpl
│ │ ├── login.tmpl
│ │ ├── logout.tmpl
│ │ ├── oldBase.tmpl
│ │ ├── resetPassword.tmpl
│ │ ├── settings.tmpl
│ │ ├── signup.tmpl
│ │ └── verifyPendingDataSource.tmpl
│ ├── urls.py
│ ├── utils
│ │ ├── __init__.py
│ │ ├── colours.py
│ │ ├── csvParser.py
│ │ ├── email.py
│ │ ├── emailConsole.py
│ │ ├── postageapp.py
│ │ ├── secureStorage.py
│ │ ├── spec.py
│ │ ├── svg.py
│ │ ├── tools.py
│ │ └── validate.py
│ └── views
│ │ ├── __init__.py
│ │ ├── account.py
│ │ ├── dashboard.py
│ │ ├── dataSource.py
│ │ ├── demo.py
│ │ ├── export.py
│ │ ├── home.py
│ │ ├── ssh.py
│ │ ├── tutorial.py
│ │ ├── upload.py
│ │ └── user.py
├── urls.py
├── utils.py
└── wsgi.py
├── polychartQuery
├── README.md
├── __init__.py
├── abstract.py
├── connections.py
├── csv
│ ├── __init__.py
│ └── connection.py
├── expr.py
├── googleAnalytics
│ ├── README.md
│ ├── __init__.py
│ ├── connection.py
│ ├── expr.py
│ ├── params.py
│ └── query.py
├── httpService.py
├── oauth.md
├── oauth.py
├── query.py
├── sql
│ ├── __init__.py
│ ├── connection.py
│ ├── expr.py
│ └── query.py
├── utils.py
└── validate.py
├── requirements
├── server
├── README
├── cairo.py
├── polychart
│ ├── README.md
│ ├── __init__.py
│ ├── config
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── deploy.py
│ │ ├── local.py
│ │ └── shared.py
│ ├── main
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── management
│ │ │ ├── __init__.py
│ │ │ └── commands
│ │ │ │ ├── __init__.py
│ │ │ │ └── createuser.py
│ │ ├── migrations
│ │ │ ├── 0001_initial.py
│ │ │ ├── 0002_auto__add_field_userinfo_global_unique_id.py
│ │ │ ├── 0003_auto__add_localdatasource__add_field_pendingdatasource_user__chg_field.py
│ │ │ ├── 0004_auto__del_event.py
│ │ │ ├── 0005_normalize_spec.py
│ │ │ └── __init__.py
│ │ ├── models.py
│ │ ├── templates
│ │ │ ├── __init__.py
│ │ │ ├── base.tmpl
│ │ │ ├── callback.tmpl
│ │ │ ├── dashEdit.tmpl
│ │ │ ├── dashView.tmpl
│ │ │ ├── demo.tmpl
│ │ │ ├── forgotPassword.tmpl
│ │ │ ├── home.tmpl
│ │ │ ├── login.tmpl
│ │ │ ├── logout.tmpl
│ │ │ ├── oldBase.tmpl
│ │ │ ├── resetPassword.tmpl
│ │ │ ├── settings.tmpl
│ │ │ ├── signup.tmpl
│ │ │ └── verifyPendingDataSource.tmpl
│ │ ├── urls.py
│ │ ├── utils
│ │ │ ├── __init__.py
│ │ │ ├── colours.py
│ │ │ ├── csvParser.py
│ │ │ ├── email.py
│ │ │ ├── emailConsole.py
│ │ │ ├── postageapp.py
│ │ │ ├── secureStorage.py
│ │ │ ├── spec.py
│ │ │ ├── svg.py
│ │ │ ├── tools.py
│ │ │ └── validate.py
│ │ └── views
│ │ │ ├── __init__.py
│ │ │ ├── account.py
│ │ │ ├── dashboard.py
│ │ │ ├── dataSource.py
│ │ │ ├── demo.py
│ │ │ ├── export.py
│ │ │ ├── home.py
│ │ │ ├── ssh.py
│ │ │ ├── tutorial.py
│ │ │ ├── upload.py
│ │ │ └── user.py
│ ├── urls.py
│ ├── utils.py
│ └── wsgi.py
└── polychartQuery
│ ├── README.md
│ ├── __init__.py
│ ├── abstract.py
│ ├── connections.py
│ ├── csv
│ ├── __init__.py
│ └── connection.py
│ ├── expr.py
│ ├── googleAnalytics
│ ├── README.md
│ ├── __init__.py
│ ├── connection.py
│ ├── expr.py
│ ├── params.py
│ └── query.py
│ ├── httpService.py
│ ├── oauth.md
│ ├── oauth.py
│ ├── query.py
│ ├── sql
│ ├── __init__.py
│ ├── connection.py
│ ├── expr.py
│ └── query.py
│ ├── utils.py
│ └── validate.py
├── src
├── README.md
├── poly.coffee
└── poly
│ ├── README.md
│ ├── common
│ ├── bootstrapMixins.less
│ ├── events.coffee
│ ├── fonts.less
│ ├── goldilocks.css
│ ├── oldLayout.less
│ ├── oldMixins.less
│ ├── serverApi.coffee
│ └── toast.less
│ ├── demoData
│ ├── content.js
│ ├── email.js
│ ├── sales.js
│ └── users.js
│ ├── dsform.coffee
│ ├── dsform.tmpl
│ ├── home.coffee
│ ├── home.less
│ ├── main
│ ├── README.md
│ ├── anim.coffee
│ ├── bindings.coffee
│ ├── builder.coffee
│ ├── chart
│ │ ├── advanced.tmpl
│ │ ├── advancedPanel.coffee
│ │ ├── aes
│ │ │ ├── base.coffee
│ │ │ ├── base.tmpl
│ │ │ ├── color.coffee
│ │ │ ├── color.tmpl
│ │ │ ├── size.coffee
│ │ │ └── size.tmpl
│ │ ├── chart.less
│ │ ├── chartbuilder.coffee
│ │ ├── chartbuilder.tmpl
│ │ ├── filters.coffee
│ │ ├── filters.tmpl
│ │ ├── icon.less
│ │ ├── joins.coffee
│ │ ├── joins.less
│ │ ├── joins.tmpl
│ │ ├── layer.coffee
│ │ ├── layer.tmpl
│ │ └── selector.less
│ ├── const.coffee
│ ├── dash
│ │ ├── aes.coffee
│ │ ├── aes.tmpl
│ │ ├── dash.less
│ │ ├── dash.tmpl
│ │ ├── dashboard.coffee
│ │ ├── item
│ │ │ ├── base.coffee
│ │ │ ├── chart.coffee
│ │ │ ├── chart.tmpl
│ │ │ ├── comment.coffee
│ │ │ ├── comment.tmpl
│ │ │ ├── numeral.coffee
│ │ │ ├── numeral.tmpl
│ │ │ ├── pivottable.coffee
│ │ │ ├── pivottable.tmpl
│ │ │ ├── polyjs.coffee
│ │ │ ├── text.coffee
│ │ │ └── text.tmpl
│ │ ├── quickadd.coffee
│ │ ├── quickadd.tmpl
│ │ ├── workspace.coffee
│ │ └── workspace.tmpl
│ ├── data
│ │ ├── autocomplete.coffee
│ │ ├── columnInfo.coffee
│ │ ├── data.less
│ │ ├── data.tmpl
│ │ ├── dataSource.coffee
│ │ ├── dataView.coffee
│ │ ├── datatableView.coffee
│ │ ├── datatableView.tmpl
│ │ ├── metric
│ │ │ ├── attached.coffee
│ │ │ ├── attached.tmpl
│ │ │ ├── base.coffee
│ │ │ ├── base.tmpl
│ │ │ ├── dropdown.coffee
│ │ │ ├── dropdown.tmpl
│ │ │ ├── facet.coffee
│ │ │ ├── layer.coffee
│ │ │ ├── quickadd.coffee
│ │ │ └── quickaddtable.coffee
│ │ ├── table.tmpl
│ │ └── tableView.coffee
│ ├── dnd.coffee
│ ├── error
│ │ ├── toast.coffee
│ │ └── toast.less
│ ├── events.coffee
│ ├── header.coffee
│ ├── header.tmpl
│ ├── init.coffee
│ ├── main
│ │ ├── builder.coffee
│ │ ├── chartbuilder.coffee
│ │ ├── chartbuilder.tmpl
│ │ ├── chartviewer.coffee
│ │ ├── chartviewer.tmpl
│ │ ├── dashbuilder.coffee
│ │ ├── dashbuilder.tmpl
│ │ ├── dashviewer.coffee
│ │ ├── dashviewer.tmpl
│ │ ├── tutorial.coffee
│ │ └── viewer.coffee
│ ├── mixins.less
│ ├── numeral
│ │ ├── numeralbuilder.coffee
│ │ └── numeralbuilder.tmpl
│ ├── overlay.coffee
│ ├── overlay.tmpl
│ ├── parser.coffee
│ ├── polychart.less
│ ├── reset.less
│ ├── share.coffee
│ ├── share.tmpl
│ ├── table
│ │ ├── aesGroup.coffee
│ │ ├── aesGroup.tmpl
│ │ ├── table.less
│ │ ├── tablebuilder.coffee
│ │ └── tablebuilder.tmpl
│ ├── template.coffee
│ └── ui.less
│ ├── nux.coffee
│ ├── nux.tmpl
│ ├── signup.coffee
│ └── verifyPendingDs.coffee
└── system_requirements
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.sublime-project
3 | *.sublime-workspace
4 | *.swo
5 | *.swp
6 |
7 | /*.db
8 | /compiledStatic
9 | /lib/jqueryui/jquery.ui.polychart.css
10 | /log/*
11 | /node_modules/*
12 | /onprem
13 | /polychart-onprem-*.zip
14 | /polychartPackaged
15 | /server/polychart/config/deployOverrides.py
16 | /server/polychart/config/localOverrides.py
17 | /server/polychart/config/overrides.py
18 | /tmp
19 | /uploadedData
20 |
21 | # Deployment
22 | /allStatic
23 | /gunicorn.conf
24 | /server/polychart/config/deployParams.py
25 | /virtualenv/*
26 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/polychart2"]
2 | path = lib/polychart2
3 | url = git@github.com:Polychart/polychart2.git
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Polychart Dashboard Builder
2 | ===========================
3 |
4 | Setting up a dev environment
5 | ----------------------------
6 |
7 | Be sure to retrieve the repository's submodules:
8 | - `git submodule update --init --recursive`
9 |
10 | It is recommended that a recent version of Node.js be installed:
11 | - `sudo apt-get install python-software-properties`
12 | - `sudo apt-add-repository ppa:chris-lea/node.js`
13 | - `sudo apt-get update`
14 | - `sudo apt-get install nodejs` (this include `npm`)
15 |
16 | To see a list of dependencies, search for "package" in the
17 | [Chef recipe](https://github.com/Polychart/deployment/blob/master/cookbooks/polychart/recipes/default.rb).
18 |
19 | Install Python dependencies:
20 | - `sudo apt-get install python-setuptools python-virtualenv python2.7-dev`
21 | - `sudo pip install -U virtualenv`
22 | - `sudo pip install -r requirements`.
23 |
24 | Install Node.js dependencies:
25 | - `npm install` (in the repo directory)
26 | - `sudo npm install -g grunt-cli`
27 |
28 | Finally, run `grunt`.
29 |
30 |
--------------------------------------------------------------------------------
/cairo.py:
--------------------------------------------------------------------------------
1 | from cairocffi import *
2 |
--------------------------------------------------------------------------------
/common/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/common/favicon.ico
--------------------------------------------------------------------------------
/common/homepage/Icon_Data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/common/homepage/Icon_Data.png
--------------------------------------------------------------------------------
/common/logo_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/common/logo_header.png
--------------------------------------------------------------------------------
/common/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/common/settings.png
--------------------------------------------------------------------------------
/docs/sample_onprem_nginx.txt:
--------------------------------------------------------------------------------
1 | # Sample nginx config for use with onprem.
2 | # To be used in documentation that is coming soon!
3 |
4 | server {
5 | listen 80;
6 | server_name localhost;
7 |
8 | location / {
9 | proxy_pass http://localhost:7000;
10 | proxy_set_header Host $http_host;
11 | proxy_redirect http:// https://;
12 | }
13 |
14 | location /static {
15 | alias /polychart-onprem/static;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/images/common/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/common/favicon.ico
--------------------------------------------------------------------------------
/images/common/homepage/Icon_Data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/common/homepage/Icon_Data.png
--------------------------------------------------------------------------------
/images/common/logo_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/common/logo_header.png
--------------------------------------------------------------------------------
/images/common/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/common/settings.png
--------------------------------------------------------------------------------
/images/main/bg_arrow_left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/main/dashboard-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/dashboard-preview.png
--------------------------------------------------------------------------------
/images/main/drag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/drag.png
--------------------------------------------------------------------------------
/images/main/icon_arrow_left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/main/icon_arrow_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/main/icon_back_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
--------------------------------------------------------------------------------
/images/main/icon_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/icon_close.png
--------------------------------------------------------------------------------
/images/main/icon_delete.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
--------------------------------------------------------------------------------
/images/main/icon_delete_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/images/main/icon_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/icon_edit.png
--------------------------------------------------------------------------------
/images/main/icon_export_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/images/main/icon_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/icon_plus.png
--------------------------------------------------------------------------------
/images/main/icon_type_cat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/images/main/icon_type_date.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/images/main/icon_type_green_cat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/images/main/icon_type_green_date.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/images/main/icon_type_green_num.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/images/main/icon_type_num.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/images/main/icon_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/images/main/icon_view.png
--------------------------------------------------------------------------------
/images/main/nux_arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/main/nux_arrow2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/images/main/nux_arrow_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/lib/cookies.js:
--------------------------------------------------------------------------------
1 | // Adapted from http://www.quirksmode.org/js/cookies.html
2 | var Cookies = {
3 | create: function (name,value,days) {
4 | if (days) {
5 | var date = new Date();
6 | date.setTime(date.getTime()+(days*24*60*60*1000));
7 | var expires = "; expires="+date.toGMTString();
8 | }
9 | else var expires = "";
10 | document.cookie = name+"="+value+expires+"; path=/";
11 | },
12 | read: function (name) {
13 | var nameEQ = name + "=";
14 | var ca = document.cookie.split(';');
15 | for(var i=0;i < ca.length;i++) {
16 | var c = ca[i];
17 | while (c.charAt(0)==' ') c = c.substring(1,c.length);
18 | if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
19 | }
20 | return null;
21 | },
22 | erase: function (name) {
23 | createCookie(name,"",-1);
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/lib/jquery-toast/resources/images/close.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/jquery-toast/resources/images/close.gif
--------------------------------------------------------------------------------
/lib/jquery-toast/resources/images/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/jquery-toast/resources/images/error.png
--------------------------------------------------------------------------------
/lib/jquery-toast/resources/images/notice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/jquery-toast/resources/images/notice.png
--------------------------------------------------------------------------------
/lib/jquery-toast/resources/images/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/jquery-toast/resources/images/success.png
--------------------------------------------------------------------------------
/lib/jquery-toast/resources/images/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/jquery-toast/resources/images/warning.png
--------------------------------------------------------------------------------
/lib/jqueryui/jquery.ui.touch-punch.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery UI Touch Punch 0.2.2
3 | *
4 | * Copyright 2011, Dave Furfero
5 | * Dual licensed under the MIT or GPL Version 2 licenses.
6 | *
7 | * Depends:
8 | * jquery.ui.widget.js
9 | * jquery.ui.mouse.js
10 | */
11 | (function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return;}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return;}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f);}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return;}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown");};c._touchMove=function(f){if(!a){return;}this._touchMoved=true;d(f,"mousemove");};c._touchEnd=function(f){if(!a){return;}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click");}a=false;};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f);};})(jQuery);
--------------------------------------------------------------------------------
/lib/polychart2.js:
--------------------------------------------------------------------------------
1 | polychart2/polychart2.js
--------------------------------------------------------------------------------
/lib/polychart2.standalone.js:
--------------------------------------------------------------------------------
1 | polychart2/polychart2.standalone.js
--------------------------------------------------------------------------------
/lib/raphael.js:
--------------------------------------------------------------------------------
1 | polychart2/lib/raphael.js
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-Black.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-BlackIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-BlackIt.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-Bold.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-BoldIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-BoldIt.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-ExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-ExtraLight.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-ExtraLightIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-ExtraLightIt.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-It.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-It.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-Light.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-LightIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-LightIt.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-Regular.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-Semibold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-Semibold.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/OTF/SourceSansPro-SemiboldIt.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/OTF/SourceSansPro-SemiboldIt.otf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-Black.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-BlackIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-BlackIt.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-Bold.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-BoldIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-BoldIt.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-ExtraLight.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-ExtraLightIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-ExtraLightIt.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-It.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-It.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-Light.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-LightIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-LightIt.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-Regular.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-Semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-Semibold.ttf
--------------------------------------------------------------------------------
/lib/sourcesanspro/TTF/SourceSansPro-SemiboldIt.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/lib/sourcesanspro/TTF/SourceSansPro-SemiboldIt.ttf
--------------------------------------------------------------------------------
/main/bg_arrow_left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/main/dashboard-preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/dashboard-preview.png
--------------------------------------------------------------------------------
/main/drag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/drag.png
--------------------------------------------------------------------------------
/main/icon_arrow_left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/main/icon_arrow_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/main/icon_back_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
--------------------------------------------------------------------------------
/main/icon_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/icon_close.png
--------------------------------------------------------------------------------
/main/icon_delete.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
--------------------------------------------------------------------------------
/main/icon_delete_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/main/icon_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/icon_edit.png
--------------------------------------------------------------------------------
/main/icon_export_white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/main/icon_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/icon_plus.png
--------------------------------------------------------------------------------
/main/icon_type_cat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/main/icon_type_date.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/main/icon_type_green_cat.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
--------------------------------------------------------------------------------
/main/icon_type_green_date.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/main/icon_type_green_num.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/main/icon_type_num.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/main/icon_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/main/icon_view.png
--------------------------------------------------------------------------------
/main/nux_arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/main/nux_arrow2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/main/nux_arrow_right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/makeTools/runServerTask.coffee:
--------------------------------------------------------------------------------
1 | {spawn, exec} = require('child_process')
2 |
3 | module.exports.register = (grunt) ->
4 | grunt.registerTask 'runServer', "Run local Django development server.", () ->
5 | done = @async()
6 | exec "./manage.py syncdb --migrate -v 0", (err) ->
7 | if err?
8 | done(false)
9 | console.log err
10 | throw err
11 | server = spawn("./manage.py", ["runserver", "--nothreading"])
12 | done(true)
13 |
14 | server.stdout.on 'data', (data) ->
15 | grunt.log.writeln data
16 | server.stderr.on 'data', (data) ->
17 | grunt.log.writeln "[Log]: #{data}"
18 | server.on 'close', (code) ->
19 | grunt.log.writeln "Server exited with code #{code}."
20 |
--------------------------------------------------------------------------------
/makeTools/stitchTask.coffee:
--------------------------------------------------------------------------------
1 | fs = require 'fs'
2 | path = require 'path'
3 | stitch = require 'stitch'
4 |
5 | # Creates a directory and all missing parent directories
6 | createDirectory = (dirPath) ->
7 | if fs.statSync(path.dirname(dirPath)).isDirectory()
8 | return
9 |
10 | parentDirPath = path.dirname path
11 | if parentDirPath isnt dirPath
12 | createDirectory parentDirPath
13 |
14 | fs.mkdirSync dirPath
15 |
16 | module.exports.register = (grunt) ->
17 | grunt.registerMultiTask 'stitch', "Build and stitch files together", () ->
18 | done = @async()
19 |
20 | config = @files[0]
21 | pkg = stitch.createPackage(paths: ["#{grunt.config('tmpDir')}#{@target}_pkg"])
22 | pkg.compile (err, src) ->
23 | if err
24 | done(false)
25 | console.log err
26 | throw err
27 |
28 | try
29 | createDirectory path.dirname config.dest
30 | fs.writeFile config.dest, src, (err) ->
31 | if err? then throw err
32 | done(true)
33 | catch err
34 | console.error err
35 | done(false)
36 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Convenient wrapper around django-admin.py.
5 |
6 | Example usage: ./manage.py syncdb
7 | """
8 |
9 | import errno
10 | import os
11 | import sys
12 | from traceback import print_exc
13 |
14 | def _mkdir(path):
15 | try:
16 | os.makedirs(path)
17 | except OSError as err:
18 | # If already exists as directory
19 | if err.errno == errno.EEXIST and os.path.isdir(path):
20 | return
21 |
22 | raise
23 |
24 | if __name__ == "__main__":
25 | # Create directory required by logger
26 | _mkdir('log/app')
27 |
28 | # Set up environment properly
29 | sys.path = ['server'] + sys.path
30 |
31 | # Detect deployment vs local
32 | if os.path.isfile('server/polychart/config/deployParams.py'):
33 | os.environ["DJANGO_SETTINGS_MODULE"] = "polychart.config.deploy"
34 | else:
35 | os.environ["DJANGO_SETTINGS_MODULE"] = "polychart.config.local"
36 |
37 | # Attempt to import Django
38 | try:
39 | from django.core.management import execute_from_command_line
40 | except ImportError:
41 | print_exc()
42 | print
43 | print 'Try rerunning this command like this:'
44 | print ' virtualenv/bin/python2 manage.py'
45 | sys.exit(1)
46 |
47 | # Pass command-line args to Django
48 | execute_from_command_line(sys.argv)
49 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "polychart-dashboardbuilder",
3 | "version": "1.0.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "https://github.com/Polychart/dbb.git"
7 | },
8 | "dependencies": {
9 | "faye-websocket": ">= 0.6.1",
10 | "jsdom": ">= 0.8.1",
11 | "underscore": ">= 1.5.1"
12 | },
13 | "devDependencies": {
14 | "coffee-script": "~1.6.3",
15 | "grunt": "~0.4.1",
16 | "grunt-cli": "~0.1.9",
17 | "grunt-contrib-less": "~0.7.0",
18 | "grunt-contrib-copy": "~0.4.1",
19 | "grunt-contrib-watch": "~0.5.1",
20 | "grunt-contrib-concat": "~0.3.0",
21 | "grunt-contrib-clean": "~0.5.0",
22 | "stitch": "~0.3.3",
23 | "grunt-contrib-uglify": "~0.2.2",
24 | "grunt-contrib-cssmin": "~0.6.1",
25 | "grunt-text-replace": "~0.3.7"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/packageData/README:
--------------------------------------------------------------------------------
1 | Example data for use by frontend only examples.
2 |
--------------------------------------------------------------------------------
/packageData/state.json:
--------------------------------------------------------------------------------
1 | {"layers":[{"additionalInfo":{"joins":{"tables":["TEST"],"joins":[]}},"type":"bar","filter":{},"x":{"var":"[TEST.Category]","name":"Category","tableName":"TEST","bin":null,"stats":"None"},"meta":{"[TEST.Category]":{"type":"cat","tableName":"TEST"},"sum([TEST.Number\\[%\\]])":{"type":"num","tableName":"TEST"},"bin([TEST.Another Number long name very long!\\]\\[_+~],1)":{"type":"num","tableName":"TEST"}},"y":{"var":"sum([TEST.Number\\[%\\]])","name":"Number[%]","tableName":"TEST","bin":1,"stats":"Sum"},"color":{"var":"bin([TEST.Another Number long name very long!\\]\\[_+~],1)","name":"Another Number long name very long!][_+~","tableName":"TEST","bin":1,"stats":"None"}}],"coord":{"flip":false,"type":"cartesian"},"guides":{"x":{},"y":{}},"facet":{},"width":731,"height":535}
2 |
--------------------------------------------------------------------------------
/packageData/test.csv:
--------------------------------------------------------------------------------
1 | Category,Number[%],Another Number long name very long!][_+~
2 | A,2,3
3 | B,3,4
4 | C,1,5
5 | D,1,2
6 |
--------------------------------------------------------------------------------
/packageExamples/README:
--------------------------------------------------------------------------------
1 | This folder contain examples for frontend-only uses of Polychart.
2 |
3 |
--------------------------------------------------------------------------------
/packageExamples/custom_backend_example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ")
20 | div.addClass("anim")
21 | div.addClass(animName)
22 | $(container).append(div)
23 |
24 | _.defer () ->
25 | div.css
26 | width: div.height()
27 | marginLeft: -div.height()/2
28 | marginTop: -div.height()/2
29 |
30 | images = _.map anim.frames, (src) =>
31 | img = new Image()
32 | img.src = '/static/main/images/' + src
33 | img
34 |
35 | curFrame = 0
36 | advFrame = () ->
37 | div.css 'background-image', 'url(' + images[curFrame].src + ')'
38 | curFrame = (curFrame + 1) % images.length
39 | @interval = setInterval advFrame, anim.interval
40 |
41 | remove: () =>
42 | @div.remove()
43 | clearInterval @interval
44 |
45 | stopOnImage: (imgSrc) =>
46 | @div.css 'background-image', 'url(' + imgSrc + ')'
47 | clearInterval @interval
48 |
49 | module.exports = Animation
50 |
--------------------------------------------------------------------------------
/poly/main/chart/advanced.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
9 |
27 |
28 |
37 |
--------------------------------------------------------------------------------
/poly/main/chart/aes/base.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
22 |
--------------------------------------------------------------------------------
/poly/main/chart/aes/color.coffee:
--------------------------------------------------------------------------------
1 | Aesthetic = require('poly/main/chart/aes/base')
2 |
3 | class ColorAesthetic extends Aesthetic
4 | template: 'tmpl-aesthetic-color'
5 | constructor: (@aes, @name, @parent) ->
6 | super(@aes, @name, @parent)
7 | @selected = 'steelblue'
8 | @defaultValue = 'steelblue'
9 | @value = ko.observable(@defaultValue)
10 | @value.subscribe @render
11 | onMetricDiscard: (event, metricItem) =>
12 | @metric(null)
13 | @render()
14 | @afterRender(@dom)
15 | afterRender: (dom) =>
16 | @dom = dom
17 | simpleColor = $('.selector', dom)
18 | simpleColor.attr 'value', @value()
19 | simpleColor.simpleColor(
20 | cellWidth: 15
21 | cellHeight: 15
22 | boxWidth: 50
23 | boxHeight: 15
24 | border: 0
25 | columns: 9
26 | )
27 | simpleColor.bind 'change', (evt) =>
28 | @value evt.target.value
29 | $(".simpleColorContainer", dom).click () => false
30 | _setConstant: (spec) =>
31 | if spec.const
32 | @value(spec.const)
33 | _getConstant: () =>
34 | const: @value()
35 |
36 | module.exports = ColorAesthetic
37 |
--------------------------------------------------------------------------------
/poly/main/chart/aes/color.tmpl:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/poly/main/chart/aes/size.coffee:
--------------------------------------------------------------------------------
1 | Aesthetic = require('poly/main/chart/aes/base')
2 |
3 | class SizeAesthetic extends Aesthetic
4 | template: 'tmpl-aesthetic-size'
5 | constructor: (@aes, @name, @parent) ->
6 | super(@aes, @name, @parent)
7 | @selected = 1
8 | @defaultValue = 2
9 | @value = ko.observable(@defaultValue)
10 | @value.subscribe @render
11 | onMetricDiscard: (event, metricItem) =>
12 | @metric(null)
13 | @render()
14 | @afterRender(@dom)
15 | afterRender: (dom) =>
16 | @dom = dom
17 | slider = $('.selector', dom)
18 | slider.slider(
19 | max: 10
20 | min: 1
21 | step: 1
22 | value: @value()
23 | )
24 | slider.bind 'slidechange', (evt, ui) =>
25 | @value(ui.value)
26 | _setConstant: (spec) =>
27 | if spec.const
28 | @value(spec.const)
29 | _getConstant: () =>
30 | const: @value()
31 |
32 | module.exports = SizeAesthetic
33 |
--------------------------------------------------------------------------------
/poly/main/chart/aes/size.tmpl:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/poly/main/chart/chartbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
39 |
40 |
43 |
--------------------------------------------------------------------------------
/poly/main/chart/layer.tmpl:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/poly/main/dash/aes.tmpl:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/poly/main/dash/dash.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/poly/main/dash/dashboard.coffee:
--------------------------------------------------------------------------------
1 | QuickAddView = require('poly/main/dash/quickadd')
2 | WorkspaceView = require('poly/main/dash/workspace')
3 |
4 | class DashboardView
5 | constructor: (title, tableMetaData) ->
6 | @workspaceView = new WorkspaceView(title, tableMetaData)
7 | @quickaddView = new QuickAddView(tableMetaData)
8 |
9 | serialize: () =>
10 | @workspaceView.serialize()
11 |
12 | initialize: (initial) => @workspaceView.initialize(initial)
13 |
14 | module.exports = DashboardView
15 |
--------------------------------------------------------------------------------
/poly/main/dash/item/chart.tmpl:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/poly/main/dash/item/comment.coffee:
--------------------------------------------------------------------------------
1 | TextItem = require('poly/main/dash/item/text')
2 |
3 | CONST = require('poly/main/const')
4 |
5 | class CommentItem extends TextItem
6 | constructor: (@author, value, position={}) ->
7 | @author or= PAGE_VARIABLE?.USERNAME ? ''
8 | position.width or= 5
9 | position.height or= 7
10 |
11 | @minWidth = 5
12 | @minHeight = 5
13 |
14 | @templateName = 'tmpl-comment-item' unless @templateName
15 | super(value, position, 'Write a comment here...')
16 |
17 | @shiftedZIndex = ko.computed =>
18 | 1000000 + @zIndex()
19 |
20 | serialize: (s={}) =>
21 | s.author = @author
22 | s.itemType = "CommentItem"
23 | super s
24 |
25 | deserialize: (s) =>
26 | @author = s.author if s.author
27 | super(s)
28 |
29 | module.exports = CommentItem
30 |
--------------------------------------------------------------------------------
/poly/main/dash/item/comment.tmpl:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/poly/main/dash/item/numeral.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/poly/main/dash/item/pivottable.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/poly/main/dash/item/polyjs.coffee:
--------------------------------------------------------------------------------
1 | Animation = require('poly/main/anim')
2 | DashItem = require('poly/main/dash/item/base')
3 | Events = require('poly/main/events')
4 |
5 | CONST = require('poly/main/const')
6 | TOAST = require('poly/main/error/toast')
7 |
8 | PADDING = 10 # extra padding for chart view outside of chart
9 |
10 | class PolyJSItem extends DashItem
11 | constructor: (@spec=null, position) ->
12 | @redraw = _.debounce(@_redraw, 300, true)
13 | @templateName = 'tmpl-chart-item' unless @templateName
14 | super(position)
15 |
16 | init: (dom) =>
17 | super(dom)
18 | @itemdom = $('.chart-inner, .inner', dom)
19 | @spec.dom = @itemdom[0]
20 | @_initSpec()
21 | Events.error.polyjs.data.on (event) =>
22 | @loadingAnim.stopOnImage("/static/main/images/broken_chart.svg")
23 | @onResize()
24 |
25 | _initSpec: () => Error("Not implemented")
26 |
27 | onResize: =>
28 | if @itemdom then @redraw()
29 |
30 | _redraw: () =>
31 | if !@itemdom
32 | # init() has to be called first so that @spec has a DOM element
33 | throw "Can't make chart before init() is called!"
34 |
35 | @spec.width = @itemdom.width() - PADDING
36 | @spec.height = @itemdom.height() - PADDING
37 | prepare =
38 | if @isViewer()
39 | ->
40 | else
41 | () => @itemdom.empty()
42 | @_renderPolyJSItem(@spec, @loaded, prepare)
43 |
44 | setSpec: (@spec, isDeserializing=false) =>
45 | unless isDeserializing
46 | Events.model.dashboarditem.update.trigger()
47 |
48 | deserialize: (s) =>
49 | @setSpec(s.spec, true)
50 | super(s)
51 |
52 | module.exports = PolyJSItem
53 |
--------------------------------------------------------------------------------
/poly/main/dash/item/text.coffee:
--------------------------------------------------------------------------------
1 | DashItem = require('poly/main/dash/item/base')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class TextItem extends DashItem
7 | constructor: (@textContent, position={}, @defaultText='Type here...') ->
8 | unless ko.isObservable(@textContent)
9 | @textContent = ko.observable @textContent
10 |
11 | @templateName = 'tmpl-text-item' unless @templateName
12 | super(position)
13 |
14 | init: (@dom) =>
15 | super(dom)
16 | @loaded()
17 |
18 | onEditAreaBlur: ->
19 | Events.model.dashboarditem.update.trigger()
20 |
21 | return true
22 |
23 | serialize: (s={}) =>
24 | s.itemType = s.itemType ? 'TextItem'
25 | s.textContent = @textContent()
26 | super s
27 |
28 | deserialize: (s) =>
29 | @textContent(s.textContent) if s.textContent
30 | super(s)
31 |
32 | module.exports = TextItem
33 |
--------------------------------------------------------------------------------
/poly/main/dash/item/text.tmpl:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/poly/main/dash/workspace.tmpl:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/poly/main/data/data.tmpl:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/poly/main/data/metric/base.coffee:
--------------------------------------------------------------------------------
1 | class MetricView
2 | constructor: (@columnInfo) ->
3 | {@name, @tableName, @gaType} = @columnInfo
4 | @type = @columnInfo.meta.type
5 | @gaType = @columnInfo.gaType
6 | @originalFormula = @columnInfo.formula
7 | @formula =
8 | if @originalFormula?
9 | @originalFormula
10 | else if @name == 'count(*)'
11 | @name
12 | else
13 | "[#{@tableName}.#{@name}]"
14 | @extraCSS =
15 | if @columnInfo.formula
16 | 'derived-var'
17 | else
18 | @gaType
19 |
20 | fullFormula: (tableMetaData, unbracket=false) =>
21 | @columnInfo.getFormula(tableMetaData, unbracket)
22 |
23 | fullMeta: () -> @columnInfo.meta
24 |
25 | module.exports = MetricView
26 |
--------------------------------------------------------------------------------
/poly/main/data/metric/base.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
--------------------------------------------------------------------------------
/poly/main/data/metric/dropdown.coffee:
--------------------------------------------------------------------------------
1 | Events = require('poly/main/events')
2 | MetricView = require('poly/main/data/metric/base')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class DropdownMetricView extends MetricView
7 | constructor: (columnInfo, @label, @dropdownTemplate, @dropdownData, @dropdownAfterRender) ->
8 | @toggleDropdown = _.throttle @_toggleDropdown # ..or clicks gets registerd 2x
9 | @dropdownShowing = false
10 | super(columnInfo)
11 |
12 | _toggleDropdown: =>
13 | if @name isnt 'count(*)'
14 | if @dropdownShowing
15 | Events.ui.dropdown.hide.trigger()
16 | else
17 | Events.ui.dropdown.show.trigger {
18 | templateName: @dropdownTemplate
19 | data: @dropdownData
20 | targetDom: @dom
21 | onRemove: @setInactive
22 | afterRender: @dropdownAfterRender
23 | info: {name: @label, value: @name}
24 | }
25 |
26 | setInactive: =>
27 | @dropdownShowing = false
28 | if @dom
29 | @dom.removeClass 'dropdown-active'
30 | @dom.draggable 'enable'
31 |
32 | close: =>
33 | Events.ui.dropdown.hide.trigger()
34 |
35 | attachDropdown: (dom) =>
36 | @dom = $(dom)
37 | Events.ui.dropdown.shown.onElem @dom, =>
38 | @dropdownShowing = true
39 | @dom.addClass 'dropdown-active'
40 | @dom.draggable 'disable'
41 | Events.ui.dropdown.hidden.onElem @dom, @setInactive
42 |
43 | module.exports = DropdownMetricView
44 |
--------------------------------------------------------------------------------
/poly/main/data/metric/dropdown.tmpl:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/poly/main/data/metric/facet.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class FacetMetricView extends AttachedMetricView
7 | constructor: (columnInfo) ->
8 | updateFn = () => Events.ui.chart.render.trigger()
9 | options = () -> CONST.facets
10 | attachedMetrics = () -> []
11 | @removeText = "Remove \"" + columnInfo.name + "\" from facet"
12 | super columnInfo, @aes, updateFn, options, attachedMetrics
13 |
14 | module.exports = FacetMetricView
15 |
--------------------------------------------------------------------------------
/poly/main/data/metric/layer.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class LayerMetricView extends AttachedMetricView
7 | constructor: (columnInfo, @options, @layer, @aesName, defaults) ->
8 | updateFn = () => Events.ui.chart.render.trigger()
9 | attachedMetrics = @layer.attachedMetrics
10 | super columnInfo, @aesName, updateFn, @options, attachedMetrics, defaults
11 |
12 | module.exports = LayerMetricView
13 |
--------------------------------------------------------------------------------
/poly/main/data/metric/quickadd.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 |
3 | class QuickAddMetricView extends AttachedMetricView
4 | constructor: (columnInfo, @options, @aes) ->
5 | updateFn = () ->
6 | attachedMetrics = () -> []
7 | @removeText = "Remove \"" + columnInfo.name + "\" from " + @aes
8 | super columnInfo, @aes, updateFn, @options, attachedMetrics
9 |
10 | module.exports = QuickAddMetricView
11 |
--------------------------------------------------------------------------------
/poly/main/data/metric/quickaddtable.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 |
3 | class QuickAddTableMetricView extends AttachedMetricView
4 | constructor: (columnInfo, @options, @aes, attachedMetrics) ->
5 | updateFn = () ->
6 | @removeText = "Remove \"" + columnInfo.name + "\" from " + @aes
7 | super columnInfo, @aes, updateFn, @options, attachedMetrics
8 |
9 | module.exports = QuickAddTableMetricView
10 |
--------------------------------------------------------------------------------
/poly/main/data/table.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
22 |
--------------------------------------------------------------------------------
/poly/main/error/toast.coffee:
--------------------------------------------------------------------------------
1 | raise = (text) ->
2 | $().toastmessage('showErrorToast', text)
3 |
4 | module.exports = {
5 | raise
6 | }
7 |
--------------------------------------------------------------------------------
/poly/main/header.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
35 |
--------------------------------------------------------------------------------
/poly/main/init.coffee:
--------------------------------------------------------------------------------
1 | # Setup necessary prior to Polychart being used
2 |
3 | # load all the knockout templates
4 | require('poly/main/templates')
5 |
6 | # initiate custom KO bindings
7 | require('poly/main/bindings').init()
8 |
--------------------------------------------------------------------------------
/poly/main/main/builder.coffee:
--------------------------------------------------------------------------------
1 | # Top level view entry point - abstract classes
2 | # Code that is shared for both chart and dashboard builder
3 |
4 | Events = require('poly/main/events')
5 | DataView = require('poly/main/data/dataView')
6 | HeaderView = require('poly/main/header')
7 | OverlayView = require('poly/main/overlay')
8 | ShareView = require('poly/main/share')
9 |
10 | class AbstractBuilderEntryPoint
11 | constructor: (@params) ->
12 | Events.registerDefaultListeners()
13 |
14 | {@dom, @dataCollection, @exportingEnabled} = params
15 |
16 | # TODO Support multiple data sources on client
17 | if @dataCollection
18 | unless _.isArray(@dataCollection)
19 | @dataCollection = [@dataCollection]
20 | @dataSource = poly.data @dataCollection[0]
21 | @dataView = new DataView(@dataSource)
22 | @overlayView = new OverlayView()
23 | else
24 | throw new Error('No data collection provided!')
25 |
26 | @hasHeader = params.header ? false
27 | @headerView = new HeaderView(params.isDemo)
28 | @shareView = new ShareView()
29 |
30 | if params.width is 'fill'
31 | $(@dom).width('100%')
32 | if _.isNumber(params.width)
33 | $(@dom).width(params.width)
34 | if params.height is 'fill'
35 | $(@dom).height('100%')
36 | if _.isNumber(params.height)
37 | $(@dom).height(params.height)
38 | if params.width is 'fill' and params.height is 'fill'
39 | $(@dom).addClass('fill')
40 |
41 | initialize: () =>
42 | @dataView.initialize()
43 |
44 | module.exports = AbstractBuilderEntryPoint
45 |
--------------------------------------------------------------------------------
/poly/main/main/chartbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/poly/main/main/chartviewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view for viewing a particular chart
2 | AbstractViewerEntryPoint = require('poly/main/main/viewer')
3 |
4 | class ChartViewerMainView extends AbstractViewerEntryPoint
5 | constructor: (@params) ->
6 | super(@params)
7 | @spec = params.initial ? {}
8 | @tableMetaData = @dataView.getTableMetaData()
9 |
10 | init: (dom) =>
11 | initialCols = @spec.newcols ? []
12 | @dataView.initialize initialCols, () =>
13 | # instead of using spec.layer, use spec.layers
14 | if @spec.layer
15 | @spec.layers = [@spec.layer]
16 | delete @spec.layer
17 | # generate the polyJS object for each layer (given tableName)
18 | for layer in @spec.layers
19 | if not layer.data
20 | tableName = layer.tableName
21 | if not tableName? and layer.meta and m = _.toArray(layer.meta)[0]
22 | tableName = m.tableName
23 | layer.data = @tableMetaData.polyJsObjectFor {tableName}
24 | @spec.width ?= @params.width
25 | @spec.height ?= @params.height
26 | @spec.dom = dom[0]
27 | polyjs.chart(@spec)
28 |
29 |
30 | module.exports = ChartViewerMainView
31 |
--------------------------------------------------------------------------------
/poly/main/main/chartviewer.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/poly/main/main/dashviewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view for viewing a particular chart
2 | AbstractViewerEntryPoint = require('poly/main/main/viewer')
3 | WorkspaceView = require('poly/main/dash/workspace')
4 |
5 | class DashViewerMainView extends AbstractViewerEntryPoint
6 | constructor: (@params) ->
7 | super(@params)
8 |
9 | tableMetaData = @dataView.getTableMetaData()
10 | @workspaceView = new WorkspaceView(@params.name, tableMetaData, true)
11 | @initialize()
12 |
13 | initialize: () ->
14 | initial = @params.initial ? []
15 | if _.isArray(@params.initial)
16 | initialItems = @params.initial
17 | initialCols = []
18 | else if _.isObject(@params.initial)
19 | initialItems = @params.initial.items ? []
20 | initialCols = @params.initial.newcols ? []
21 |
22 | @dataView.initialize initialCols, () => @workspaceView.initialize(initialItems)
23 |
24 | module.exports = DashViewerMainView
25 |
--------------------------------------------------------------------------------
/poly/main/main/dashviewer.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/poly/main/main/viewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view entry point - abstract classes
2 | # Code that is shared for both chart and dashboard Viewer
3 |
4 | DataView = require('poly/main/data/dataView')
5 | Events = require('poly/main/events')
6 |
7 | class AbstractViewerEntryPoint
8 | constructor: (@params) ->
9 | Events.registerDefaultListeners()
10 |
11 | {@dom, @dataCollection} = params
12 |
13 | # TODO Support multiple data sources on client
14 | if @dataCollection
15 | unless _.isArray(@dataCollection)
16 | @dataCollection = [@dataCollection]
17 | # shared "views"
18 | @dataSource = poly.data @dataCollection[0]
19 | else
20 | throw new Error('No data collection provided!')
21 |
22 | @dataView = new DataView(@dataSource)
23 |
24 | initialize: () =>
25 | @dataView.initialize()
26 |
27 | module.exports = AbstractViewerEntryPoint
28 |
--------------------------------------------------------------------------------
/poly/main/numeral/numeralbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
25 |
26 |
29 |
--------------------------------------------------------------------------------
/poly/main/share.coffee:
--------------------------------------------------------------------------------
1 | ###
2 | # Hook up events for the share panel.
3 | ###
4 | CONST = require('poly/main/const')
5 | Events = require('poly/main/events')
6 | serverApi = require('poly/common/serverApi')
7 |
8 | class ShareView
9 | constructor: () ->
10 | @defaultPanelRight = -250
11 | @panelRight = ko.observable(@defaultPanelRight)
12 | Events.nav.sharepanel.open.on @open
13 | Events.nav.sharepanel.close.on @close
14 |
15 | open: () =>
16 | @panelRight(0)
17 |
18 | close: () =>
19 | @panelRight(@defaultPanelRight)
20 |
21 | exportPDF: ->
22 | Events.export.pdf.click.trigger callback: @_export('pdf')
23 |
24 | exportPNG: ->
25 | Events.export.png.click.trigger callback: @_export('png')
26 |
27 | exportSVG: ->
28 | Events.export.svg.click.trigger callback: @_export('svg')
29 |
30 | _export: (type) -> (serial) ->
31 | serverApi.sendPost(
32 | "/dashboard/export/code"
33 | , {serial: serial, exportType: type}
34 | , (err, result) ->
35 | if err
36 | console.error err
37 | TOAST.raise 'Error exporting dashboard.'
38 | return
39 |
40 | window.location = "/api/dashboard/export/" + encodeURIComponent(result.code)
41 | )
42 |
43 | module.exports = ShareView
44 |
--------------------------------------------------------------------------------
/poly/main/share.tmpl:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/poly/main/table/aesGroup.tmpl:
--------------------------------------------------------------------------------
1 |
33 |
34 |
--------------------------------------------------------------------------------
/poly/main/table/table.less:
--------------------------------------------------------------------------------
1 | .tablebuilder-table {
2 | height: 100%;
3 | overflow: scroll;
4 | padding: 2px;
5 |
6 | text-align: center;
7 | background-color: @white;
8 | }
9 |
--------------------------------------------------------------------------------
/poly/main/table/tablebuilder.tmpl:
--------------------------------------------------------------------------------
1 |
32 |
33 |
36 |
--------------------------------------------------------------------------------
/poly/signup.coffee:
--------------------------------------------------------------------------------
1 | Events = require('poly/main/events')
2 |
3 | init = () ->
4 | Events.signup.page.view.trigger()
5 | eulaClickTrap '#start', '#realsubmit', '#eula', Events.signup.eula.error
6 | Events.signup.form.submit.trackForm $('#realsubmit')
7 | $('input').on 'keypress keydown', _.once ->
8 | Events.signup.form.interact.trigger()
9 |
10 | eulaClickTrap = (submitBtn, hiddenBtn, eula, errorEvt) ->
11 | $(submitBtn).on 'click', (e) ->
12 | e.stopPropagation()
13 | if $(eula).prop 'checked'
14 | $(hiddenBtn).click()
15 | else
16 | if errorEvt then errorEvt.trigger()
17 | alert 'You must first read and accept the Terms and Conditions.'
18 |
19 | module.exports = {
20 | init
21 | }
22 |
--------------------------------------------------------------------------------
/poly/verifyPendingDs.coffee:
--------------------------------------------------------------------------------
1 | serverApi = require('poly/common/serverApi')
2 |
3 | load = (dsParams) ->
4 | serverApi.sendPost '/data-source/create', dsParams, (err, response) ->
5 | if err
6 | console.error err
7 | else
8 | window.location.href = '/home'
9 |
10 | module.exports = {run}
11 |
--------------------------------------------------------------------------------
/polychart/README.md:
--------------------------------------------------------------------------------
1 | Polychart Dashboard Builder Backend
2 | ===================================
3 | Herein lies the backend code for the Polychart Dashboard Builder. The server is
4 | written in Python and is built atop of the [Django] (https://www.djangoproject.com/)
5 | web framework. The primary directories here are `config/` and `main/`; the
6 | former contains Django-related configuration files that provide settings to the
7 | Django environment, with the possibility of differing setups in a local
8 | development environment and a production environment; the latter directory
9 | contains the actual logic and code for Dashboard Builder related processing. For
10 | a detailed description of the contents of each directory, see the documents
11 | contained in the individual directories.
12 |
13 | Within this directory lie three main files.
14 |
15 | First, `urls.py` determines the collection of URL patterns to be given to the
16 | application. This file is written in such a way that it may collect the URL
17 | patterns for a variety of applications, add to it some other predetermined
18 | patterns, and package them up for the Django application as a whole.
19 |
20 | The other two files, `utils.py` and `wsgi.py` are rather short and
21 | self-explanatory: the first defines a collection of Django-related utility
22 | functions that are oft used in View Handler functions and the latter defines the
23 | [WSGI] (http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) application
24 | settings for the Django environment.
25 |
--------------------------------------------------------------------------------
/polychart/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/__init__.py
--------------------------------------------------------------------------------
/polychart/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/config/__init__.py
--------------------------------------------------------------------------------
/polychart/config/deploy.py:
--------------------------------------------------------------------------------
1 | """
2 | Project settings for production-like deployments.
3 |
4 | Settings in this file are overridden by values in
5 | polychart.config.deployOverrides.
6 | """
7 |
8 | from polychart.config.shared import *
9 |
10 | DEBUG = False
11 | TEMPLATE_DEBUG = False
12 |
13 | SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
14 |
15 | try:
16 | from polychart.config.deployOverrides import *
17 | except ImportError:
18 | pass
19 |
--------------------------------------------------------------------------------
/polychart/config/local.py:
--------------------------------------------------------------------------------
1 | """
2 | Project settings used during local development.
3 |
4 | Settings in this file are overridden by values in
5 | polychart.config.localOverrides.
6 | """
7 |
8 | from polychart.config.shared import *
9 |
10 | DEBUG = True
11 | TEMPLATE_DEBUG = True
12 |
13 | # Generate your own for production deployments!
14 | SECRET_KEY = 'TkLhoWRKORnKShe3PtdJo8jvTcm6RloPzj1sagGHbIbK3vd16U9OvZ96qvpA6TRW'
15 |
16 | HOST_URL = 'http://localhost:8000'
17 |
18 | DATABASES = {
19 | 'default': {
20 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
21 | 'NAME': 'dev.db', # Or path to database file if using sqlite3.
22 | # The following settings are not used with sqlite3:
23 | 'USER': '',
24 | 'PASSWORD': '',
25 | 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
26 | 'PORT': '', # Set to empty string for default.
27 | }
28 | }
29 |
30 | CACHES = {
31 | 'default': {
32 | 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
33 | 'LOCATION': 'unique-snowflake',
34 | }
35 | }
36 |
37 | EMAIL_BACKEND = 'polychart.main.utils.emailConsole.ConsoleEmailBackend'
38 |
39 | try:
40 | from polychart.config.localOverrides import *
41 | except ImportError:
42 | pass
43 |
--------------------------------------------------------------------------------
/polychart/config/localOverrides.py:
--------------------------------------------------------------------------------
1 | GOOGLE_ANALYTICS_CLIENT_ID = "740897306893.apps.googleusercontent.com"
2 | GOOGLE_ANALYTICS_CLIENT_SECRET = "si27VH63M7XNmhaM4ycLFTq-"
3 |
4 | ENABLED_DATA_SOURCE_TYPES = [
5 | 'mysql',
6 | 'infobright',
7 | 'postgresql',
8 | 'csv',
9 |
10 | # Salesforce requires additional settings:
11 | # SALESFORCE_CLIENT_ID and SALESFORCE_CLIENT_SECRET
12 | # 'salesforce',
13 |
14 | # Google Analytics requires additional settings:
15 | # GOOGLE_ANALYTICS_CLIENT_ID and GOOGLE_ANALYTICS_CLIENT_SECRET
16 | 'googleAnalytics',
17 | ]
18 |
--------------------------------------------------------------------------------
/polychart/main/README.md:
--------------------------------------------------------------------------------
1 | Polychart Dashboard Builder Main Application
2 | ============================================
3 | This directory contains the Django application for the Polychart Dashboard
4 | Builder. The layout is typical of a Django application:
5 |
6 | * `models.py` define the models that are used in the database;
7 | * `urls.py` define the specific endpoints for which the Dashboard builder
8 | uses, and the corresponding handler function for these endpoints.
9 | * `management/` contains extensions to how `manage.py` works at the root level
10 | of the Django application;
11 | * `migrations/` contains generated and handwritten data base migrations for
12 | the Django application;
13 | * `templates/` directory contains the Django template files;
14 | * `utils/` directory contains an assortment of utility modules that are used
15 | throughout the code base;
16 | * `views/` directory contains handler functions that are used by the URL
17 | routing;
18 |
19 | One important thing to note here is that the backend code also relies on the
20 | Polychart Query package.
21 |
--------------------------------------------------------------------------------
/polychart/main/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/__init__.py
--------------------------------------------------------------------------------
/polychart/main/management/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/management/__init__.py
--------------------------------------------------------------------------------
/polychart/main/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/management/commands/__init__.py
--------------------------------------------------------------------------------
/polychart/main/management/commands/createuser.py:
--------------------------------------------------------------------------------
1 | from django.core.management.base import BaseCommand, CommandError
2 | from getpass import getpass
3 |
4 | from polychart.main.views.account import createUser
5 |
6 | class Command(BaseCommand):
7 | def handle(self, *args, **kwargs):
8 | userParams = {
9 | 'first_name': _prompt('First name: '),
10 | 'last_name': _prompt('Last name: '),
11 | 'username': _prompt('Username: '),
12 | 'password': _prompt('Password: ', maskInput=True),
13 | }
14 |
15 | createUser(userParams)
16 |
17 | def _prompt(msg, maskInput=False):
18 | while True:
19 | if maskInput:
20 | result = getpass(msg)
21 | else:
22 | result = raw_input(msg)
23 |
24 | result = result.strip()
25 |
26 | if result:
27 | return result
28 |
--------------------------------------------------------------------------------
/polychart/main/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/migrations/__init__.py
--------------------------------------------------------------------------------
/polychart/main/templates/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/templates/__init__.py
--------------------------------------------------------------------------------
/polychart/main/templates/base.tmpl:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{% block title %}{% endblock %}
9 |
10 |
11 |
12 |
13 | {% block styles %}
14 | {% endblock %}
15 |
16 |
17 |
18 |
19 | {% block scripts %}
20 | {% endblock %}
21 |
22 |
23 | {% block body %}{% endblock %}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/polychart/main/templates/callback.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 | {% load staticfiles %}
3 |
4 | {% block title %}Loading...{% endblock %}
5 | {% block body %}
6 |
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/polychart/main/templates/dashEdit.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/polychart/main/templates/dashView.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
21 | {% endblock %}
22 |
--------------------------------------------------------------------------------
/polychart/main/templates/demo.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder Demo{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
48 | {% endblock %}
49 |
--------------------------------------------------------------------------------
/polychart/main/templates/forgotPassword.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 |
3 | {% block body %}
4 | {% if status == 'success' %}
5 |
6 |
7 | Please check your email for a reset code.
8 |
9 |
10 | {% else %}
11 |
12 | {% if status == 'accountNotFound' %}
13 |
14 | We could not locate your account.
15 |
16 | {% endif %}
17 |
18 |
19 |
20 |
Forgot your password?
21 |
Just enter your email address or username below.
22 |
23 |
35 |
36 | {% endif %}
37 | {% endblock %}
38 |
--------------------------------------------------------------------------------
/polychart/main/templates/login.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 | {% block body %}
3 |
4 | {% if error == 'auth' %}
5 |
6 | Invalid username or password.
7 |
8 | {% elif error %}
9 |
10 | An unknown error occured. Please try again later!
11 |
12 | {% endif %}
13 |
14 |
15 |
16 | Log In
17 | {% if settings.SIGNUP_ENABLED %}
18 |
19 | Don't have an account? Sign up for one here, it's free!
20 |
21 | {% endif %}
22 | {% if settings.PASSWORD_RESET_ENABLED %}
23 |
24 | If you already have an account but you've forgot your password, click here.
25 |
26 | {% endif %}
27 |
28 |
50 |
51 | {% endblock %}
52 |
--------------------------------------------------------------------------------
/polychart/main/templates/logout.tmpl:
--------------------------------------------------------------------------------
1 |
Log Out
2 |
5 |
--------------------------------------------------------------------------------
/polychart/main/templates/resetPassword.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 |
3 | {% block body %}
4 |
5 |
Reset password
6 |
Enter a new password for the user account “{{ username }}”.
7 |
18 |
19 | {% endblock %}
20 |
--------------------------------------------------------------------------------
/polychart/main/templates/verifyPendingDataSource.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% block title %}Connecting data source...{% end %}
4 |
5 | {% block body %}
6 | {% if result['status'] == 'error' %}
7 |
8 |
Oh, no!
9 |
10 | Unfortunately, we were not able to connect your data source to Polychart.
11 |
12 | {% if result['error']['type'] == 'connection' %}
13 |
{{ result['error']['message'] }}
14 |
15 | If you're not sure how to resolve this issue,
16 | feel free to contact us via the link in the bottom right corner.
17 |
18 | {% else %}
19 |
20 | We're not quite sure what went wrong.
21 | Please contact us via the link in the bottom right to resolve this issue.
22 |
23 | {% end %}
24 |
25 | {% endblock %}
26 | {% endblock %}
27 |
--------------------------------------------------------------------------------
/polychart/main/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/polychart/main/utils/secureStorage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import Padding
4 |
5 | from Crypto.Cipher import AES
6 | from base64 import urlsafe_b64encode, urlsafe_b64decode
7 | from django.conf import settings
8 | from os import urandom
9 | from pbkdf2 import PBKDF2
10 |
11 | def getEncryptionKey(password, salt):
12 | assert password
13 | assert salt
14 |
15 | saltbytes = urlsafe_b64decode(salt.encode('utf-8'))
16 | hashThing = PBKDF2(password, saltbytes)
17 | return hashThing.read(32)
18 |
19 | DEFAULT_KEY = getEncryptionKey(settings.SECRET_KEY, 'ziIwStZZ')
20 |
21 | def encrypt(key, plaintext):
22 | assert key
23 |
24 | if plaintext == "":
25 | return ""
26 |
27 | aes = AES.new(key, AES.MODE_CBC, b"Polychart AES IV")
28 | padded = Padding.appendPadding(plaintext)
29 | cipherbytes = aes.encrypt(padded)
30 | return urlsafe_b64encode(cipherbytes)
31 |
32 | def decrypt(key, ciphertext):
33 | assert key
34 |
35 | if ciphertext == "":
36 | return ""
37 |
38 | aes = AES.new(key, AES.MODE_CBC, b"Polychart AES IV")
39 | cipherbytes = urlsafe_b64decode(ciphertext.encode('utf-8'))
40 | padded = aes.decrypt(cipherbytes)
41 | return Padding.removePadding(padded)
42 |
43 | def generateSalt():
44 | return urlsafe_b64encode(urandom(8))
45 |
--------------------------------------------------------------------------------
/polychart/main/utils/spec.py:
--------------------------------------------------------------------------------
1 | """
2 | Functions related to processing frontend spec objects.
3 | """
4 | import re
5 |
6 |
7 | def getDsInfo(spec):
8 | """
9 | Extracts the list of (tableName, dsKey) pairs from the clientside chart
10 | specification produced by the Dashboard Builder.
11 |
12 | Args:
13 | spec: A dictionary corresponding to the client side chart spec object. The
14 | spec object must have the field 'meta', whose value will be a dictionary
15 | with keys as column names and values as dictionaries that contain the
16 | desired information. For example:
17 |
18 | spec = { ...
19 | meta: { columnOne: { tableName: "Table_One", dsKey: "keyone" , ... }
20 | , columnTwo: { tableName: "Table_Two", dsKey: "keyone" , ...}
21 | ... }
22 | ... }
23 |
24 | Returns:
25 | A list of distinct pairs with tableName in the first entry and dsKey in the
26 | second. Both values will be strings.
27 | """
28 | result = []
29 | for _, val in spec['meta'].iteritems():
30 | pair = (val.get('tableName'), val.get('dsKey'))
31 | if pair[0] is None and pair[1] is None:
32 | continue
33 | elif pair not in result:
34 | result.append(pair)
35 | return result
36 |
--------------------------------------------------------------------------------
/polychart/main/utils/tools.py:
--------------------------------------------------------------------------------
1 | """
2 | A collection of very miscellaneous tools.
3 | """
4 | ### Filepath tools
5 | from base64 import urlsafe_b64encode
6 | import atexit
7 | import os
8 |
9 | # Ensure tmp directory exists
10 | if not os.path.exists('tmp'):
11 | os.mkdir('tmp')
12 |
13 | def getNewTempFilePath():
14 | path = os.getcwd() + '/tmp/' + urlsafe_b64encode(os.urandom(18))
15 | deleteOnExit(path)
16 | return path
17 |
18 | def deleteOnExit(path):
19 | def cleanup():
20 | try: os.remove(path)
21 | except: pass
22 | atexit.register(cleanup)
23 |
24 | ### Misc functions
25 | def randomCode():
26 | # 18 random bytes -- more than a UUID, and looks nicer in base 64
27 | return urlsafe_b64encode(os.urandom(18))
28 |
--------------------------------------------------------------------------------
/polychart/main/views/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/polychart/main/views/__init__.py
--------------------------------------------------------------------------------
/polychart/main/views/demo.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers to deal with the demo.
3 | """
4 | import json
5 |
6 | from django.shortcuts import render
7 | from django.views.decorators.http import require_GET, require_http_methods
8 |
9 | from polychart.main.models import TutorialCompletion
10 |
11 | @require_GET
12 | def demoShow(request):
13 | """Django handler to show the demo dashboard."""
14 | # pylint: disable = E1101
15 | # Pylint does not recognize Django model attributes.
16 | if request.user.is_authenticated():
17 | showTutorial = not TutorialCompletion.objects.filter(user=request.user, type='nux').exists()
18 | else:
19 | showTutorial = True
20 |
21 | tutorialOverride = request.GET.get('showTutorial', None)
22 | if tutorialOverride == 'yes':
23 | showTutorial = True
24 | elif tutorialOverride == 'no':
25 | showTutorial = False
26 |
27 | return render( request
28 | , 'demo.tmpl'
29 | , dictionary = { 'showTutorial': showTutorial })
30 |
31 |
--------------------------------------------------------------------------------
/polychart/main/views/home.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers to deal with the Dashboard Builder home.
3 | """
4 | from django.contrib.auth.decorators import login_required
5 | from django.shortcuts import render
6 | from django.views.decorators.http import require_GET
7 |
8 | from polychart.main.models import DataSource, Dashboard, TutorialCompletion
9 |
10 | @require_GET
11 | @login_required
12 | def show(request):
13 | """Django handler to render home."""
14 | # pylint: disable = E1101
15 | # Pylint does not notice Django model attributes
16 | newDataSourceKey = request.GET.get('newDataSourceKey', None)
17 |
18 | dataSources = DataSource.objects.filter(user=request.user)
19 | dashboards = Dashboard.objects.filter(user=request.user)
20 | tutorialCompleted = TutorialCompletion.objects.filter(user=request.user, type='nux').exists()
21 |
22 | return render( request
23 | , 'home.tmpl'
24 | , dictionary = { 'dataSources': dataSources
25 | , 'dashboards': dashboards
26 | , 'tutorialCompleted': tutorialCompleted
27 | , 'newDataSourceKey': newDataSourceKey })
28 |
--------------------------------------------------------------------------------
/polychart/main/views/tutorial.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers related to the tutorial.
3 | """
4 | import json
5 |
6 | from django.contrib.auth.decorators import login_required
7 | from django.views.decorators.http import require_POST
8 |
9 | from polychart.main.models import TutorialCompletion
10 | from polychart.utils import jsonResponse
11 |
12 | @require_POST
13 | @login_required
14 | def tutorialComplete(request):
15 | """Django handler for completion of the tutorial."""
16 | body = json.loads(request.body)
17 |
18 | TutorialCompletion(
19 | user=request.user,
20 | type=body['type']
21 | ).save()
22 |
23 | return jsonResponse({})
24 |
--------------------------------------------------------------------------------
/polychart/urls.py:
--------------------------------------------------------------------------------
1 | """
2 | Defines how Django should route HTTP requests to views.
3 | Some applications have their own routing files.
4 | See `polychart.*.urls`.
5 | """
6 |
7 | import polychart.main.urls as MAIN_URLS
8 |
9 | try:
10 | import polychart.site.urls as SITE_URLS
11 | except ImportError:
12 | SITE_URLS = None
13 |
14 | try:
15 | import polychart.jsSite.urls as JS_SITE_URLS
16 | except ImportError:
17 | JS_SITE_URLS = None
18 |
19 | try:
20 | import polychart.analytics.urls as ANALYTICS_URLS
21 | except ImportError:
22 | ANALYTICS_URLS = None
23 |
24 | from django.conf.urls import include, patterns, url
25 | from polychart.utils import permanentRedirect
26 |
27 | def _buildPatternList():
28 | urls = [
29 | # Main website
30 | url(r'^', include(SITE_URLS)) if SITE_URLS else None,
31 |
32 | # Main app
33 | url(r'^', include(MAIN_URLS)),
34 |
35 | # Polychart.js website
36 | url(r'^js/', include(JS_SITE_URLS)) if JS_SITE_URLS else None,
37 |
38 | # Analytics
39 | url('^', include(ANALYTICS_URLS)) if ANALYTICS_URLS else None,
40 |
41 | # Deprecated URLs
42 | url(r'^beta$', permanentRedirect('/signup')),
43 | url(r'^devkit.*$', permanentRedirect('/')),
44 | url(r'^embed/.*$', permanentRedirect('/')),
45 | ]
46 |
47 | # Filter out None
48 | urls = [x for x in urls if x]
49 |
50 | return patterns('polychart.main.views', *urls)
51 |
52 | urlpatterns = _buildPatternList()
53 |
--------------------------------------------------------------------------------
/polychart/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for polychart project.
3 |
4 | This module contains the WSGI application used by Django's development server
5 | and any production WSGI deployments. It should expose a module-level variable
6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7 | this application via the ``WSGI_APPLICATION`` setting.
8 |
9 | Usually you will have the standard Django WSGI application here, but it also
10 | might make sense to replace the whole Django WSGI application with a custom one
11 | that later delegates to the Django one. For example, you could introduce WSGI
12 | middleware here, or combine a Django application with an application of another
13 | framework.
14 | """
15 |
16 | # This application object is used by any WSGI server configured to use this
17 | # file. This includes Django's development server, if the WSGI_APPLICATION
18 | # setting points here.
19 | from django.core.wsgi import get_wsgi_application
20 | application = get_wsgi_application()
21 |
22 | # Apply WSGI middleware here.
23 | # from helloworld.wsgi import HelloWorldApplication
24 | # application = HelloWorldApplication(application)
25 |
--------------------------------------------------------------------------------
/polychartQuery/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Provide a public interface for constructing new SQL-esque data sources.
3 | """
4 | from polychartQuery.sql import MySqlConn, InfobrightConn, PostgreSqlConn
5 |
6 | __all__ = []
7 |
8 | def openConnection(type, *args, **kwargs):
9 | if type == 'mysql':
10 | return MySqlConn(*args, **kwargs)
11 |
12 | elif type == 'infobright':
13 | return InfobrightConn(*args, **kwargs)
14 |
15 | elif type == 'postgresql':
16 | return PostgreSqlConn(*args, **kwargs)
17 |
--------------------------------------------------------------------------------
/polychartQuery/csv/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from connection import Conn as Connection
4 |
--------------------------------------------------------------------------------
/polychartQuery/csv/connection.py:
--------------------------------------------------------------------------------
1 | """
2 | Module defining a dummy CSV connection.
3 | """
4 | from polychartQuery.abstract import DataSourceConnection
5 |
6 | class Conn(DataSourceConnection):
7 | """
8 | Dummy class (for now)
9 | """
10 | def __init__(self, *args, **kwargs):
11 | super(Conn, self).__init__(*args, **kwargs)
12 | pass
13 |
--------------------------------------------------------------------------------
/polychartQuery/googleAnalytics/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from query import GAQuery as Query
4 | from connection import GAConn as Connection
5 |
--------------------------------------------------------------------------------
/polychartQuery/sql/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from polychartQuery.sql.query import SqlQuery, PostgreSqlQuery
4 | from polychartQuery.sql.connection import MySqlConn, PostgreSqlConn, InfobrightConn
5 |
--------------------------------------------------------------------------------
/requirements:
--------------------------------------------------------------------------------
1 | # Please include an exact version number with every package,
2 | # and use the correct case of the package name.
3 | # Unless necessary, do not use the inequality operators (e.g. ">").
4 | #
5 | # This reduces the number of "works for me" problems that occur
6 | # between different installations of Polychart.
7 |
8 | # Django
9 | Django==1.5.5
10 | South==0.7.6
11 | django-jsonfield==0.8.11
12 | django-modeldict==1.3.6
13 | nexus==0.2.3
14 |
15 | # Database drivers
16 | MySQL-python==1.2.5
17 | psycopg2==2.5.1
18 |
19 | # Crypto
20 | Padding==0.4
21 | pbkdf2==1.3
22 | pycrypto==2.6
23 |
24 | # Build-related
25 | lxml==3.2.0
26 | virtualenv==1.10.1
27 |
28 | # Deployment-related
29 | gunicorn==17.5
30 | python-memcached==1.53
31 |
32 | # Export-related
33 | CairoSVG==0.5 # can't move to 1.0.X due to https://github.com/Kozea/CairoSVG/issues/37
34 | WeasyPrint==0.19.2
35 | cairocffi==0.5.1
36 | svgwrite==1.1.2
37 | websocket-client==0.11.0
38 |
39 | # Misc
40 | analytics-python==0.4.1
41 | pika==0.9.5
42 | python-dateutil==2.1
43 | raven==1.6.1
44 | requests==1.2.3
45 | unittest-xml-reporting==1.3.2
46 |
--------------------------------------------------------------------------------
/server/README:
--------------------------------------------------------------------------------
1 | Backend files for Polychart.
2 |
3 | The folder `polychartQuery` contains the logic for turning frontend
4 | drag-and-drop actions into SQL queries, google analytics calls, etc.
5 |
6 |
--------------------------------------------------------------------------------
/server/cairo.py:
--------------------------------------------------------------------------------
1 | from cairocffi import *
2 |
--------------------------------------------------------------------------------
/server/polychart/README.md:
--------------------------------------------------------------------------------
1 | Polychart Dashboard Builder Backend
2 | ===================================
3 | Herein lies the backend code for the Polychart Dashboard Builder. The server is
4 | written in Python and is built atop of the [Django] (https://www.djangoproject.com/)
5 | web framework. The primary directories here are `config/` and `main/`; the
6 | former contains Django-related configuration files that provide settings to the
7 | Django environment, with the possibility of differing setups in a local
8 | development environment and a production environment; the latter directory
9 | contains the actual logic and code for Dashboard Builder related processing. For
10 | a detailed description of the contents of each directory, see the documents
11 | contained in the individual directories.
12 |
13 | Within this directory lie three main files.
14 |
15 | First, `urls.py` determines the collection of URL patterns to be given to the
16 | application. This file is written in such a way that it may collect the URL
17 | patterns for a variety of applications, add to it some other predetermined
18 | patterns, and package them up for the Django application as a whole.
19 |
20 | The other two files, `utils.py` and `wsgi.py` are rather short and
21 | self-explanatory: the first defines a collection of Django-related utility
22 | functions that are oft used in View Handler functions and the latter defines the
23 | [WSGI] (http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) application
24 | settings for the Django environment.
25 |
--------------------------------------------------------------------------------
/server/polychart/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/__init__.py
--------------------------------------------------------------------------------
/server/polychart/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/config/__init__.py
--------------------------------------------------------------------------------
/server/polychart/config/deploy.py:
--------------------------------------------------------------------------------
1 | """
2 | Project settings for production-like deployments.
3 |
4 | Settings in this file are overridden by values in
5 | polychart.config.deployOverrides.
6 | """
7 |
8 | from polychart.config.shared import *
9 |
10 | DEBUG = False
11 | TEMPLATE_DEBUG = False
12 |
13 | SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
14 |
15 | try:
16 | from polychart.config.deployOverrides import *
17 | except ImportError:
18 | pass
19 |
--------------------------------------------------------------------------------
/server/polychart/config/local.py:
--------------------------------------------------------------------------------
1 | """
2 | Project settings used during local development.
3 |
4 | Settings in this file are overridden by values in
5 | polychart.config.localOverrides.
6 | """
7 |
8 | from polychart.config.shared import *
9 |
10 | DEBUG = True
11 | TEMPLATE_DEBUG = True
12 |
13 | # Generate your own for production deployments!
14 | SECRET_KEY = 'TkLhoWRKORnKShe3PtdJo8jvTcm6RloPzj1sagGHbIbK3vd16U9OvZ96qvpA6TRW'
15 |
16 | HOST_URL = 'http://localhost:8000'
17 |
18 | DATABASES = {
19 | 'default': {
20 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
21 | 'NAME': 'dev.db', # Or path to database file if using sqlite3.
22 | # The following settings are not used with sqlite3:
23 | 'USER': '',
24 | 'PASSWORD': '',
25 | 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
26 | 'PORT': '', # Set to empty string for default.
27 | }
28 | }
29 |
30 | CACHES = {
31 | 'default': {
32 | 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
33 | 'LOCATION': 'unique-snowflake',
34 | }
35 | }
36 |
37 | EMAIL_BACKEND = 'polychart.main.utils.emailConsole.ConsoleEmailBackend'
38 |
39 | try:
40 | from polychart.config.localOverrides import *
41 | except ImportError:
42 | pass
43 |
--------------------------------------------------------------------------------
/server/polychart/main/README.md:
--------------------------------------------------------------------------------
1 | Polychart Dashboard Builder Main Application
2 | ============================================
3 | This directory contains the Django application for the Polychart Dashboard
4 | Builder. The layout is typical of a Django application:
5 |
6 | * `models.py` define the models that are used in the database;
7 | * `urls.py` define the specific endpoints for which the Dashboard builder
8 | uses, and the corresponding handler function for these endpoints.
9 | * `management/` contains extensions to how `manage.py` works at the root level
10 | of the Django application;
11 | * `migrations/` contains generated and handwritten data base migrations for
12 | the Django application;
13 | * `templates/` directory contains the Django template files;
14 | * `utils/` directory contains an assortment of utility modules that are used
15 | throughout the code base;
16 | * `views/` directory contains handler functions that are used by the URL
17 | routing;
18 |
19 | One important thing to note here is that the backend code also relies on the
20 | Polychart Query package.
21 |
--------------------------------------------------------------------------------
/server/polychart/main/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/management/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/management/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/management/commands/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/management/commands/createuser.py:
--------------------------------------------------------------------------------
1 | from django.core.management.base import BaseCommand, CommandError
2 | from getpass import getpass
3 |
4 | from polychart.main.views.account import createUser
5 |
6 | class Command(BaseCommand):
7 | def handle(self, *args, **kwargs):
8 | userParams = {
9 | 'first_name': _prompt('First name: '),
10 | 'last_name': _prompt('Last name: '),
11 | 'username': _prompt('Username: '),
12 | 'password': _prompt('Password: ', maskInput=True),
13 | }
14 |
15 | createUser(userParams)
16 |
17 | def _prompt(msg, maskInput=False):
18 | while True:
19 | if maskInput:
20 | result = getpass(msg)
21 | else:
22 | result = raw_input(msg)
23 |
24 | result = result.strip()
25 |
26 | if result:
27 | return result
28 |
--------------------------------------------------------------------------------
/server/polychart/main/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/migrations/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/templates/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/templates/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/templates/base.tmpl:
--------------------------------------------------------------------------------
1 | {% load staticfiles %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{% block title %}{% endblock %}
9 |
10 |
11 |
12 |
13 | {% block styles %}
14 | {% endblock %}
15 |
16 |
17 |
18 |
19 | {% block scripts %}
20 | {% endblock %}
21 |
22 |
23 | {% block body %}{% endblock %}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/callback.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 | {% load staticfiles %}
3 |
4 | {% block title %}Loading...{% endblock %}
5 | {% block body %}
6 |
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/dashEdit.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/dashView.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
21 | {% endblock %}
22 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/demo.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% load staticfiles %}
4 |
5 | {% block title %}Dashboard Builder Demo{% endblock %}
6 |
7 | {% block body %}
8 |
9 |
48 | {% endblock %}
49 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/forgotPassword.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 |
3 | {% block body %}
4 | {% if status == 'success' %}
5 |
6 |
7 | Please check your email for a reset code.
8 |
9 |
10 | {% else %}
11 |
12 | {% if status == 'accountNotFound' %}
13 |
14 | We could not locate your account.
15 |
16 | {% endif %}
17 |
18 |
19 |
20 |
Forgot your password?
21 |
Just enter your email address or username below.
22 |
23 |
35 |
36 | {% endif %}
37 | {% endblock %}
38 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/login.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 | {% block body %}
3 |
4 | {% if error == 'auth' %}
5 |
6 | Invalid username or password.
7 |
8 | {% elif error %}
9 |
10 | An unknown error occured. Please try again later!
11 |
12 | {% endif %}
13 |
14 |
15 |
16 | Log In
17 | {% if settings.SIGNUP_ENABLED %}
18 |
19 | Don't have an account? Sign up for one here, it's free!
20 |
21 | {% endif %}
22 | {% if settings.PASSWORD_RESET_ENABLED %}
23 |
24 | If you already have an account but you've forgot your password, click here.
25 |
26 | {% endif %}
27 |
28 |
50 |
51 | {% endblock %}
52 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/logout.tmpl:
--------------------------------------------------------------------------------
1 |
Log Out
2 |
5 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/resetPassword.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "oldBase.tmpl" %}
2 |
3 | {% block body %}
4 |
5 |
Reset password
6 |
Enter a new password for the user account “{{ username }}”.
7 |
18 |
19 | {% endblock %}
20 |
--------------------------------------------------------------------------------
/server/polychart/main/templates/verifyPendingDataSource.tmpl:
--------------------------------------------------------------------------------
1 | {% extends "base.tmpl" %}
2 |
3 | {% block title %}Connecting data source...{% end %}
4 |
5 | {% block body %}
6 | {% if result['status'] == 'error' %}
7 |
8 |
Oh, no!
9 |
10 | Unfortunately, we were not able to connect your data source to Polychart.
11 |
12 | {% if result['error']['type'] == 'connection' %}
13 |
{{ result['error']['message'] }}
14 |
15 | If you're not sure how to resolve this issue,
16 | feel free to contact us via the link in the bottom right corner.
17 |
18 | {% else %}
19 |
20 | We're not quite sure what went wrong.
21 | Please contact us via the link in the bottom right to resolve this issue.
22 |
23 | {% end %}
24 |
25 | {% endblock %}
26 | {% endblock %}
27 |
--------------------------------------------------------------------------------
/server/polychart/main/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/server/polychart/main/utils/secureStorage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import Padding
4 |
5 | from Crypto.Cipher import AES
6 | from base64 import urlsafe_b64encode, urlsafe_b64decode
7 | from django.conf import settings
8 | from os import urandom
9 | from pbkdf2 import PBKDF2
10 |
11 | def getEncryptionKey(password, salt):
12 | assert password
13 | assert salt
14 |
15 | saltbytes = urlsafe_b64decode(salt.encode('utf-8'))
16 | hashThing = PBKDF2(password, saltbytes)
17 | return hashThing.read(32)
18 |
19 | DEFAULT_KEY = getEncryptionKey(settings.SECRET_KEY, 'ziIwStZZ')
20 |
21 | def encrypt(key, plaintext):
22 | assert key
23 |
24 | if plaintext == "":
25 | return ""
26 |
27 | aes = AES.new(key, AES.MODE_CBC, b"Polychart AES IV")
28 | padded = Padding.appendPadding(plaintext)
29 | cipherbytes = aes.encrypt(padded)
30 | return urlsafe_b64encode(cipherbytes)
31 |
32 | def decrypt(key, ciphertext):
33 | assert key
34 |
35 | if ciphertext == "":
36 | return ""
37 |
38 | aes = AES.new(key, AES.MODE_CBC, b"Polychart AES IV")
39 | cipherbytes = urlsafe_b64decode(ciphertext.encode('utf-8'))
40 | padded = aes.decrypt(cipherbytes)
41 | return Padding.removePadding(padded)
42 |
43 | def generateSalt():
44 | return urlsafe_b64encode(urandom(8))
45 |
--------------------------------------------------------------------------------
/server/polychart/main/utils/spec.py:
--------------------------------------------------------------------------------
1 | """
2 | Functions related to processing frontend spec objects.
3 | """
4 | import re
5 |
6 |
7 | def getDsInfo(spec):
8 | """
9 | Extracts the list of (tableName, dsKey) pairs from the clientside chart
10 | specification produced by the Dashboard Builder.
11 |
12 | Args:
13 | spec: A dictionary corresponding to the client side chart spec object. The
14 | spec object must have the field 'meta', whose value will be a dictionary
15 | with keys as column names and values as dictionaries that contain the
16 | desired information. For example:
17 |
18 | spec = { ...
19 | meta: { columnOne: { tableName: "Table_One", dsKey: "keyone" , ... }
20 | , columnTwo: { tableName: "Table_Two", dsKey: "keyone" , ...}
21 | ... }
22 | ... }
23 |
24 | Returns:
25 | A list of distinct pairs with tableName in the first entry and dsKey in the
26 | second. Both values will be strings.
27 | """
28 | result = []
29 | for _, val in spec['meta'].iteritems():
30 | pair = (val.get('tableName'), val.get('dsKey'))
31 | if pair[0] is None and pair[1] is None:
32 | continue
33 | elif pair not in result:
34 | result.append(pair)
35 | return result
36 |
--------------------------------------------------------------------------------
/server/polychart/main/utils/tools.py:
--------------------------------------------------------------------------------
1 | """
2 | A collection of very miscellaneous tools.
3 | """
4 | ### Filepath tools
5 | from base64 import urlsafe_b64encode
6 | import atexit
7 | import os
8 |
9 | # Ensure tmp directory exists
10 | if not os.path.exists('tmp'):
11 | os.mkdir('tmp')
12 |
13 | def getNewTempFilePath():
14 | path = os.getcwd() + '/tmp/' + urlsafe_b64encode(os.urandom(18))
15 | deleteOnExit(path)
16 | return path
17 |
18 | def deleteOnExit(path):
19 | def cleanup():
20 | try: os.remove(path)
21 | except: pass
22 | atexit.register(cleanup)
23 |
24 | ### Misc functions
25 | def randomCode():
26 | # 18 random bytes -- more than a UUID, and looks nicer in base 64
27 | return urlsafe_b64encode(os.urandom(18))
28 |
--------------------------------------------------------------------------------
/server/polychart/main/views/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polychart/builder/a352ccd62a145c7379e954253c722e9704178f20/server/polychart/main/views/__init__.py
--------------------------------------------------------------------------------
/server/polychart/main/views/demo.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers to deal with the demo.
3 | """
4 | import json
5 |
6 | from django.shortcuts import render
7 | from django.views.decorators.http import require_GET, require_http_methods
8 |
9 | from polychart.main.models import TutorialCompletion
10 |
11 | @require_GET
12 | def demoShow(request):
13 | """Django handler to show the demo dashboard."""
14 | # pylint: disable = E1101
15 | # Pylint does not recognize Django model attributes.
16 | if request.user.is_authenticated():
17 | showTutorial = not TutorialCompletion.objects.filter(user=request.user, type='nux').exists()
18 | else:
19 | showTutorial = True
20 |
21 | tutorialOverride = request.GET.get('showTutorial', None)
22 | if tutorialOverride == 'yes':
23 | showTutorial = True
24 | elif tutorialOverride == 'no':
25 | showTutorial = False
26 |
27 | return render( request
28 | , 'demo.tmpl'
29 | , dictionary = { 'showTutorial': showTutorial })
30 |
31 |
--------------------------------------------------------------------------------
/server/polychart/main/views/home.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers to deal with the Dashboard Builder home.
3 | """
4 | from django.contrib.auth.decorators import login_required
5 | from django.shortcuts import render
6 | from django.views.decorators.http import require_GET
7 |
8 | from polychart.main.models import DataSource, Dashboard, TutorialCompletion
9 |
10 | @require_GET
11 | @login_required
12 | def show(request):
13 | """Django handler to render home."""
14 | # pylint: disable = E1101
15 | # Pylint does not notice Django model attributes
16 | newDataSourceKey = request.GET.get('newDataSourceKey', None)
17 |
18 | dataSources = DataSource.objects.filter(user=request.user)
19 | dashboards = Dashboard.objects.filter(user=request.user)
20 | tutorialCompleted = TutorialCompletion.objects.filter(user=request.user, type='nux').exists()
21 |
22 | return render( request
23 | , 'home.tmpl'
24 | , dictionary = { 'dataSources': dataSources
25 | , 'dashboards': dashboards
26 | , 'tutorialCompleted': tutorialCompleted
27 | , 'newDataSourceKey': newDataSourceKey })
28 |
--------------------------------------------------------------------------------
/server/polychart/main/views/tutorial.py:
--------------------------------------------------------------------------------
1 | """
2 | Django handlers related to the tutorial.
3 | """
4 | import json
5 |
6 | from django.contrib.auth.decorators import login_required
7 | from django.views.decorators.http import require_POST
8 |
9 | from polychart.main.models import TutorialCompletion
10 | from polychart.utils import jsonResponse
11 |
12 | @require_POST
13 | @login_required
14 | def tutorialComplete(request):
15 | """Django handler for completion of the tutorial."""
16 | body = json.loads(request.body)
17 |
18 | TutorialCompletion(
19 | user=request.user,
20 | type=body['type']
21 | ).save()
22 |
23 | return jsonResponse({})
24 |
--------------------------------------------------------------------------------
/server/polychart/urls.py:
--------------------------------------------------------------------------------
1 | """
2 | Defines how Django should route HTTP requests to views.
3 | Some applications have their own routing files.
4 | See `polychart.*.urls`.
5 | """
6 |
7 | import polychart.main.urls as MAIN_URLS
8 |
9 | try:
10 | import polychart.site.urls as SITE_URLS
11 | except ImportError:
12 | SITE_URLS = None
13 |
14 | try:
15 | import polychart.jsSite.urls as JS_SITE_URLS
16 | except ImportError:
17 | JS_SITE_URLS = None
18 |
19 | try:
20 | import polychart.analytics.urls as ANALYTICS_URLS
21 | except ImportError:
22 | ANALYTICS_URLS = None
23 |
24 | from django.conf.urls import include, patterns, url
25 | from polychart.utils import permanentRedirect
26 |
27 | def _buildPatternList():
28 | urls = [
29 | # Main website
30 | url(r'^', include(SITE_URLS)) if SITE_URLS else None,
31 |
32 | # Main app
33 | url(r'^', include(MAIN_URLS)),
34 |
35 | # Polychart.js website
36 | url(r'^js/', include(JS_SITE_URLS)) if JS_SITE_URLS else None,
37 |
38 | # Analytics
39 | url('^', include(ANALYTICS_URLS)) if ANALYTICS_URLS else None,
40 |
41 | # Deprecated URLs
42 | url(r'^beta$', permanentRedirect('/signup')),
43 | url(r'^devkit.*$', permanentRedirect('/')),
44 | url(r'^embed/.*$', permanentRedirect('/')),
45 | ]
46 |
47 | # Filter out None
48 | urls = [x for x in urls if x]
49 |
50 | return patterns('polychart.main.views', *urls)
51 |
52 | urlpatterns = _buildPatternList()
53 |
--------------------------------------------------------------------------------
/server/polychart/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for polychart project.
3 |
4 | This module contains the WSGI application used by Django's development server
5 | and any production WSGI deployments. It should expose a module-level variable
6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7 | this application via the ``WSGI_APPLICATION`` setting.
8 |
9 | Usually you will have the standard Django WSGI application here, but it also
10 | might make sense to replace the whole Django WSGI application with a custom one
11 | that later delegates to the Django one. For example, you could introduce WSGI
12 | middleware here, or combine a Django application with an application of another
13 | framework.
14 | """
15 |
16 | # This application object is used by any WSGI server configured to use this
17 | # file. This includes Django's development server, if the WSGI_APPLICATION
18 | # setting points here.
19 | from django.core.wsgi import get_wsgi_application
20 | application = get_wsgi_application()
21 |
22 | # Apply WSGI middleware here.
23 | # from helloworld.wsgi import HelloWorldApplication
24 | # application = HelloWorldApplication(application)
25 |
--------------------------------------------------------------------------------
/server/polychartQuery/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Provide a public interface for constructing new SQL-esque data sources.
3 | """
4 | from polychartQuery.sql import MySqlConn, InfobrightConn, PostgreSqlConn
5 |
6 | __all__ = []
7 |
8 | def openConnection(type, *args, **kwargs):
9 | if type == 'mysql':
10 | return MySqlConn(*args, **kwargs)
11 |
12 | elif type == 'infobright':
13 | return InfobrightConn(*args, **kwargs)
14 |
15 | elif type == 'postgresql':
16 | return PostgreSqlConn(*args, **kwargs)
17 |
--------------------------------------------------------------------------------
/server/polychartQuery/csv/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from connection import Conn as Connection
4 |
--------------------------------------------------------------------------------
/server/polychartQuery/csv/connection.py:
--------------------------------------------------------------------------------
1 | """
2 | Module defining a dummy CSV connection.
3 | """
4 | from polychartQuery.abstract import DataSourceConnection
5 |
6 | class Conn(DataSourceConnection):
7 | """
8 | Dummy class (for now)
9 | """
10 | def __init__(self, *args, **kwargs):
11 | super(Conn, self).__init__(*args, **kwargs)
12 | pass
13 |
--------------------------------------------------------------------------------
/server/polychartQuery/googleAnalytics/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from query import GAQuery as Query
4 | from connection import GAConn as Connection
5 |
--------------------------------------------------------------------------------
/server/polychartQuery/sql/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from polychartQuery.sql.query import SqlQuery, PostgreSqlQuery
4 | from polychartQuery.sql.connection import MySqlConn, PostgreSqlConn, InfobrightConn
5 |
--------------------------------------------------------------------------------
/src/poly/README.md:
--------------------------------------------------------------------------------
1 | This directory contains the frontend source files for the Polychart Dashboard
2 | Builder. The templates and Coffeescript files within this directory implement the
3 | `home` view for dashboards.
4 |
5 | `main`
6 | ------
7 | This directory contains the main source code for the Dashboard builder. Look
8 | within for more information.
9 |
10 | `common`
11 | --------
12 | Here, internal libraries and shared styles are contained. The `events.coffee`
13 | file implements the internal event bus for Polychart; the `serverApi.coffee` file
14 | defines a uniform internal method for communicating with a remote server; all
15 | other files are style files that are used in this application and other internal
16 | applications.
17 |
18 | `demoData`
19 | ----------
20 | Data for the Dashboard Builder Demo is contained.
21 |
22 | `examples`
23 | ----------
24 | This directory contains example source files interacting with the dashboard
25 | builder.
26 |
--------------------------------------------------------------------------------
/src/poly/main/anim.coffee:
--------------------------------------------------------------------------------
1 | ###
2 | # Define a basic animations library; useful for loading and transitions.
3 | ###
4 | ANIMATIONS =
5 | loading:
6 | interval: 200,
7 | frames: [
8 | 'anim_loading_0.svg',
9 | 'anim_loading_1.svg',
10 | 'anim_loading_2.svg'
11 | ]
12 |
13 | class Animation
14 | constructor: (animName, container) ->
15 | anim = ANIMATIONS[animName]
16 | if !anim
17 | throw "Animation " + animName + " does not exist!"
18 |
19 | @div = div = $("
")
20 | div.addClass("anim")
21 | div.addClass(animName)
22 | $(container).append(div)
23 |
24 | _.defer () ->
25 | div.css
26 | width: div.height()
27 | marginLeft: -div.height()/2
28 | marginTop: -div.height()/2
29 |
30 | images = _.map anim.frames, (src) =>
31 | img = new Image()
32 | img.src = '/static/main/images/' + src
33 | img
34 |
35 | curFrame = 0
36 | advFrame = () ->
37 | div.css 'background-image', 'url(' + images[curFrame].src + ')'
38 | curFrame = (curFrame + 1) % images.length
39 | @interval = setInterval advFrame, anim.interval
40 |
41 | remove: () =>
42 | @div.remove()
43 | clearInterval @interval
44 |
45 | stopOnImage: (imgSrc) =>
46 | @div.css 'background-image', 'url(' + imgSrc + ')'
47 | clearInterval @interval
48 |
49 | module.exports = Animation
50 |
--------------------------------------------------------------------------------
/src/poly/main/chart/advanced.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
9 |
27 |
28 |
37 |
--------------------------------------------------------------------------------
/src/poly/main/chart/aes/base.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
22 |
--------------------------------------------------------------------------------
/src/poly/main/chart/aes/color.coffee:
--------------------------------------------------------------------------------
1 | Aesthetic = require('poly/main/chart/aes/base')
2 |
3 | class ColorAesthetic extends Aesthetic
4 | template: 'tmpl-aesthetic-color'
5 | constructor: (@aes, @name, @parent) ->
6 | super(@aes, @name, @parent)
7 | @selected = 'steelblue'
8 | @defaultValue = 'steelblue'
9 | @value = ko.observable(@defaultValue)
10 | @value.subscribe @render
11 | onMetricDiscard: (event, metricItem) =>
12 | @metric(null)
13 | @render()
14 | @afterRender(@dom)
15 | afterRender: (dom) =>
16 | @dom = dom
17 | simpleColor = $('.selector', dom)
18 | simpleColor.attr 'value', @value()
19 | simpleColor.simpleColor(
20 | cellWidth: 15
21 | cellHeight: 15
22 | boxWidth: 50
23 | boxHeight: 15
24 | border: 0
25 | columns: 9
26 | )
27 | simpleColor.bind 'change', (evt) =>
28 | @value evt.target.value
29 | $(".simpleColorContainer", dom).click () => false
30 | _setConstant: (spec) =>
31 | if spec.const
32 | @value(spec.const)
33 | _getConstant: () =>
34 | const: @value()
35 |
36 | module.exports = ColorAesthetic
37 |
--------------------------------------------------------------------------------
/src/poly/main/chart/aes/color.tmpl:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/src/poly/main/chart/aes/size.coffee:
--------------------------------------------------------------------------------
1 | Aesthetic = require('poly/main/chart/aes/base')
2 |
3 | class SizeAesthetic extends Aesthetic
4 | template: 'tmpl-aesthetic-size'
5 | constructor: (@aes, @name, @parent) ->
6 | super(@aes, @name, @parent)
7 | @selected = 1
8 | @defaultValue = 2
9 | @value = ko.observable(@defaultValue)
10 | @value.subscribe @render
11 | onMetricDiscard: (event, metricItem) =>
12 | @metric(null)
13 | @render()
14 | @afterRender(@dom)
15 | afterRender: (dom) =>
16 | @dom = dom
17 | slider = $('.selector', dom)
18 | slider.slider(
19 | max: 10
20 | min: 1
21 | step: 1
22 | value: @value()
23 | )
24 | slider.bind 'slidechange', (evt, ui) =>
25 | @value(ui.value)
26 | _setConstant: (spec) =>
27 | if spec.const
28 | @value(spec.const)
29 | _getConstant: () =>
30 | const: @value()
31 |
32 | module.exports = SizeAesthetic
33 |
--------------------------------------------------------------------------------
/src/poly/main/chart/aes/size.tmpl:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/src/poly/main/chart/chartbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
39 |
40 |
43 |
--------------------------------------------------------------------------------
/src/poly/main/chart/layer.tmpl:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/src/poly/main/dash/aes.tmpl:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/src/poly/main/dash/dash.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/poly/main/dash/dashboard.coffee:
--------------------------------------------------------------------------------
1 | QuickAddView = require('poly/main/dash/quickadd')
2 | WorkspaceView = require('poly/main/dash/workspace')
3 |
4 | class DashboardView
5 | constructor: (title, tableMetaData) ->
6 | @workspaceView = new WorkspaceView(title, tableMetaData)
7 | @quickaddView = new QuickAddView(tableMetaData)
8 |
9 | serialize: () =>
10 | @workspaceView.serialize()
11 |
12 | initialize: (initial) => @workspaceView.initialize(initial)
13 |
14 | module.exports = DashboardView
15 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/chart.tmpl:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/comment.coffee:
--------------------------------------------------------------------------------
1 | TextItem = require('poly/main/dash/item/text')
2 |
3 | CONST = require('poly/main/const')
4 |
5 | class CommentItem extends TextItem
6 | constructor: (@author, value, position={}) ->
7 | @author or= PAGE_VARIABLE?.USERNAME ? ''
8 | position.width or= 5
9 | position.height or= 7
10 |
11 | @minWidth = 5
12 | @minHeight = 5
13 |
14 | @templateName = 'tmpl-comment-item' unless @templateName
15 | super(value, position, 'Write a comment here...')
16 |
17 | @shiftedZIndex = ko.computed =>
18 | 1000000 + @zIndex()
19 |
20 | serialize: (s={}) =>
21 | s.author = @author
22 | s.itemType = "CommentItem"
23 | super s
24 |
25 | deserialize: (s) =>
26 | @author = s.author if s.author
27 | super(s)
28 |
29 | module.exports = CommentItem
30 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/comment.tmpl:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/numeral.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/pivottable.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/polyjs.coffee:
--------------------------------------------------------------------------------
1 | Animation = require('poly/main/anim')
2 | DashItem = require('poly/main/dash/item/base')
3 | Events = require('poly/main/events')
4 |
5 | CONST = require('poly/main/const')
6 | TOAST = require('poly/main/error/toast')
7 |
8 | PADDING = 10 # extra padding for chart view outside of chart
9 |
10 | class PolyJSItem extends DashItem
11 | constructor: (@spec=null, position) ->
12 | @redraw = _.debounce(@_redraw, 300, true)
13 | @templateName = 'tmpl-chart-item' unless @templateName
14 | super(position)
15 |
16 | init: (dom) =>
17 | super(dom)
18 | @itemdom = $('.chart-inner, .inner', dom)
19 | @spec.dom = @itemdom[0]
20 | @_initSpec()
21 | Events.error.polyjs.data.on (event) =>
22 | @loadingAnim.stopOnImage("/static/main/images/broken_chart.svg")
23 | @onResize()
24 |
25 | _initSpec: () => Error("Not implemented")
26 |
27 | onResize: =>
28 | if @itemdom then @redraw()
29 |
30 | _redraw: () =>
31 | if !@itemdom
32 | # init() has to be called first so that @spec has a DOM element
33 | throw "Can't make chart before init() is called!"
34 |
35 | @spec.width = @itemdom.width() - PADDING
36 | @spec.height = @itemdom.height() - PADDING
37 | prepare =
38 | if @isViewer()
39 | ->
40 | else
41 | () => @itemdom.empty()
42 | @_renderPolyJSItem(@spec, @loaded, prepare)
43 |
44 | setSpec: (@spec, isDeserializing=false) =>
45 | unless isDeserializing
46 | Events.model.dashboarditem.update.trigger()
47 |
48 | deserialize: (s) =>
49 | @setSpec(s.spec, true)
50 | super(s)
51 |
52 | module.exports = PolyJSItem
53 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/text.coffee:
--------------------------------------------------------------------------------
1 | DashItem = require('poly/main/dash/item/base')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class TextItem extends DashItem
7 | constructor: (@textContent, position={}, @defaultText='Type here...') ->
8 | unless ko.isObservable(@textContent)
9 | @textContent = ko.observable @textContent
10 |
11 | @templateName = 'tmpl-text-item' unless @templateName
12 | super(position)
13 |
14 | init: (@dom) =>
15 | super(dom)
16 | @loaded()
17 |
18 | onEditAreaBlur: ->
19 | Events.model.dashboarditem.update.trigger()
20 |
21 | return true
22 |
23 | serialize: (s={}) =>
24 | s.itemType = s.itemType ? 'TextItem'
25 | s.textContent = @textContent()
26 | super s
27 |
28 | deserialize: (s) =>
29 | @textContent(s.textContent) if s.textContent
30 | super(s)
31 |
32 | module.exports = TextItem
33 |
--------------------------------------------------------------------------------
/src/poly/main/dash/item/text.tmpl:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/src/poly/main/dash/workspace.tmpl:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/src/poly/main/data/data.tmpl:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/base.coffee:
--------------------------------------------------------------------------------
1 | class MetricView
2 | constructor: (@columnInfo) ->
3 | {@name, @tableName, @gaType} = @columnInfo
4 | @type = @columnInfo.meta.type
5 | @gaType = @columnInfo.gaType
6 | @originalFormula = @columnInfo.formula
7 | @formula =
8 | if @originalFormula?
9 | @originalFormula
10 | else if @name == 'count(*)'
11 | @name
12 | else
13 | "[#{@tableName}.#{@name}]"
14 | @extraCSS =
15 | if @columnInfo.formula
16 | 'derived-var'
17 | else
18 | @gaType
19 |
20 | fullFormula: (tableMetaData, unbracket=false) =>
21 | @columnInfo.getFormula(tableMetaData, unbracket)
22 |
23 | fullMeta: () -> @columnInfo.meta
24 |
25 | module.exports = MetricView
26 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/base.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/dropdown.coffee:
--------------------------------------------------------------------------------
1 | Events = require('poly/main/events')
2 | MetricView = require('poly/main/data/metric/base')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class DropdownMetricView extends MetricView
7 | constructor: (columnInfo, @label, @dropdownTemplate, @dropdownData, @dropdownAfterRender) ->
8 | @toggleDropdown = _.throttle @_toggleDropdown # ..or clicks gets registerd 2x
9 | @dropdownShowing = false
10 | super(columnInfo)
11 |
12 | _toggleDropdown: =>
13 | if @name isnt 'count(*)'
14 | if @dropdownShowing
15 | Events.ui.dropdown.hide.trigger()
16 | else
17 | Events.ui.dropdown.show.trigger {
18 | templateName: @dropdownTemplate
19 | data: @dropdownData
20 | targetDom: @dom
21 | onRemove: @setInactive
22 | afterRender: @dropdownAfterRender
23 | info: {name: @label, value: @name}
24 | }
25 |
26 | setInactive: =>
27 | @dropdownShowing = false
28 | if @dom
29 | @dom.removeClass 'dropdown-active'
30 | @dom.draggable 'enable'
31 |
32 | close: =>
33 | Events.ui.dropdown.hide.trigger()
34 |
35 | attachDropdown: (dom) =>
36 | @dom = $(dom)
37 | Events.ui.dropdown.shown.onElem @dom, =>
38 | @dropdownShowing = true
39 | @dom.addClass 'dropdown-active'
40 | @dom.draggable 'disable'
41 | Events.ui.dropdown.hidden.onElem @dom, @setInactive
42 |
43 | module.exports = DropdownMetricView
44 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/dropdown.tmpl:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/facet.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class FacetMetricView extends AttachedMetricView
7 | constructor: (columnInfo) ->
8 | updateFn = () => Events.ui.chart.render.trigger()
9 | options = () -> CONST.facets
10 | attachedMetrics = () -> []
11 | @removeText = "Remove \"" + columnInfo.name + "\" from facet"
12 | super columnInfo, @aes, updateFn, options, attachedMetrics
13 |
14 | module.exports = FacetMetricView
15 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/layer.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 | Events = require('poly/main/events')
3 |
4 | CONST = require('poly/main/const')
5 |
6 | class LayerMetricView extends AttachedMetricView
7 | constructor: (columnInfo, @options, @layer, @aesName, defaults) ->
8 | updateFn = () => Events.ui.chart.render.trigger()
9 | attachedMetrics = @layer.attachedMetrics
10 | super columnInfo, @aesName, updateFn, @options, attachedMetrics, defaults
11 |
12 | module.exports = LayerMetricView
13 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/quickadd.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 |
3 | class QuickAddMetricView extends AttachedMetricView
4 | constructor: (columnInfo, @options, @aes) ->
5 | updateFn = () ->
6 | attachedMetrics = () -> []
7 | @removeText = "Remove \"" + columnInfo.name + "\" from " + @aes
8 | super columnInfo, @aes, updateFn, @options, attachedMetrics
9 |
10 | module.exports = QuickAddMetricView
11 |
--------------------------------------------------------------------------------
/src/poly/main/data/metric/quickaddtable.coffee:
--------------------------------------------------------------------------------
1 | AttachedMetricView = require('poly/main/data/metric/attached')
2 |
3 | class QuickAddTableMetricView extends AttachedMetricView
4 | constructor: (columnInfo, @options, @aes, attachedMetrics) ->
5 | updateFn = () ->
6 | @removeText = "Remove \"" + columnInfo.name + "\" from " + @aes
7 | super columnInfo, @aes, updateFn, @options, attachedMetrics
8 |
9 | module.exports = QuickAddTableMetricView
10 |
--------------------------------------------------------------------------------
/src/poly/main/data/table.tmpl:
--------------------------------------------------------------------------------
1 |
21 |
22 |
--------------------------------------------------------------------------------
/src/poly/main/error/toast.coffee:
--------------------------------------------------------------------------------
1 | raise = (text) ->
2 | $().toastmessage('showErrorToast', text)
3 |
4 | module.exports = {
5 | raise
6 | }
7 |
--------------------------------------------------------------------------------
/src/poly/main/header.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
35 |
--------------------------------------------------------------------------------
/src/poly/main/init.coffee:
--------------------------------------------------------------------------------
1 | # Setup necessary prior to Polychart being used
2 |
3 | # load all the knockout templates
4 | require('poly/main/templates')
5 |
6 | # initiate custom KO bindings
7 | require('poly/main/bindings').init()
8 |
--------------------------------------------------------------------------------
/src/poly/main/main/builder.coffee:
--------------------------------------------------------------------------------
1 | # Top level view entry point - abstract classes
2 | # Code that is shared for both chart and dashboard builder
3 |
4 | Events = require('poly/main/events')
5 | DataView = require('poly/main/data/dataView')
6 | HeaderView = require('poly/main/header')
7 | OverlayView = require('poly/main/overlay')
8 | ShareView = require('poly/main/share')
9 |
10 | class AbstractBuilderEntryPoint
11 | constructor: (@params) ->
12 | Events.registerDefaultListeners()
13 |
14 | {@dom, @dataCollection, @exportingEnabled} = params
15 |
16 | # TODO Support multiple data sources on client
17 | if @dataCollection
18 | unless _.isArray(@dataCollection)
19 | @dataCollection = [@dataCollection]
20 | @dataSource = poly.data @dataCollection[0]
21 | @dataView = new DataView(@dataSource)
22 | @overlayView = new OverlayView()
23 | else
24 | throw new Error('No data collection provided!')
25 |
26 | @hasHeader = params.header ? false
27 | @headerView = new HeaderView(params.isDemo)
28 | @shareView = new ShareView()
29 |
30 | if params.width is 'fill'
31 | $(@dom).width('100%')
32 | if _.isNumber(params.width)
33 | $(@dom).width(params.width)
34 | if params.height is 'fill'
35 | $(@dom).height('100%')
36 | if _.isNumber(params.height)
37 | $(@dom).height(params.height)
38 | if params.width is 'fill' and params.height is 'fill'
39 | $(@dom).addClass('fill')
40 |
41 | initialize: () =>
42 | @dataView.initialize()
43 |
44 | module.exports = AbstractBuilderEntryPoint
45 |
--------------------------------------------------------------------------------
/src/poly/main/main/chartbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/src/poly/main/main/chartviewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view for viewing a particular chart
2 | AbstractViewerEntryPoint = require('poly/main/main/viewer')
3 |
4 | class ChartViewerMainView extends AbstractViewerEntryPoint
5 | constructor: (@params) ->
6 | super(@params)
7 | @spec = params.initial ? {}
8 | @tableMetaData = @dataView.getTableMetaData()
9 |
10 | init: (dom) =>
11 | initialCols = @spec.newcols ? []
12 | @dataView.initialize initialCols, () =>
13 | # instead of using spec.layer, use spec.layers
14 | if @spec.layer
15 | @spec.layers = [@spec.layer]
16 | delete @spec.layer
17 | # generate the polyJS object for each layer (given tableName)
18 | for layer in @spec.layers
19 | if not layer.data
20 | tableName = layer.tableName
21 | if not tableName? and layer.meta and m = _.toArray(layer.meta)[0]
22 | tableName = m.tableName
23 | layer.data = @tableMetaData.polyJsObjectFor {tableName}
24 | @spec.width ?= @params.width
25 | @spec.height ?= @params.height
26 | @spec.dom = dom[0]
27 | polyjs.chart(@spec)
28 |
29 |
30 | module.exports = ChartViewerMainView
31 |
--------------------------------------------------------------------------------
/src/poly/main/main/chartviewer.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/poly/main/main/dashviewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view for viewing a particular chart
2 | AbstractViewerEntryPoint = require('poly/main/main/viewer')
3 | WorkspaceView = require('poly/main/dash/workspace')
4 |
5 | class DashViewerMainView extends AbstractViewerEntryPoint
6 | constructor: (@params) ->
7 | super(@params)
8 |
9 | tableMetaData = @dataView.getTableMetaData()
10 | @workspaceView = new WorkspaceView(@params.name, tableMetaData, true)
11 | @initialize()
12 |
13 | initialize: () ->
14 | initial = @params.initial ? []
15 | if _.isArray(@params.initial)
16 | initialItems = @params.initial
17 | initialCols = []
18 | else if _.isObject(@params.initial)
19 | initialItems = @params.initial.items ? []
20 | initialCols = @params.initial.newcols ? []
21 |
22 | @dataView.initialize initialCols, () => @workspaceView.initialize(initialItems)
23 |
24 | module.exports = DashViewerMainView
25 |
--------------------------------------------------------------------------------
/src/poly/main/main/dashviewer.tmpl:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/poly/main/main/viewer.coffee:
--------------------------------------------------------------------------------
1 | # Top level view entry point - abstract classes
2 | # Code that is shared for both chart and dashboard Viewer
3 |
4 | DataView = require('poly/main/data/dataView')
5 | Events = require('poly/main/events')
6 |
7 | class AbstractViewerEntryPoint
8 | constructor: (@params) ->
9 | Events.registerDefaultListeners()
10 |
11 | {@dom, @dataCollection} = params
12 |
13 | # TODO Support multiple data sources on client
14 | if @dataCollection
15 | unless _.isArray(@dataCollection)
16 | @dataCollection = [@dataCollection]
17 | # shared "views"
18 | @dataSource = poly.data @dataCollection[0]
19 | else
20 | throw new Error('No data collection provided!')
21 |
22 | @dataView = new DataView(@dataSource)
23 |
24 | initialize: () =>
25 | @dataView.initialize()
26 |
27 | module.exports = AbstractViewerEntryPoint
28 |
--------------------------------------------------------------------------------
/src/poly/main/numeral/numeralbuilder.tmpl:
--------------------------------------------------------------------------------
1 |
25 |
26 |
29 |
--------------------------------------------------------------------------------
/src/poly/main/share.coffee:
--------------------------------------------------------------------------------
1 | ###
2 | # Hook up events for the share panel.
3 | ###
4 | CONST = require('poly/main/const')
5 | Events = require('poly/main/events')
6 | serverApi = require('poly/common/serverApi')
7 |
8 | class ShareView
9 | constructor: () ->
10 | @defaultPanelRight = -250
11 | @panelRight = ko.observable(@defaultPanelRight)
12 | Events.nav.sharepanel.open.on @open
13 | Events.nav.sharepanel.close.on @close
14 |
15 | open: () =>
16 | @panelRight(0)
17 |
18 | close: () =>
19 | @panelRight(@defaultPanelRight)
20 |
21 | exportPDF: ->
22 | Events.export.pdf.click.trigger callback: @_export('pdf')
23 |
24 | exportPNG: ->
25 | Events.export.png.click.trigger callback: @_export('png')
26 |
27 | exportSVG: ->
28 | Events.export.svg.click.trigger callback: @_export('svg')
29 |
30 | _export: (type) -> (serial) ->
31 | serverApi.sendPost(
32 | "/dashboard/export/code"
33 | , {serial: serial, exportType: type}
34 | , (err, result) ->
35 | if err
36 | console.error err
37 | TOAST.raise 'Error exporting dashboard.'
38 | return
39 |
40 | window.location = "/api/dashboard/export/" + encodeURIComponent(result.code)
41 | )
42 |
43 | module.exports = ShareView
44 |
--------------------------------------------------------------------------------
/src/poly/main/share.tmpl:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/src/poly/main/table/aesGroup.tmpl:
--------------------------------------------------------------------------------
1 |
33 |
34 |
--------------------------------------------------------------------------------
/src/poly/main/table/table.less:
--------------------------------------------------------------------------------
1 | .tablebuilder-table {
2 | height: 100%;
3 | overflow: scroll;
4 | padding: 2px;
5 |
6 | text-align: center;
7 | background-color: @white;
8 | }
9 |
--------------------------------------------------------------------------------
/src/poly/main/table/tablebuilder.tmpl:
--------------------------------------------------------------------------------
1 |
32 |
33 |
36 |
--------------------------------------------------------------------------------
/src/poly/signup.coffee:
--------------------------------------------------------------------------------
1 | Events = require('poly/main/events')
2 |
3 | init = () ->
4 | Events.signup.page.view.trigger()
5 | eulaClickTrap '#start', '#realsubmit', '#eula', Events.signup.eula.error
6 | Events.signup.form.submit.trackForm $('#realsubmit')
7 | $('input').on 'keypress keydown', _.once ->
8 | Events.signup.form.interact.trigger()
9 |
10 | eulaClickTrap = (submitBtn, hiddenBtn, eula, errorEvt) ->
11 | $(submitBtn).on 'click', (e) ->
12 | e.stopPropagation()
13 | if $(eula).prop 'checked'
14 | $(hiddenBtn).click()
15 | else
16 | if errorEvt then errorEvt.trigger()
17 | alert 'You must first read and accept the Terms and Conditions.'
18 |
19 | module.exports = {
20 | init
21 | }
22 |
--------------------------------------------------------------------------------
/src/poly/verifyPendingDs.coffee:
--------------------------------------------------------------------------------
1 | serverApi = require('poly/common/serverApi')
2 |
3 | load = (dsParams) ->
4 | serverApi.sendPost '/data-source/create', dsParams, (err, response) ->
5 | if err
6 | console.error err
7 | else
8 | window.location.href = '/home'
9 |
10 | module.exports = {run}
11 |
--------------------------------------------------------------------------------
/system_requirements:
--------------------------------------------------------------------------------
1 | # Package names on Ubuntu.
2 | # Don't forget to also update the Chef recipe.
3 |
4 | libffi-dev
5 | libmysqlclient-dev
6 | libpq-dev
7 | libxml2-dev
8 | libxslt-dev
9 | mysql-client-core-5.5
10 | mysql-server
11 | python-setuptools
12 | python-virtualenv
13 | python2.7-dev
14 | socat
15 |
--------------------------------------------------------------------------------