Nuria has uploaded a new change for review.
https://gerrit.wikimedia.org/r/306980
Change subject: [WIP] Bookmark for tab/graph/date
......................................................................
[WIP] Bookmark for tab/graph/date
Need to throughly test state transactions
Bug: T143689
Change-Id: Ibb363ae923781478fdb390af19b80012fdf61a0a
---
M src/components/tabs-layout/tabs-layout.js
M src/components/visualizers/visualizer/visualizer.js
2 files changed, 123 insertions(+), 5 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/analytics/dashiki
refs/changes/80/306980/1
diff --git a/src/components/tabs-layout/tabs-layout.js
b/src/components/tabs-layout/tabs-layout.js
index 941a7b9..d4b9a5d 100644
--- a/src/components/tabs-layout/tabs-layout.js
+++ b/src/components/tabs-layout/tabs-layout.js
@@ -7,6 +7,7 @@
var ko = require('knockout'),
_ = require('lodash'),
templateMarkup = require('text!./tabs-layout.html'),
+ URI = require('uri/URI'),
configApi = require('apis.config');
require('twix');
@@ -21,17 +22,57 @@
this.selectedTab = ko.observable({});
this.selectedGraph = ko.observable(null);
+ /**
+ * Selects tab based on state on hash
+ * #graph=all-sites-by-os/tab=os-family-and-major-hierarchical-view
+ * for backwards compatibility this also works:
#all-sites-by-os/os-family-and-major-hierarchical-view
+ * but the second option doesn't interact well with other state
published from other components to url
+ **/
this.select = function (tab, graph) {
- location.hash = tab.id;
+ // parse state
+
+ //get tab, maintain older urls that users might have bookmarked
that do not contain the "graph="
+ var currentUri = new URI().normalizeHash();
+ // hash without '#'
+ var currentHash = currentUri.fragment();
+ // hash without visualizer state
+
+ // remove tab and graph from hash, that would be the outside state
we want
+ // to preserve
+
+ var tabSelected = /\/tab=(\w{1,}(-\w*){0,})/i;
+ var graphSelected = /\/graph=(\w{1,}(-\w*){0,})/i;
+
+ var tabState = "/tab=" + tab.id;
+
+ var nextUri = new URI().normalizeHash();
+ //reset fragment
+ nextUri.fragment(tabState);
+
+
if (isGraph(graph) && !graph.selected()) {
- location.hash += '/' + graph.id;
+ nextUri.fragment(nextUri.fragment() + '/graph=' + graph.id);
+
this.selectedGraph(graph);
// TODO: hack - take this out into a binding
$('.scrollable').scrollTop(0);
} else {
this.selectedGraph(null);
}
+
this.selectedTab(tab);
+
+ // careful to only reassign hash so no reload happens
+ // remove tab and graph state from current state
+ // append new tab and graph state
+ if (currentHash.match(tabSelected)) {
+ window.location.assign(nextUri.toString() +
currentHash.replace(tabSelected, '').replace(graphSelected, ''));
+
+ } else {
+ // old url, wipe out
+ window.location.assign(nextUri.toString());
+ }
+
}.bind(this);
configApi.getDefaultDashboard(function (config) {
@@ -72,11 +113,28 @@
var tabId = config.tabs[0].id,
graphId, tab, graph;
- if (location.hash) {
+ var uri = new URI().normalizeHash();
+ // hash without '#'
+ var hash = uri.fragment();
+ var tabSelected = /tab=(\w{1,}(-\w*){0,})/i;
+ var graphSelected = /graph=(\w{1,}(-\w*){0,})/i;
+ var found = hash.match(tabSelected);
+
+ if (found) {
+ tabId = found[1];
+ found = hash.match(graphSelected);
+ if (found) {
+ graphId = found[1];
+ }
+ }
+ //backwards compatibility for urls without 'graph=' or 'tab='
+ // breaking component encapsulation but this code should be
removed
+ if (!tabId && hash.length > 0 && !hash.match('dates')) {
var selectIds = location.hash.substr(1).split('/');
tabId = selectIds[0];
graphId = selectIds[1];
}
+
tab = _.find(config.tabs, function (t) {
return t.id === tabId;
});
diff --git a/src/components/visualizers/visualizer/visualizer.js
b/src/components/visualizers/visualizer/visualizer.js
index 1819478..9dda818 100644
--- a/src/components/visualizers/visualizer/visualizer.js
+++ b/src/components/visualizers/visualizer/visualizer.js
@@ -8,6 +8,7 @@
colorUtils = require('utils.colors'),
numberUtils = require('utils.numbers'),
TimeseriesData = require('converters.timeseries'),
+ URI = require('uri/URI'),
moment = require('moment');
require('datepicker-binding');
@@ -40,9 +41,30 @@
this.data = ko.observable(new TimeseriesData());
api.getData(graph, 'all').done(this.data);
- this.startDate = ko.observable(graph.startDate);
+
+ /*
+ * Assign state to date range, two inputs:
+ * 1) graph config
+ * 2) url state
+ */
+
+ var uri = new URI().normalizeHash();
+ // hash without '#'
+ var hash = uri.fragment();
+
+ var r = /dates=(\d\d\d\d-\d\d-\d\d),(\d\d\d\d-\d\d-\d\d)/i;
+ var found = hash.match(r);
+ if (found) {
+ this.startDate = ko.observable(found[1]);
+ this.endDate = ko.observable(found[2]);
+
+ } else {
+ this.startDate = ko.observable(graph.startDate);
+ this.endDate = ko.observable();
+ }
+
this.minDate = ko.observable(graph.startDate);
- this.endDate = ko.observable();
+
/** If date is a unix tiemstamp change it to ISO format **/
this.prettyDate = function (value) {
@@ -52,6 +74,44 @@
return value;
};
+ var self = this;
+
+ /**
+ * url handling in components above this one might not be optimal
+ * ignore it, just preserve url as is and append date state
+ *
+ **/
+ this.urlDates = ko.computed(function () {
+
+ if (!self.startDate() || !self.endDate()) {
+ return;
+ }
+
+ var startDatePretty =
moment(self.startDate()).format("YYYY-MM-DD");
+ var endDatePretty = moment(self.endDate()).format("YYYY-MM-DD");
+ // read url and remove fragment that has to do with dates if
present
+
+ var currentUri = new URI().normalizeHash();
+ // hash without '#'
+ var currentHash = currentUri.fragment();
+ // has without visualizer state
+ var urlDates = "/dates=" + startDatePretty + "," + endDatePretty;
+ //reset fragment
+ var nextUri = new URI().normalizeHash();
+ //reset fragment
+ var r = /\/dates=(\d\d\d\d-\d\d-\d\d),(\d\d\d\d-\d\d-\d\d)/i;
+
+ nextUri.fragment(currentHash.replace(r, '') + urlDates);
+
+ // careful to only reassign hash so no reload happens
+ window.location.assign(nextUri.toString());
+
+ return urlDates;
+
+ });
+
+
+
// turn the header into a list of items that can be selected /
deselected
// make it a computed so if the parent changes the data, this updates
this.filteredHeader = ko.computed(function () {
--
To view, visit https://gerrit.wikimedia.org/r/306980
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibb363ae923781478fdb390af19b80012fdf61a0a
Gerrit-PatchSet: 1
Gerrit-Project: analytics/dashiki
Gerrit-Branch: master
Gerrit-Owner: Nuria <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits