Nuria has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/157777

Change subject: [WIP] Adding removing options from browsing component
......................................................................

[WIP] Adding removing options from browsing component

Adding/removing options from side bar. Only interactions.
No style yet.

Change-Id: I34096c205f2d464efd68d6d962c16ab27dde6af9
---
M src/app/apis/wikimetrics.js
M src/components/project-selector/project-selector.html
M src/components/project-selector/project-selector.js
M src/components/wikimetrics-layout/wikimetrics-layout.html
M src/components/wikimetrics-layout/wikimetrics-layout.js
M src/css/layouts.css
M src/lib/logger.js
M stubs/fake-wikimetrics/projectLanguageChoices.json
8 files changed, 310 insertions(+), 36 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/analytics/dashiki 
refs/changes/77/157777/1

diff --git a/src/app/apis/wikimetrics.js b/src/app/apis/wikimetrics.js
index dae97af..f32fdc1 100644
--- a/src/app/apis/wikimetrics.js
+++ b/src/app/apis/wikimetrics.js
@@ -9,8 +9,13 @@
         this.root = config.wikimetricsDomain;
         this.projectOptions = [];
         this.languageOptions = [];
+        /** project selection present upon bootstrap **/
+        this.defaultProjects = [];
         this.urlProjectLanguageChoices = config.urlProjectLanguageChoices;
         this.categorizedMetricsUrl = config.categorizedMetricsUrl;
+
+        /** Given a project returns language and project friendly names*/
+        this.reverseLookup = {};
     }
 
 
@@ -80,6 +85,13 @@
                 this.languageOptions = map.call(json[0], function (data) {
                     return new LanguageOption(data);
                 });
+
+                this.defaultProjects = map.call(json[2], function (data) {
+                    return new ProjectOption(data);
+                });
+                //super hardcoded and fake
+                this.reverseLookup = json[3];
+
                 callback();
 
             }.bind(this));
@@ -106,7 +118,7 @@
      *
      *      {category: 'some category', name: 'some metric'}
      **/
-    WikimetricsApi.prototype.getCategorizedMetrics = function(callback) {
+    WikimetricsApi.prototype.getCategorizedMetrics = function (callback) {
         return $.get(this.categorizedMetricsUrl).done(callback);
     };
 
diff --git a/src/components/project-selector/project-selector.html 
b/src/components/project-selector/project-selector.html
index a9d86f3..68fdb1b 100644
--- a/src/components/project-selector/project-selector.html
+++ b/src/components/project-selector/project-selector.html
@@ -4,16 +4,32 @@
             projectOptions: projectOptions,
             languageOptions: languageOptions,
             select: displaySecondLevel
-       }" class="typeahead search_box" autocomplete="off" size="20"/>
+       } , event 
{blur:function(data,event){setTimeout(hideSecondLevel.bind($data),500)}}" 
class="typeahead search_box" autocomplete="off" size="20"/>
 
-<span class="tt-dropdown-menu" data-bind="css: {open: displaySuboptions}, 
click: hideSecondLevel">
+<span class="tt-dropdown-menu" data-bind="css: {open: displaySuboptions},
+event:{blur:function(data,event){setTimeout(hideSecondLevel.bind($data),200);}}">
     <div class="tt-dataset-suboptions">
         <span class="header" data-bind="text: selectedOption"></span>
         <hr/>
         <span class="tt-suggestions">
         <!-- ko foreach: suboptions -->
-            <div class="tt-suggestion" data-bind="text: option"></div>
+            <div class="tt-suggestion" data-bind="text: name,
+            click: function(data,event){$parent.addProject(data);}"></div>
+            <span class="hidden" data-bind="text:project"> </span>
         <!-- /ko -->
         </span>
     </div>
 </span>
