diff --git a/dashed/__init__.py b/dashed/__init__.py
index 83e6cce5b47e4..6dfc8b2aa3ead 100644
--- a/dashed/__init__.py
+++ b/dashed/__init__.py
@@ -28,7 +28,7 @@
class MyIndexView(IndexView):
@expose('/')
def index(self):
- return redirect('/dashed/featured')
+ return redirect('/dashed/welcome')
appbuilder = AppBuilder(
app, db.session,
diff --git a/dashed/assets/javascripts/featured.js b/dashed/assets/javascripts/featured.js
deleted file mode 100644
index 2b8617f3a807a..0000000000000
--- a/dashed/assets/javascripts/featured.js
+++ /dev/null
@@ -1,19 +0,0 @@
-var $ = window.$ = require('jquery');
-var jQuery = window.jQuery = $;
-require('./modules/dashed.js');
-
-require('bootstrap');
-require('datatables');
-require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css');
-
-$(document).ready(function () {
- $('#dataset-table').DataTable({
- bPaginate: false,
- order: [
- [1, "asc"]
- ]
- });
- $('#dataset-table_info').remove();
- //$('input[type=search]').addClass('form-control'); # TODO get search box to look nice
- $('#dataset-table').show();
-});
diff --git a/dashed/assets/javascripts/welcome.js b/dashed/assets/javascripts/welcome.js
new file mode 100644
index 0000000000000..898e0803d07fe
--- /dev/null
+++ b/dashed/assets/javascripts/welcome.js
@@ -0,0 +1,53 @@
+var $ = window.$ = require('jquery');
+var jQuery = window.jQuery = $;
+var px = require('./modules/dashed.js');
+
+require('../stylesheets/dashed.css');
+require('../stylesheets/welcome.css');
+
+require('bootstrap');
+require('datatables');
+require('d3');
+
+require('../node_modules/cal-heatmap/cal-heatmap.css');
+var CalHeatMap = require('cal-heatmap');
+
+
+
+function modelViewTable(selector, modelEndpoint, ordering) {
+ // Builds a dataTable from a flask appbuilder api endpoint
+ $.getJSON(modelEndpoint + '/api/read', function (data) {
+ var tableData = jQuery.map(data.result, function(el, i) {
+ var row = $.map(data.list_columns, function(col, i) {
+ return el[col];
+ });
+ return [row];
+ });
+ var cols = jQuery.map(data.list_columns, function(col, i) {
+ return { "sTitle": data.label_columns[col] }
+ });
+ $(selector).DataTable({
+ aaData: tableData,
+ aoColumns: cols,
+ bPaginate: false,
+ order: ordering,
+ searching: false
+ });
+ $('[data-toggle="tooltip"]').tooltip({ container: 'body' });
+ });
+}
+
+$(document).ready(function () {
+ var cal = new CalHeatMap();
+ cal.init({
+ start: new Date().setFullYear(new Date().getFullYear() - 1),
+ range: 13,
+ data: '/dashed/activity_per_day',
+ domain : "month",
+ subDomain : "day",
+ itemName: "action",
+ tooltip: true
+ });
+ modelViewTable('#dash_table', '/dashboardmodelviewasync');
+ modelViewTable('#slice_table', '/sliceasync');
+});
diff --git a/dashed/assets/package.json b/dashed/assets/package.json
index 49b361136349b..4017399df200b 100644
--- a/dashed/assets/package.json
+++ b/dashed/assets/package.json
@@ -43,6 +43,7 @@
"bootstrap-datepicker": "^1.6.0",
"bootstrap-toggle": "^2.2.1",
"brace": "^0.7.0",
+ "cal-heatmap": "3.5.4",
"css-loader": "^0.23.1",
"d3": "^3.5.14",
"d3-cloud": "^1.2.1",
diff --git a/dashed/assets/stylesheets/dashed.css b/dashed/assets/stylesheets/dashed.css
index dd8d5cc57894b..525e384ab9f46 100644
--- a/dashed/assets/stylesheets/dashed.css
+++ b/dashed/assets/stylesheets/dashed.css
@@ -68,6 +68,10 @@ form div {
}
.navbar-brand a {
color: white;
+ text-decoration: none;
+}
+.navbar-brand a:hover {
+ color: white;
}
.header span {
diff --git a/dashed/assets/stylesheets/welcome.css b/dashed/assets/stylesheets/welcome.css
new file mode 100644
index 0000000000000..d8760f694ad50
--- /dev/null
+++ b/dashed/assets/stylesheets/welcome.css
@@ -0,0 +1,21 @@
+.welcome .widget{
+ border-radius: 0;
+ border: 1px solid #ccc;
+ box-shadow: 2px 1px 5px -2px #aaa;
+ background-color: #fff;
+}
+
+.welcome .widget .header {
+ background-color: #f1f1f1;
+ text-align: center;
+}
+
+.welcome .widget>div {
+ padding: 3px;
+ overflow: auto;
+ max-height: 500px;
+}
+
+.table i {
+ padding-top: 6px;
+}
diff --git a/dashed/assets/webpack.config.js b/dashed/assets/webpack.config.js
index 465a04e1c8ac8..d9253f3d5c413 100644
--- a/dashed/assets/webpack.config.js
+++ b/dashed/assets/webpack.config.js
@@ -8,7 +8,7 @@ var config = {
'css-theme': APP_DIR + '/javascripts/css-theme.js',
dashboard: APP_DIR + '/javascripts/dashboard.js',
explore: APP_DIR + '/javascripts/explore.js',
- featured: APP_DIR + '/javascripts/featured.js',
+ welcome: APP_DIR + '/javascripts/welcome.js',
sql: APP_DIR + '/javascripts/sql.js',
standalone: APP_DIR + '/javascripts/standalone.js'
},
diff --git a/dashed/migrations/versions/1d2ddd543133_log_dt.py b/dashed/migrations/versions/1d2ddd543133_log_dt.py
new file mode 100644
index 0000000000000..a5f50f4f64c38
--- /dev/null
+++ b/dashed/migrations/versions/1d2ddd543133_log_dt.py
@@ -0,0 +1,22 @@
+"""log dt
+
+Revision ID: 1d2ddd543133
+Revises: d2424a248d63
+Create Date: 2016-03-25 14:35:44.642576
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '1d2ddd543133'
+down_revision = 'd2424a248d63'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.add_column('logs', sa.Column('dt', sa.Date(), nullable=True))
+
+
+def downgrade():
+ op.drop_column('logs', 'dt')
diff --git a/dashed/models.py b/dashed/models.py
index 878b5f99f3b93..e3b1c03ed3eba 100644
--- a/dashed/models.py
+++ b/dashed/models.py
@@ -2,7 +2,7 @@
from copy import deepcopy, copy
from collections import namedtuple
-from datetime import timedelta, datetime
+from datetime import timedelta, datetime, date
import functools
import json
import logging
@@ -15,12 +15,13 @@
from flask.ext.appbuilder import Model
from flask.ext.appbuilder.models.mixins import AuditMixin
import pandas as pd
+import humanize
from pydruid import client
from pydruid.utils.filters import Dimension, Filter
import sqlalchemy as sqla
from sqlalchemy import (
- Column, Integer, String, ForeignKey, Text, Boolean, DateTime,
+ Column, Integer, String, ForeignKey, Text, Boolean, DateTime, Date,
Table, create_engine, MetaData, desc, select, and_, func)
from sqlalchemy.engine import reflection
from sqlalchemy.orm import relationship
@@ -68,6 +69,22 @@ def created_by_(self):
def changed_by_(self):
return '{}'.format(self.changed_by or '')
+ @property
+ def modified(self):
+ s = humanize.naturaltime(datetime.now() - self.changed_on)
+ return "