You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kibble.apache.org by hu...@apache.org on 2018/09/17 07:49:58 UTC

[kibble] branch master updated (cd554dc -> 7f5d092)

This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git.


    from cd554dc  fix link and typo
     new 75379fb  add contributors API point
     new 7a4bb34  json needs to be marked as unicode
     new 7d16907  regen openapi
     new 31a6e3d  add widgets for contributors page
     new 31f9ba6  scrap old phonebook, start work on a new one
     new 19e3a7f  this is phonebook now
     new d22b68b  tweak CSS for phonebook
     new 7f5d092  regen JS

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../timeseries-single.py => org/contributors.py}   | 141 +++++------
 api/plugins/session.py                             |   2 +-
 api/yaml/openapi.yaml                              |  23 ++
 api/yaml/widgets.yaml                              |  30 +++
 ui/css/kibble.min.css                              |  22 ++
 ui/js/coffee/datepicker.coffee                     |   1 +
 ui/js/coffee/explorer.coffee                       |  28 +--
 ui/js/coffee/pageloader.coffee                     |   2 +-
 ui/js/coffee/phonebook.coffee                      | 165 +++----------
 ui/js/coffee/widget.coffee                         |   2 +-
 ui/js/kibble.v1.js                                 | 272 +++++++--------------
 11 files changed, 292 insertions(+), 396 deletions(-)
 copy api/pages/{mail/timeseries-single.py => org/contributors.py} (53%)


[kibble] 07/08: tweak CSS for phonebook

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit d22b68be335aa5ad0b52ab7941dc39f40895bd68
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:49:38 2018 +0200

    tweak CSS for phonebook
---
 ui/css/kibble.min.css | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/ui/css/kibble.min.css b/ui/css/kibble.min.css
index 557e016..b356e61 100644
--- a/ui/css/kibble.min.css
+++ b/ui/css/kibble.min.css
@@ -3067,3 +3067,25 @@ body.error .logo h1 {
     border-top-left-radius: 0;
     border-top-right-radius: 0
 }
+
+.phonebook_entry {
+   width: 340px;
+   overflow: hidden;
+   text-overflow: ellipsis;
+   height: 40px;
+   border-radius: 3px;
+   border: 1px solid #3336;
+   background: #EEE;
+   display: inline-block;
+   margin: 3px;
+}
+
+.phonebook_entry > a > img {
+   margin: 2px; 
+}
+
+.phonebook_entry > div {
+   overflow: hidden;
+   text-overflow: ellipsis;
+   white-space: nowrap;
+}
\ No newline at end of file


[kibble] 06/08: this is phonebook now

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 19e3a7f6cb0eb0d021a81180632570f66e60f093
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:49:25 2018 +0200

    this is phonebook now
---
 ui/js/coffee/datepicker.coffee |  1 +
 ui/js/coffee/explorer.coffee   | 28 ++++++++++++++--------------
 ui/js/coffee/pageloader.coffee |  2 +-
 ui/js/coffee/widget.coffee     |  2 +-
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/ui/js/coffee/datepicker.coffee b/ui/js/coffee/datepicker.coffee
index 5250679..3413d26 100644
--- a/ui/js/coffee/datepicker.coffee
+++ b/ui/js/coffee/datepicker.coffee
@@ -35,6 +35,7 @@ updateTimeseriesWidgets = (range) ->
             updateWidgets('report', null, { to: to, from: from})
             updateWidgets('mvp', null, { to: to, from: from})
             updateWidgets('comstat', null, { to: to, from: from})
+            updateWidgets('phonebook', null, { to: to, from: from})
             updateWidgets('worldmap', null, { to: to, from: from})
             updateWidgets('jsondump', null, { to: to, from: from})
                 
diff --git a/ui/js/coffee/explorer.coffee b/ui/js/coffee/explorer.coffee
index 7f9e3a1..0bf761f 100644
--- a/ui/js/coffee/explorer.coffee
+++ b/ui/js/coffee/explorer.coffee
@@ -58,7 +58,7 @@ explorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -86,7 +86,7 @@ explorer = (json, state) ->
                 updateWidgets('donut', null, { author: author })
                 updateWidgets('gauge', null, { author: author })
                 updateWidgets('line', null, { author: author })
-                updateWidgets('contacts', null, { author: author })
+                updateWidgets('phonebook', null, { author: author })
                 updateWidgets('top5', null, { author: author })
                 updateWidgets('factors', null, { author: author })
                 updateWidgets('trends', null, { author: author })
@@ -161,13 +161,13 @@ sourceexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
                 updateWidgets('mvp', null, { source: source })
                 updateWidgets('comstat', null, { source: source })
-                updateWidgets('jsondump', null, { author: author })
+                updateWidgets('jsondump', null, { source: source })
         )
 
 
@@ -218,7 +218,7 @@ mailexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -327,7 +327,7 @@ issueexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -384,7 +384,7 @@ forumexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -441,7 +441,7 @@ imexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -498,7 +498,7 @@ ciexplorer = (json, state) ->
                 updateWidgets('donut', null, { source: source })
                 updateWidgets('gauge', null, { source: source })
                 updateWidgets('line', null, { source: source })
-                updateWidgets('contacts', null, { source: source })
+                updateWidgets('phonebook', null, { source: source })
                 updateWidgets('top5', null, { source: source })
                 updateWidgets('factors', null, { source: source })
                 updateWidgets('trends', null, { source: source })
@@ -552,7 +552,7 @@ multiviewexplorer = (json, state) ->
                     updateWidgets('donut', null, x)
                     updateWidgets('gauge', null, x)
                     updateWidgets('line', null, x)
-                    updateWidgets('contacts', null, x)
+                    updateWidgets('phonebook', null, x)
                     updateWidgets('top5', null, x)
                     updateWidgets('factors', null, x)
                     updateWidgets('trends', null, x)
@@ -577,7 +577,7 @@ subFilter = () ->
         updateWidgets('donut', null, x)
         updateWidgets('gauge', null, x)
         updateWidgets('line', null, x)
-        updateWidgets('contacts', null, x)
+        updateWidgets('phonebook', null, x)
         updateWidgets('top5', null, x)
         updateWidgets('factors', null, x)
         updateWidgets('trends', null, x)
@@ -615,7 +615,7 @@ pathFilter = () ->
         updateWidgets('donut', null, x)
         updateWidgets('gauge', null, x)
         updateWidgets('line', null, x)
-        updateWidgets('contacts', null, x)
+        updateWidgets('phonebook', null, x)
         updateWidgets('top5', null, x)
         updateWidgets('factors', null, x)
         updateWidgets('trends', null, x)
@@ -690,7 +690,7 @@ viewexplorer = (json, state) ->
                 updateWidgets('donut', null, x)
                 updateWidgets('gauge', null, x)
                 updateWidgets('line', null, x)
-                updateWidgets('contacts', null, x)
+                updateWidgets('phonebook', null, x)
                 updateWidgets('top5', null, x)
                 updateWidgets('factors', null, x)
                 updateWidgets('trends', null, x)
@@ -817,7 +817,7 @@ widgetexplorer = (json, state) ->
                 updateWidgets('donut', null, x)
                 updateWidgets('gauge', null, x)
                 updateWidgets('line', null, x)
-                updateWidgets('contacts', null, x)
+                updateWidgets('phonebook', null, x)
                 updateWidgets('top5', null, x)
                 updateWidgets('factors', null, x)
                 updateWidgets('trends', null, x)
diff --git a/ui/js/coffee/pageloader.coffee b/ui/js/coffee/pageloader.coffee
index b42b065..251d2b2 100644
--- a/ui/js/coffee/pageloader.coffee
+++ b/ui/js/coffee/pageloader.coffee
@@ -100,7 +100,7 @@ setupPage = (json, state) ->
                 when 'messages' then widget.load(messages)
                 when 'sourcelist' then widget.load(sourcelist)
                 when 'sourceadd' then widget.load(sourceadd)
-                when 'contacts' then setupPhonebook(widget, child)
+                when 'phonebook' then widget.load(phonebook)
                 when 'preferences' then widget.load(preferences)
                 when 'orgadmin' then widget.load(orgadmin)
                 when 'affiliations' then widget.load(affiliation)
diff --git a/ui/js/coffee/widget.coffee b/ui/js/coffee/widget.coffee
index 0abd34b..9d5fb5a 100644
--- a/ui/js/coffee/widget.coffee
+++ b/ui/js/coffee/widget.coffee
@@ -120,7 +120,7 @@ updateWidgets = (type, target, eargs) ->
                 when 'preferences' then widget.load(preferences)
                 when 'messages' then widget.load(messages)
                 when 'widget' then widget.load(publisher)
-                when 'contacts' then fetchPhonebook({ widget: widget, w: w, letter: 'a', project: target})
+                when 'phonebook' then widget.load(phonebook)
                 when 'repopicker' then widget.load(explorer)
                 when 'sourcepicker' then widget.load(sourceexplorer)
                 when 'issuepicker' then widget.load(issueexplorer)


[kibble] 04/08: add widgets for contributors page

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 31a6e3dbfef8585b453e3cc5d8ae8f69a4aa1081
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:48:51 2018 +0200

    add widgets for contributors page
---
 api/yaml/widgets.yaml | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/api/yaml/widgets.yaml b/api/yaml/widgets.yaml
index 3f44f57..5895075 100644
--- a/api/yaml/widgets.yaml
+++ b/api/yaml/widgets.yaml
@@ -875,3 +875,33 @@ widgets:
                         source:     "forum/top-count"
                         name:       "Busiest forums by posts"
                         target:     ""
+
+### PEOPLE
+    people:
+        title: "Contributors"
+        rows:
+            -
+                name: "Date picker row"
+                children:
+                    -
+                        type:   "datepicker"
+                        blocks: 4
+                        name:   "Date picker"
+                    -
+                        type:   "viewpicker"
+                        blocks: 4
+                        source: "views"
+                        name:   "Quick filter"
+                    -
+                        type:   sourcepicker
+                        blocks: 4
+                        source: "sources"
+                        name:   "Source filter"
+            -
+                name: "Contributor row"
+                children:
+                    -
+                        type:   "phonebook"
+                        blocks: 12
+                        source: "org/contributors"
+                        name:   "Contributor list"


[kibble] 01/08: add contributors API point

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 75379fbe9e52a4468ef005530a7be4da6cab1d2f
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:48:16 2018 +0200

    add contributors API point
---
 api/pages/org/contributors.py | 168 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)

diff --git a/api/pages/org/contributors.py b/api/pages/org/contributors.py
new file mode 100644
index 0000000..c42e0f9
--- /dev/null
+++ b/api/pages/org/contributors.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+# OPENAPI-URI: /api/org/contributors
+########################################################################
+# post:
+#   requestBody:
+#     content:
+#       application/json:
+#         schema:
+#           $ref: '#/components/schemas/defaultWidgetArgs'
+#   responses:
+#     '200':
+#       content:
+#         application/json:
+#           schema:
+#             $ref: '#/components/schemas/contributorList'
+#       description: 200 Response
+#     default:
+#       content:
+#         application/json:
+#           schema:
+#             $ref: '#/components/schemas/Error'
+#       description: unexpected error
+#   security:
+#   - cookieAuth: []
+#   summary: Shows contributors for the entire org or matching filters.
+# 
+########################################################################
+
+
+
+
+
+"""
+This is the contributor list renderer for Kibble
+"""
+
+import json
+import time
+import hashlib
+
+cached_people = {} # Store people we know, so we don't have to fetch them again.
+
+def run(API, environ, indata, session):
+    
+    # We need to be logged in for this!
+    if not session.user:
+        raise API.exception(403, "You must be logged in to use this API endpoint! %s")
+    
+    
+    # First, fetch the view if we have such a thing enabled
+    viewList = []
+    if indata.get('view'):
+        viewList = session.getView(indata.get('view'))
+    if indata.get('subfilter'):
+        viewList = session.subFilter(indata.get('subfilter'), view = viewList) 
+    
+    
+    # Fetch all contributors for the org
+    dOrg = session.user['defaultOrganisation'] or "apache"
+    query = {
+                'query': {
+                    'bool': {
+                        'must': [
+                            {
+                                'term': {
+                                    'organisation': dOrg
+                                }
+                            }
+                        ]
+                    }
+                }
+            }
+    
+    # Source-specific or view-specific??
+    if indata.get('source'):
+        query['query']['bool']['must'].append({'term': {'sourceID': indata.get('source')}})
+    elif viewList:
+        query['query']['bool']['must'].append({'terms': {'sourceID': viewList}})
+    
+    # Date specific?
+    dateTo = indata.get('to', int(time.time()))
+    dateFrom = indata.get('from', dateTo - (86400*30*6)) # Default to a 6 month span
+    query['query']['bool']['must'].append(
+        {'range':
+            {
+                'ts': {
+                    'from': dateFrom,
+                    'to': dateTo
+                }
+            }
+        }
+        )
+    emails = []
+    contribs = {}
+    
+    for field in ['email', 'address', 'author_email', 'assignee', 'issueCreator', 'issueCloser']:
+        N = 0
+        while N < 5:
+            query['aggs'] = {
+                'by_id': {
+                    'terms': {
+                        'field': field,
+                        'size': 10000,
+                        'include': {
+                            'partition': N,
+                            'num_partitions': 5
+                         },
+                    }                
+                }
+            }
+            res = session.DB.ES.search(
+                    index=session.DB.dbname,
+                    doc_type="*",
+                    size = 0,
+                    body = query
+                )
+            # Break if we've found nothing more
+            #if len(res['aggregations']['by_id']['buckets']) == 0:
+                #break
+            # otherwise, add 'em to the pile
+            for k in res['aggregations']['by_id']['buckets']:
+                if k['key'] not in emails:
+                    emails.append(k['key'])
+                    contribs[k['key']] = k['doc_count']
+            N += 1
+            
+    people = []
+    for email in emails:
+        pid = hashlib.sha1( ("%s%s" % (dOrg, email)).encode('ascii', errors='replace')).hexdigest()
+        person = None
+        if pid in cached_people:
+            person = cached_people[pid]
+        else:
+            try:
+                doc = session.DB.ES.get(index=session.DB.dbname, doc_type = 'person', id = pid)
+                cached_people[pid] = {
+                    'name': doc['_source']['name'],
+                    'email': doc['_source']['email'],
+                    'gravatar': hashlib.md5( email.encode('ascii', errors = 'replace')).hexdigest()
+                }
+                person = cached_people[pid]
+            except:
+                pass # Couldn't find 'em, booo
+        if person:
+            person['contributions'] = contribs.get(email, 0)
+            people.append(person)
+        
+    JSON_OUT = {
+        'people': people,
+        'okay': True
+    }
+    yield json.dumps(JSON_OUT)


[kibble] 08/08: regen JS

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 7f5d0928a16fd2f6ffe8b655ca51f2376c078d77
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:49:42 2018 +0200

    regen JS
---
 ui/js/kibble.v1.js | 272 ++++++++++++++++++-----------------------------------
 1 file changed, 92 insertions(+), 180 deletions(-)

diff --git a/ui/js/kibble.v1.js b/ui/js/kibble.v1.js
index c640fb7..1325acf 100644
--- a/ui/js/kibble.v1.js
+++ b/ui/js/kibble.v1.js
@@ -1,5 +1,5 @@
 // Generated by CoffeeScript 1.12.7
-var API, APIVERSION, Chart, HTML, Row, Widget, aSourceTypes, accountCallback, addSourceType, addSources, addorguser, addsources, affiliate, affiliation, affiliationWizard, altemail, app, badModal, bio, chartOnclick, chartToSvg, chartWrapperButtons, charts_donutchart, charts_gaugechart, charts_linechart, charts_linechart_stacked, charts_linked, charts_radarchart, ciexplorer, cog, comShow, comstat, copyCSS, currentSources, dataTable, datepicker, datepickers, defaultOrgChanged, deletesource [...]
+var API, APIVERSION, Chart, HTML, Row, Widget, aSourceTypes, accountCallback, addSourceType, addSources, addorguser, addsources, affiliate, affiliation, affiliationWizard, altemail, app, badModal, bio, chartOnclick, chartToSvg, chartWrapperButtons, charts_donutchart, charts_gaugechart, charts_linechart, charts_linechart_stacked, charts_linked, charts_radarchart, ciexplorer, cog, comShow, comstat, copyCSS, currentSources, dataTable, datepicker, datepickers, defaultOrgChanged, deletesource [...]
   indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
 
 signup = function(form) {
@@ -1462,6 +1462,10 @@ updateTimeseriesWidgets = function(range) {
       to: to,
       from: from
     });