+
+<hr/>
+
+<div class="ui" style=" width:300px">
+<!-- ko foreach: selectionForDisplay -->
+    <span class="ui large label" data-bind="text:name"> </span>
+    <i class="delete icon" data-bind="click: 
function(data,event){$parent.removeCategory(data);}"></i>
+    <!-- ko foreach: languages -->
+     <div data-bind="text:name"> </div>
+     <i class="delete icon" data-bind="click: 
function(data,event){$parents[1].removeCategory(data);}"></i>
+    <!-- /ko -->
+<!-- /ko -->
+</div>
diff --git a/src/components/project-selector/project-selector.js 
b/src/components/project-selector/project-selector.js
index 6d7d113..d5b46e8 100644
--- a/src/components/project-selector/project-selector.js
+++ b/src/components/project-selector/project-selector.js
@@ -1,22 +1,146 @@
 /* jshint -W098 */
 define(['knockout', 'text!./project-selector.html', './bindings'], function 
(ko, templateMarkup) {
     'use strict';
+    /**
+    * A selection item is of this form
+        {
+             'name': projectData.name,
+            'languages': [{
+                'name': language,
+                'project': data.project
+                }]
+            }
+    **/
+    function SelectionItem(projectName, project, languageName) {
+        this.name = projectName;
+        this.languages = [];
+        if (project && projectName) {
+            this.addLanguage(project, languageName);
+        }
+
+
+    }
+
+    function LanguageItem(project, languageName) {
+        this.name = languageName;
+        this.project = project;
+    }
+
+    /** Adds a language to the project selection if it is not already there **/
+    SelectionItem.prototype.addLanguage = function (project, languageName) {
+        var found = false;
+        for (var i = 0; i < this.languages.length; i++) {
+            if (this.languages[i].project.trim() === project.trim()) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            this.languages.push(new LanguageItem(project, languageName));
+        }
+    };
+
+    SelectionItem.prototype.addLanguages = function (languages) {
+        this.languages = languages;
+    };
+
 
     function ProjectSelector(params) {
-
+        var self = this;
         this.projectOptions = params.projectOptions();
         this.languageOptions = params.languageOptions();
-        /** options selected upon bootstrap if any **/
-        this.defaultProjects = params.defaultProjects;
         this.displaySuboptions = ko.observable(false);
         this.selectedOption = ko.observable();
         this.suboptions = ko.observableArray([]);
+        this.reverseLookup = params.reverseLookup();
+        this.selectionForDisplay = ko.observableArray([]);
+        this.setSelectionForDisplay(params.defaultProjects);
+
+        /** From the selectionfrom display
+            calculates the projects the visualization component cares about:
+            input:
+            [{
+                "name": "Wikipedia",
+                "languages": [{
+
+                    "name": "English",
+                    "project": "enwiki"
+                }, {
+                    "name": "German",
+                    "project": "dewiki"
+                }]
+            }, {
+                "name": "WikiSomething",
+                "languages": [{
+                    "name": "Spanish",
+                    "project": "essomethingwiki"
+                }, {
+                    "name": "German",
+                    "project": "desomethingwiki"
+                }]
+            }],
+
+            output:
+            [enwiki, dewiki, essomethingwiki, desomethingwiki]
+         **/
+        this.addedProjects = ko.computed(function () {
+            var selectionForDisplay = this.selectionForDisplay();
+            var projects = [];
+
+            if (selectionForDisplay.length > 0) {
+                selectionForDisplay.map(function (item) {
+                    var languages = item.languages;
+                    for (var i = 0; i < languages.length; i++) {
+                        projects.push(languages[i].project);
+                    }
+                    return projects;
+                });
+            }
+            return projects;
+        }, this);
     }
+
+    /**
+     * Turns a plain json array of objs like:
+     [{
+        "name": "Wikipedia",
+        "languages": [{
+
+            "name": "English",
+            "project": "enwiki"
+        }, {
+            "name": "German",
+            "project": "dewiki"
+        }]
+    }, {
+        "name": "WikiSomething",
+        "languages": [{
+            "name": "Spanish",
+            "project": "essomethingwiki"
+        }, {
+            "name": "German",
+            "project": "desomethingwiki"
+        }]
+    }],
+    into richer SelectionItems objects we can use with more ease
+     **/
+    ProjectSelector.prototype.setSelectionForDisplay = function 
(defaultOptionsRaw) {
+        var selectionForDisplay = [];
+        var defaultOptions = defaultOptionsRaw();
+        for (var i = 0; i < defaultOptions.length; i++) {
+            var selectionItem = new SelectionItem(defaultOptions[i].name);
+            selectionItem.addLanguages(defaultOptions[i].languages);
+            selectionForDisplay.push(selectionItem);
+        }
+        this.selectionForDisplay(selectionForDisplay);
+        this.selectionForDisplay.sort();
+    };
 
     function makeOptions(obj) {
         return Object.getOwnPropertyNames(obj).map(function (p) {
             return {
-                option: p
+                name: p,
+                project: obj[p]
             };
         });
     }
@@ -36,6 +160,62 @@
         this.suboptions([]);
     };
 
+    ProjectSelector.prototype.addProject = function (data) {
+        // get project nice name and language nice name
+        var projectData = this.reverseLookup[data.project];
+        // add them to side bar list
+        // o(n) on number of projects added at worst, can of course be improved
+
+        // try to see if this is a new category project
+        var existingItems = this.selectionForDisplay.remove(function (item) {
+            var category = item.name;
+            return item.name === projectData.name;
+        });
+
+        var language = projectData.language;
+
+        if (existingItems.length > 0) {
+            // new language in existing category, add it to set
+            var existingItem = existingItems[0];
+            existingItem.addLanguage(data.project, projectData.language);
+
+            this.selectionForDisplay.push(existingItem);
+            this.selectionForDisplay.sort();
+
+        } else {
+
+            // new category
+            var item = new SelectionItem(projectData.name, data.project, 
language);
+
+            this.selectionForDisplay.push(item);
+            this.selectionForDisplay.sort();
+        }
+
+        this.hideSecondLevel();
+    };
+
+    ProjectSelector.prototype.removeProject = function (data) {
+        //there is a bug invoking this function
+        // sometimes does not get called?
+        var existingItem = this.selectionForDisplay.remove(function (item) {
+            var languages = item.languages;
+            var found = false;
+            for (var i; i < languages.length; i++) {
+                if (languages.project === data.project.trim()) {
+                    found = true;
+                }
+            }
+            return found;
+        });
+    };
+
+    ProjectSelector.prototype.removeCategory = function (data) {
+        // get project nice name and language nice name
+        var existingItem = this.selectionForDisplay.remove(function (item) {
+            return item.name.trim() === data.name.trim();
+        });
+    };
+
     return {
         viewModel: ProjectSelector,
         template: templateMarkup
diff --git a/src/components/wikimetrics-layout/wikimetrics-layout.html 
b/src/components/wikimetrics-layout/wikimetrics-layout.html
index 48fcb00..05927f7 100644
--- a/src/components/wikimetrics-layout/wikimetrics-layout.html
+++ b/src/components/wikimetrics-layout/wikimetrics-layout.html
@@ -2,7 +2,8 @@
     <section class="col span_small projects-container">
         <project-selector params="{ projectOptions:projectOptions,
                                     languageOptions:languageOptions,
-                                    defaultProjects: defaultProjects}">
+                                    defaultProjects: defaultProjects,
+                                    reverseLookup: reverseLookup}">
 
         </project-selector>
     </section>
diff --git a/src/components/wikimetrics-layout/wikimetrics-layout.js 
b/src/components/wikimetrics-layout/wikimetrics-layout.js
index cce9223..da6521b 100644
--- a/src/components/wikimetrics-layout/wikimetrics-layout.js
+++ b/src/components/wikimetrics-layout/wikimetrics-layout.js
@@ -13,19 +13,23 @@
         self.selectedProjects = ko.observableArray([]);
         self.projectOptions = ko.observableArray([]);
         self.languageOptions = ko.observableArray([]);
-        self.defaultProjects = [];
+        self.defaultProjects = ko.observableArray([]);
+        self.reverseLookup = ko.observable();
 
         wikimetricsApi.getProjectAndLanguageChoices(function () {
             self.languageOptions(wikimetricsApi.languageOptions);
             self.projectOptions(wikimetricsApi.projectOptions);
+            self.defaultProjects(wikimetricsApi.defaultProjects);
+            self.reverseLookup(wikimetricsApi.reverseLookup);
         });
 
-        self.selectedProjects = ko.observableArray();
+        /** infer selected projects from defaultProjectSelection object which 
is taylored for the ui **/
+
 
         self.metricData = ko.observable();
         wikimetricsApi.getCategorizedMetrics(self.metricData);
 
-        self.metrics = ko.computed(function() {
+        self.metrics = ko.computed(function () {
             var configData = this.metricData();
             if (configData) {
                 return configData.categorizedMetrics;
@@ -33,7 +37,7 @@
             return [];
         }, self);
 
-        self.defaultMetrics = ko.computed(function() {
+        self.defaultMetrics = ko.computed(function () {
             var configData = this.metricData();
             if (configData) {
                 return configData.defaultMetrics;
diff --git a/src/css/layouts.css b/src/css/layouts.css
index 9e54ee2..9901abb 100644
--- a/src/css/layouts.css
+++ b/src/css/layouts.css
@@ -15,3 +15,7 @@
     .span_small { position: relative; width: 100%; right: 0; }
     .span_large { position: relative; width: 100%; left: 0; }
 }
+
+.hidden {
+    display:none;
+}
diff --git a/src/lib/logger.js b/src/lib/logger.js
index d383313..3c253bd 100644
--- a/src/lib/logger.js
+++ b/src/lib/logger.js
@@ -1,4 +1,4 @@
-define([], function() {
+define([], function () {
     'use strict';
     /**
      * Logger for client side errors.
@@ -22,16 +22,17 @@
 
     window.logger = {
 
-        error: function(message) {
+        error: function (message) {
             console.log(this._getTimestamp() + message);
         },
-        _getTimestamp: function() {
+        _getTimestamp: function () {
             return new Date().toUTCString();
         }
     };
 
     // registering for window.onerror, although many events do not trigger this
-    window.onerror = function(message, file, line) {
+    window.onerror = function (message, file, line) {
         logger.error(file + ':' + line + '\n\n' + message);
     };
+
 });
diff --git a/stubs/fake-wikimetrics/projectLanguageChoices.json 
b/stubs/fake-wikimetrics/projectLanguageChoices.json
index 1b7803e..d10a864 100644
--- a/stubs/fake-wikimetrics/projectLanguageChoices.json
+++ b/stubs/fake-wikimetrics/projectLanguageChoices.json
@@ -3,41 +3,41 @@
         "name": "English",
         "description": "All projects",
         "projects": {
-            "Wikipedia": "eswiki",
-            "Somethingwiki": "somewiki",
-            "Wikidictionary": "somewiki"
+            "Wikipedia": "enwiki",
+            "WikiSomething": "ensomethingwiki",
+            "Wikidictionary": "endictionarywiki"
         }
     }, {
         "name": "German",
         "description": "All projects",
         "projects": {
             "Wikipedia": "dewiki",
-            "SomethingGermanWiki": "somewiki",
-            "Wikidictionary": "somewiki"
+            "WikiSomething": "desomethingwiki",
+            "Wikidictionary": "dedictionarywiki"
         }
     }, {
         "name": "Spanish",
         "description": "All projects",
         "projects": {
             "Wikipedia": "eswiki",
-            "SomethingSpanishWiki": "somewiki",
-            "Wikidictionary": "somewiki"
+            "WikiSomething": "essomethingwiki",
+            "Wikidictionary": "esdictionarywiki"
         }
     }, {
         "name": "Cantonese",
         "description": "All projects",
         "projects": {
             "Wikipedia": "cawiki",
-            "SomethingCantoneseWiki": "somewiki",
-            "Wikidictionary": "somewiki"
+            "WikiSomething": "casomethingwiki",
+            "Wikidictionary": "cadictionarywiki"
         }
     }, {
         "name": "Catalan",
         "description": "All projects",
         "projects": {
-            "Wikipedia": "cawiki",
-            "SomethingCatalanWiki": "somewiki",
-            "Wikidictionary": "somewiki"
+            "Wikipedia": "catwiki",
+            "WikiSomething": "catsomethingwiki",
+            "Wikidictionary": "catdictionarywiki"
         }
     }],
     [{
@@ -52,17 +52,17 @@
         "name": "WikiSomething",
         "description": "100 languages",
         "languages": {
-            "Spanish": "eswiki",
-            "English": "enwiki",
-            "German": "dewiki"
+            "Spanish": "essomethingwiki",
+            "English": "ensomethingwiki",
+            "German": "desomethingwiki"
         }
     }, {
         "name": "Wikitionary",
         "description": "170 languages",
         "languages": {
-            "Spanish": "eswiki",
-            "English": "enwiki",
-            "German": "dewiki"
+            "Spanish": "esdictionarywiki",
+            "English": "endictionarywiki",
+            "German": "dedictionarywiki"
         }
     }, {
         "name": "Commons",
@@ -70,5 +70,61 @@
         "languages": {
             "Mandarin": "mawiki"
         }
-    }]
+    }],
+    [{
+        "name": "Wikipedia",
+        "languages": [{
+
+            "name": "English",
+            "project": "enwiki"
+        }, {
+            "name": "German",
+            "project": "dewiki"
+        }]
+    }, {
+        "name": "WikiSomething",
+        "languages": [{
+            "name": "Spanish",
+            "project": "essomethingwiki"
+        }, {
+            "name": "German",
+            "project": "desomethingwiki"
+        }]
+    }],
+
+    {
+        "enwiki": {
+            "name": "Wikipedia",
+            "language": "English"
+        },
+        "dewiki": {
+            "name": "Wikipedia",
+            "language": "German"
+        },
+        "eswiki": {
+            "name": "Wikipedia",
+            "language": "Spanish"
+        },
+        "catwiki": {
+            "name": "Wikipedia",
+            "language": "Catalan"
+        },
+        "ensomethingwiki": {
+            "name": "Wikisomething",
+            "language": "English"
+        },
+        "desomethingwiki": {
+            "name": "WikiSomething",
+            "language": "German"
+        },
+        "essomethingwiki": {
+            "name": "WikiSomething",
+            "language": "Spanish"
+        },
+        "catsomethingwiki": {
+            "name": "WikiSomething",
+            "language": "Catalan"
+        }
+    }
+
 ]

-- 
To view, visit https://gerrit.wikimedia.org/r/157777
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I34096c205f2d464efd68d6d962c16ab27dde6af9
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