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

Reply via email to