+    updateWidgets('phonebook', null, {
+      to: to,
+      from: from
+    });
     updateWidgets('worldmap', null, {
       to: to,
       from: from
@@ -1656,7 +1660,7 @@ explorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -1702,7 +1706,7 @@ explorer = function(json, state) {
     updateWidgets('line', null, {
       author: author
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       author: author
     });
     updateWidgets('top5', null, {
@@ -1842,7 +1846,7 @@ sourceexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -1861,7 +1865,7 @@ sourceexplorer = function(json, state) {
       source: source
     });
     return updateWidgets('jsondump', null, {
-      author: author
+      source: source
     });
   });
 };
@@ -1936,7 +1940,7 @@ mailexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -2112,7 +2116,7 @@ issueexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -2200,7 +2204,7 @@ forumexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -2288,7 +2292,7 @@ imexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -2377,7 +2381,7 @@ ciexplorer = function(json, state) {
     updateWidgets('line', null, {
       source: source
     });
-    updateWidgets('contacts', null, {
+    updateWidgets('phonebook', null, {
       source: source
     });
     updateWidgets('top5', null, {
@@ -2459,7 +2463,7 @@ multiviewexplorer = function(json, state) {
           updateWidgets('donut', null, x);
           updateWidgets('gauge', null, x);
           updateWidgets('line', null, x);
-          updateWidgets('contacts', null, x);
+          updateWidgets('phonebook', null, x);
           updateWidgets('top5', null, x);
           updateWidgets('factors', null, x);
           updateWidgets('trends', null, x);
@@ -2493,7 +2497,7 @@ subFilter = function() {
   updateWidgets('donut', null, x);
   updateWidgets('gauge', null, x);
   updateWidgets('line', null, x);
-  updateWidgets('contacts', null, x);
+  updateWidgets('phonebook', null, x);
   updateWidgets('top5', null, x);
   updateWidgets('factors', null, x);
   updateWidgets('trends', null, x);
@@ -2537,7 +2541,7 @@ pathFilter = function() {
   updateWidgets('donut', null, x);
   updateWidgets('gauge', null, x);
   updateWidgets('line', null, x);
-  updateWidgets('contacts', null, x);
+  updateWidgets('phonebook', null, x);
   updateWidgets('top5', null, x);
   updateWidgets('factors', null, x);
   updateWidgets('trends', null, x);
@@ -2631,7 +2635,7 @@ viewexplorer = function(json, state) {
     updateWidgets('donut', null, x);
     updateWidgets('gauge', null, x);
     updateWidgets('line', null, x);
-    updateWidgets('contacts', null, x);
+    updateWidgets('phonebook', null, x);
     updateWidgets('top5', null, x);
     updateWidgets('factors', null, x);
     updateWidgets('trends', null, x);
@@ -2790,7 +2794,7 @@ widgetexplorer = function(json, state) {
     updateWidgets('donut', null, x);
     updateWidgets('gauge', null, x);
     updateWidgets('line', null, x);
-    updateWidgets('contacts', null, x);
+    updateWidgets('phonebook', null, x);
     updateWidgets('top5', null, x);
     updateWidgets('factors', null, x);
     updateWidgets('trends', null, x);
@@ -3918,8 +3922,8 @@ setupPage = function(json, state) {
           case 'sourceadd':
             results1.push(widget.load(sourceadd));
             break;
-          case 'contacts':
-            results1.push(setupPhonebook(widget, child));
+          case 'phonebook':
+            results1.push(widget.load(phonebook));
             break;
           case 'preferences':
             results1.push(widget.load(preferences));
@@ -4078,166 +4082,79 @@ renderAccountInfo = function(json, state) {
   }
 };
 
-phonebook_cached = {};
-
-fetchPhonebook = function(args) {
-  var url, wargs;
-  if (args) {
-    wargs = JSON.stringify(args);
-    if (phonebook_cached[wargs]) {
-      renderPhonebook(phonebook_cached[wargs], args);
-      return;
-    }
-  }
-  args.widget.cog();
-  url = "people/";
-  return postJSON(url, args, args, renderPhonebook);
-};
-
-setupPhonebook = function(widget, w) {
-  return fetchPhonebook({
-    widget: widget,
-    w: w,
-    letter: 'a',
-    project: w.target || ""
-  });
-};
-
-renderPhonebook = function(json, state) {
-  var a, imgsrc, len, len1, letter, letters, li, people, person, q, rdiv, ref, row, tbl, u, ul, wargs;
-  wargs = JSON.stringify(state);
-  phonebook_cached[wargs] = json;
-  letters = "abcdefghijklmnopqrstuvwxyz".split("");
-  row = document.createElement('div');
-  row.setAttribute("class", "row");
-  rdiv = document.createElement('div');
-  rdiv.setAttribute("class", "col-md-12 col-sm-12 col-xs-12 text-center");
-  ul = document.createElement('ul');
-  ul.setAttribute("class", "pagination pagination-split");
-  for (q = 0, len = letters.length; q < len; q++) {
-    letter = letters[q];
-    li = document.createElement('li');
-    a = document.createElement('a');
-    a.setAttribute("href", "#");
-    a.addEventListener("click", function() {
-      state.letter = this.childNodes[0].data.toLowerCase();
-      return fetchPhonebook(state);
-    }, false);
-    a.appendChild(document.createTextNode(letter.toUpperCase()));
-    if (state.letter && letter === state.letter) {
-      li.setAttribute("class", "active");
-    }
-    li.appendChild(a);
-    ul.appendChild(li);
-  }
-  rdiv.appendChild(ul);
-  row.appendChild(rdiv);
-  state.widget.inject(row, true);
-  row = mk('table', {
-    "class": "display"
-  }, mk('thead', {}, mk('tr', {}, [mk('th', {}, 'Avatar'), mk('th', {}, 'Name'), mk('th', {}, 'Email')])));
-  people = [];
-  json.people.sort((function(_this) {
-    return function(a, b) {
-      if (a.name === b.name) {
-        return 0;
-      } else {
+phonebook = function(json, state) {
+  var i, id, idiv, item, items, left, obj, ref, results, right, rightInner, title;
+  items = [];
+  if (json.people) {
+    id = parseInt(Math.random() * 99999999).toString(16);
+    obj = new HTML('div', {
+      id: id
+    });
+    obj.innerText = "Found " + json.people.length + " contributors..";
+    obj.inject(new HTML('br'));
+    state.widget.inject(obj, true);
+    json.people.sort((function(_this) {
+      return function(a, b) {
+        if (a.name < b.name) {
+          return -1;
+        }
         if (a.name > b.name) {
           return 1;
-        } else {
-          return -1;
         }
+        return 0;
+      };
+    })(this));
+    ref = json.people;
+    results = [];
+    for (i in ref) {
+      item = ref[i];
+      if (i > 250) {
+        break;
       }
-    };
-  })(this));
-  a = 0;
-  ref = json.people;
-  for (u = 0, len1 = ref.length; u < len1; u++) {
-    person = ref[u];
-    a++;
-    imgsrc = document.createElement('img');
-    imgsrc.setAttribute("class", "img-circle img-responsive");
-    imgsrc.setAttribute("onshow", "this.src = 'https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon'");
-    people.push(["https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon", person.name, person.email]);
-  }
-  state.widget.inject(row);
-  return tbl = $(row).DataTable({
-    serverSide: true,
-    searching: false,
-    lengthMenu: [[25, 50, 100], [25, 50, 100]],
-    columnDefs: [
-      {
-        targets: 0,
-        data: "avatar",
-        render: function(data, type, full, meta) {
-          return '<img class="img-circle img-responsive" style="width: 24px; height: 24px;" src="' + full[0] + '"/>';
-        }
-      }, {
-        targets: 1,
-        data: "email",
-        render: function(data, type, full, meta) {
-          return '<a href="?page=people&email=' + full[2] + '">' + full[1] + "</a>";
-        }
+      idiv = new HTML('div', {
+        "class": "phonebook_entry"
+      });
+      left = new HTML('a', {
+        "class": "pull-left"
+      });
+      if (item.gravatar) {
+        left.inject(new HTML('img', {
+          "class": "img-circle img-reponsive",
+          src: "https://secure.gravatar.com/avatar/" + item.gravatar + ".png?d=identicon",
+          style: {
+            width: "32px",
+            height: "32px"
+          }
+        }));
       }
-    ],
-    ajax: function(data, callback, settings) {
-      var i, i1, out, ref1, ref2;
-      out = [];
-      for (i = i1 = ref1 = data.start, ref2 = data.start + data.length; ref1 <= ref2 ? i1 < ref2 : i1 > ref2; i = ref1 <= ref2 ? ++i1 : --i1) {
-        out.push(people[i]);
-      }
-      return setTimeout(function() {
-        return callback({
-          draw: data.draw,
-          data: out,
-          recordsTotal: people.length,
-          recordsFiltered: people.length
-        });
-      }, 50);
-    }
-  }, {
-    scrollY: 200,
-    scroller: {
-      loadingIndicator: true
+      right = new HTML('div', {
+        "class": "media event"
+      });
+      rightInner = new HTML('div', {
+        style: {
+          marginLeft: '10px',
+          width: '280px',
+          height: '24px',
+          display: 'inline-block',
+          overflow: 'hidden',
+          textOverflow: 'ellipsis'
+        }
+      });
+      right.inject(rightInner);
+      if (item.email) {
+        title = new HTML('a', {
+          "class": "title",
+          href: "contributors.html?page=biography&email=" + item.email
+        }, txt(item.name));
+        rightInner.inject(title);
+        rightInner.inject(' - ' + item.contributions + ' contribution' + (item.contributions !== 1 ? 's' : ''));
+      }
+      idiv.inject(left);
+      idiv.inject(right);
+      results.push(obj.inject(idiv));
     }
-  });
-
-  /*
-      card = document.createElement('div')
-      card.setAttribute("class", "col-md-3 col-sm-4 col-xs-12 profile_details")
-      well = document.createElement('div')
-      well.setAttribute("class", "well profile_view")
-      well.style.width = "100%"
-      card.appendChild(well)
-      
-      namecard = document.createElement('div')
-      namecard.setAttribute("class", "left col-xs-7")
-      img = document.createElement('div')
-      img.setAttribute("class", "right col-xs-5 text-center")
-      imgsrc = document.createElement('img')
-      imgsrc.setAttribute("class", "img-circle img-responsive")
-      imgsrc.setAttribute("src", "https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon")
-      img.appendChild(imgsrc)
-      well.appendChild(namecard)
-      well.appendChild(img)
-      a = document.createElement('a')
-      a.setAttribute('href', '?page=people&email=' + person.email)
-      name = document.createElement('h2')
-      name.appendChild(document.createTextNode(person.name))
-      a.appendChild(name)
-      namecard.appendChild(a)
-      namecard.appendChild(document.createTextNode(person.email))
-      groups = []
-      if person.tags
-          for tag in person.tags
-              if tag != '_untagged'
-                  groups.push(tag)
-      if groups.length > 0
-          namecard.appendChild(mk('br'))
-          namecard.appendChild(txt("Part of: " + groups.join(", ")))
-      
-      row.appendChild(card)
-   */
+    return results;
+  }
 };
 
 addsources = function(form) {
@@ -5300,13 +5217,8 @@ updateWidgets = function(type, target, eargs) {
         case 'widget':
           results.push(widget.load(publisher));
           break;
-        case 'contacts':
-          results.push(fetchPhonebook({
-            widget: widget,
-            w: w,
-            letter: 'a',
-            project: target
-          }));
+        case 'phonebook':
+          results.push(widget.load(phonebook));
           break;
         case 'repopicker':
           results.push(widget.load(explorer));
@@ -5388,10 +5300,10 @@ pubWidget = (function() {
 })();
 
 Widget = (function() {
-  function Widget(blocks, args1, pub) {
+  function Widget(blocks, args, pub) {
     var a, cldiv, i, li, t, tt, ul;
     this.blocks = blocks;
-    this.args = args1;
+    this.args = args;
     this.id = Math.floor(Math.random() * 1000000).toString(16);
     this.div = document.createElement('div');
     this.div.setAttribute("id", this.id);


[kibble] 03/08: regen openapi

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 7d1690775f1784724339281c63f8e1a8fe6f06bf
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:48:39 2018 +0200

    regen openapi
---
 api/yaml/openapi.yaml | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/api/yaml/openapi.yaml b/api/yaml/openapi.yaml
index bc61cc2..4caa3e4 100644
--- a/api/yaml/openapi.yaml
+++ b/api/yaml/openapi.yaml
@@ -2620,6 +2620,29 @@ paths:
       security:
       - cookieAuth: []
       summary: Shows a quick email trend summary of the past 6 months for your org
+  /api/org/contributors:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/defaultWidgetArgs'
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/contributorList'
+          description: 200 Response
+        default:
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/Error'
+          description: unexpected error
+      security:
+      - cookieAuth: []
+      summary: Shows contributors for the entire org or matching filters.
   /api/org/list:
     get:
       responses:


[kibble] 05/08: scrap old phonebook, start work on a new one

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 31f9ba6338a248c093c34a3981d5c0d8488867fa
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:49:12 2018 +0200

    scrap old phonebook, start work on a new one
---
 ui/js/coffee/phonebook.coffee | 165 +++++++++---------------------------------
 1 file changed, 34 insertions(+), 131 deletions(-)

diff --git a/ui/js/coffee/phonebook.coffee b/ui/js/coffee/phonebook.coffee
index 373e167..c43264d 100644
--- a/ui/js/coffee/phonebook.coffee
+++ b/ui/js/coffee/phonebook.coffee
@@ -1,135 +1,38 @@
-phonebook_cached = {}
 
-fetchPhonebook = (args) ->
-        if (args) 
-            wargs = JSON.stringify(args)
-            if (phonebook_cached[wargs])
-                renderPhonebook(phonebook_cached[wargs], args)
-                return
-                
-        args.widget.cog()
-        url = "people/"
+phonebook = (json, state) ->
+    items = []
+    if json.people
+        id = parseInt(Math.random()*99999999).toString(16)
+        obj = new HTML('div', { id: id})
+        obj.innerText = "Found #{json.people.length} contributors.."
+        obj.inject(new HTML('br'))
+        state.widget.inject(obj, true)
         
-        postJSON(url, args, args, renderPhonebook)
-
-setupPhonebook = (widget, w) ->
-        fetchPhonebook({ widget: widget, w: w, letter: 'a', project:  w.target or "" })
-
-
-renderPhonebook = (json, state) ->
-        wargs = JSON.stringify(state)
-        phonebook_cached[wargs] = json
-        letters = "abcdefghijklmnopqrstuvwxyz".split("")
-        row = document.createElement('div')
-        row.setAttribute("class", "row")
-        rdiv = document.createElement('div')
-        rdiv.setAttribute("class", "col-md-12 col-sm-12 col-xs-12 text-center")
-        ul = document.createElement('ul')
-        ul.setAttribute("class", "pagination pagination-split")
-        for letter in letters
-                li = document.createElement('li')
-                a = document.createElement('a')
-                a.setAttribute("href", "#")
-                a.addEventListener("click", () ->
-                        state.letter = this.childNodes[0].data.toLowerCase()
-                        fetchPhonebook(state)
-                , false)
-                a.appendChild(document.createTextNode(letter.toUpperCase()))
-                if (state.letter && letter == state.letter)
-                    li.setAttribute("class", "active")
+        json.people.sort( (a,b) =>
+                if a.name < b.name
+                        return -1
+                if a.name > b.name
+                        return 1
+                return 0
+        )
+        
+        for i, item of json.people
+                if i > 250
+                        break
+                idiv = new HTML('div', { class: "phonebook_entry"} )
+                left = new HTML('a', { class: "pull-left"})
+                if item.gravatar
+                    left.inject(new HTML('img', { class: "img-circle img-reponsive", src: "https://secure.gravatar.com/avatar/#{item.gravatar}.png?d=identicon" ,style: { width: "32px", height: "32px"}}))
+                right = new HTML('div', { class: "media event"})
+                rightInner = new HTML('div', { style: {marginLeft: '10px', width: '280px', height: '24px', display: 'inline-block', overflow: 'hidden', textOverflow: 'ellipsis'}})
+                right.inject(rightInner)
+                if item.email
+                    title = new HTML('a', { class: "title", href:"contributors.html?page=biography&email=#{item.email}"}, txt(item.name))
+                    rightInner.inject(title)
+                    rightInner.inject(' - ' + item.contributions + ' contribution' + (if item.contributions != 1 then 's' else ''))
+                idiv.inject(left)
+                idiv.inject(right)
+                obj.inject(idiv)
                 
-                li.appendChild(a)
-                ul.appendChild(li)
 
-        rdiv.appendChild(ul)
-        row.appendChild(rdiv)
-        
-        state.widget.inject(row, true)
-        
-        
-        # Render entries
-        row = mk('table', {class:"display"}, mk('thead', {}, mk('tr', {}, [mk('th', {}, 'Avatar'), mk('th', {}, 'Name'), mk('th', {}, 'Email')])))
-        
-        people = []
-        json.people.sort( (a,b) => if (a.name == b.name) then 0 else (if a.name > b.name then 1 else -1))
-        a = 0
-        for person in json.people
-            a++
-            imgsrc = document.createElement('img')
-            imgsrc.setAttribute("class", "img-circle img-responsive")
-            imgsrc.setAttribute("onshow", "this.src = 'https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon'")
-            people.push(["https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon", person.name, person.email])
-            
-        state.widget.inject(row)
-        tbl = $(row).DataTable(
-            serverSide: true,
-            searching: false,
-            lengthMenu: [[25, 50, 100], [25, 50, 100]]
-            columnDefs: [ {
-                targets: 0,
-                data: "avatar",
-                render: ( data, type, full, meta ) ->
-                  return '<img class="img-circle img-responsive" style="width: 24px; height: 24px;" src="'+full[0]+'"/>';
-            },
-             {
-                targets: 1,
-                data: "email",
-                render: ( data, type, full, meta ) ->
-                  return '<a href="?page=people&email='+full[2]+'">' + full[1] + "</a>"
-            }]
-            ajax: ( data, callback, settings ) ->
-                out = [];
-                for i in [data.start...(data.start+data.length)]
-                    out.push(people[i])
-    
-                setTimeout( () ->
-                    callback( {
-                        draw: data.draw,
-                        data: out,
-                        recordsTotal: people.length,
-                        recordsFiltered: people.length
-                    })
-                , 50 )
-        scrollY: 200,
-        scroller: {
-            loadingIndicator: true
-        })
-        
-        
-        ###
-            card = document.createElement('div')
-            card.setAttribute("class", "col-md-3 col-sm-4 col-xs-12 profile_details")
-            well = document.createElement('div')
-            well.setAttribute("class", "well profile_view")
-            well.style.width = "100%"
-            card.appendChild(well)
-            
-            namecard = document.createElement('div')
-            namecard.setAttribute("class", "left col-xs-7")
-            img = document.createElement('div')
-            img.setAttribute("class", "right col-xs-5 text-center")
-            imgsrc = document.createElement('img')
-            imgsrc.setAttribute("class", "img-circle img-responsive")
-            imgsrc.setAttribute("src", "https://secure.gravatar.com/avatar/" + person.md5 + ".png?d=identicon")
-            img.appendChild(imgsrc)
-            well.appendChild(namecard)
-            well.appendChild(img)
-            a = document.createElement('a')
-            a.setAttribute('href', '?page=people&email=' + person.email)
-            name = document.createElement('h2')
-            name.appendChild(document.createTextNode(person.name))
-            a.appendChild(name)
-            namecard.appendChild(a)
-            namecard.appendChild(document.createTextNode(person.email))
-            groups = []
-            if person.tags
-                for tag in person.tags
-                    if tag != '_untagged'
-                        groups.push(tag)
-            if groups.length > 0
-                namecard.appendChild(mk('br'))
-                namecard.appendChild(txt("Part of: " + groups.join(", ")))
-            
-            row.appendChild(card)
-        ###
-            
\ No newline at end of file
+        
\ No newline at end of file


[kibble] 02/08: json needs to be marked as unicode

Posted by hu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

humbedooh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kibble.git

commit 7a4bb34b538065e80f5b9e5459b93b0d43069aae
Author: Daniel Gruno <hu...@apache.org>
AuthorDate: Mon Sep 17 09:48:27 2018 +0200

    json needs to be marked as unicode
---
 api/plugins/session.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/api/plugins/session.py b/api/plugins/session.py
index 08caa98..6476135 100644
--- a/api/plugins/session.py
+++ b/api/plugins/session.py
@@ -97,7 +97,7 @@ class KibbleSession(object):
         self.config = config
         self.user = None
         self.DB = DB
-        self.headers = [('Content-Type', 'application/json')]
+        self.headers = [('Content-Type', 'application/json; charset=utf-8')]
         self.cookie = None
         
         # Construct the URL we're visiting