xmosaicsource: move sources management from xmosaicframe to xmosaicsource

(related to #290474)

authorSamuel Trégouët <samuel.tregouet@logilab.fr>
changeseta13d46e7ef7b
branchdefault
phasepublic
hiddenno
parent revision#e42b0a6715ee xmosaicsource: add fetch capability (related to #290474)
child revision#baaa771c97f4 xmosaicsource: rename event to a more specific one + enable bubbling
files modified by this revision
app/portfolio.js
components/xmosaicframe/xmosaicframe.es6
components/xmosaicframe/xmosaicframe.html
components/xmosaicsource/xmosaicsource.html
components/xmosaicsource/xmosaicsource.js
# HG changeset patch
# User Samuel Trégouët <samuel.tregouet@logilab.fr>
# Date 1429001721 -7200
# Tue Apr 14 10:55:21 2015 +0200
# Node ID a13d46e7ef7bdaab9593e1640e8de63d50ebad42
# Parent e42b0a6715ee39c1dfcfd394aa6766f791dcc96a
xmosaicsource: move sources management from xmosaicframe to xmosaicsource

(related to #290474)

diff --git a/app/portfolio.js b/app/portfolio.js
@@ -5,11 +5,11 @@
1      let frames = root.getElementById('frames');
2 
3      let btn_frame = root.getElementById('addFrame');
4      btn_frame.addEventListener('click', function(ev) {
5          let frame = root.createElement('x-mosaic-frame');
6 -        frame.innerHTML = 'title';
7 +        frame.appendChild(root.createElement('x-mosaic-source'));
8          frames.appendChild(frame);
9      });
10 
11      let btn_text = root.getElementById('addText');
12      btn_text.addEventListener('click', function(ev) {
diff --git a/components/xmosaicframe/xmosaicframe.es6 b/components/xmosaicframe/xmosaicframe.es6
@@ -1,228 +1,62 @@
13  /* global $ */
14  /* jshint esnext: true */
15  (function init(ownerDocument) {
16      'use strict';
17 
18 +    var slice = Array.prototype.slice;
19 +
20      function initXmosaicframe(host, ownerDocument) {
21          // clone template into shadowroot
22          let template = ownerDocument.querySelector('#x-mosaic-frame-template');
23          let clone = document.importNode(template.content, true);
24          let root = host.createShadowRoot();
25          let registry = require('registry');
26          root.appendChild(clone);
27          var qs = root.querySelector.bind(root);
28 
29          var editNode = qs('#edit'),
30 -            formNode = qs('form'),
31 +            editControl = qs('#edit-control'),
32 +            addSource = qs('#add-source'),
33 +            hideSource = qs('#hide-source'),
34              panelNode = qs('#panel'),
35 -            frameBody = qs('#panel .panel-body'),
36 -            vidOptionsNode = qs('#select-vid');
37 +            frameBody = qs('#panel .panel-body');
38 
39          function showEdit() {
40 +            var children = slice.call(host.childNodes);
41 +            children.forEach(function(el) {
42 +                el.displayForm();
43 +            });
44 +            editControl.style.display = 'block';
45              panelNode.style.display = 'none';
46 -            formNode.style.display = 'block';
47          }
48          function showResult() {
49 +            var children = slice.call(host.childNodes);
50 +            children.forEach(function(el) {
51 +                el.hideForm();
52 +            });
53              panelNode.style.display = 'block';
54 -            formNode.style.display = 'none';
55 -        }
56 -        function fillForm(data) {
57 -            qs('input[name="baseurl"]').value = data.baseurl;
58 -            qs('textarea[name="query"]').value = data.query;
59 -        }
60 -        function showButtonViews(sourceName) {
61 -            // build viewNames list
62 -            var sourceViews = registry.views[sourceName];
63 -            var viewNames = ['auto'];
64 -            viewNames.push.apply(viewNames,
65 -                                 !!sourceViews ? Object.keys(sourceViews) : []);
66 -            // remove radio button
67 -            vidOptionsNode.textContent = '';
68 -            // add new radio buttons
69 -            viewNames.forEach(function(viewName, idx) {
70 -                var label = document.createElement('label'),
71 -                    input = document.createElement('input'),
72 -                    text = document.createTextNode(viewName);
73 -                input.setAttribute('name', 'vid');
74 -                input.setAttribute('type', 'radio');
75 -                input.setAttribute('value', viewName);
76 -                if (idx === 0) {
77 -                    input.setAttribute('checked', 'checked');
78 -                }
79 -                label.appendChild(input);
80 -                label.appendChild(text);
81 -                vidOptionsNode.appendChild(label);
82 -            });
83 -        }
84 -        // generate initial vid radio buttons
85 -        showButtonViews('sparql');
86 -
87 -        var dataset = host.dataset;
88 -        if (('source' in dataset) && ('baseurl' in dataset) && ('query' in dataset)) {
89 -            fillForm(dataset);
90 -            queryUpdated(host, ownerDocument, registry);
91 -            showResult();
92 +            editControl.style.display = 'none';
93          }
94 
95 -        qs('#select-source').addEventListener('change', function(ev) {
96 -            var sourceName = ev.target.value;
97 -            showButtonViews(sourceName);
98 +        hideSource.addEventListener('click', showResult);
99 +        addSource.addEventListener('click', function() {
100 +            host.appendChild(document.createElement('x-mosaic-source'));
101          });
102 +
103          editNode.addEventListener('click', showEdit);
104 -        formNode.addEventListener('submit', function(e) {
105 -            host.dataset.source = qs('input[name="source"]:checked').value;
106 -            host.dataset.baseurl = qs('input[name="baseurl"]').value;
107 -            host.dataset.query = qs('textarea[name="query"]').value;
108 -            host.dataset.vid = qs('input[name="vid"]:checked').value;
109 -            queryUpdated(host, ownerDocument, registry);
110 -            showResult();
111 -            e.preventDefault();
112 -        });
113 +
114          qs('#remove-frame').addEventListener('click', function(e) {
115              host.remove();
116          });
117          qs('#toggle-frame').addEventListener('click', function(e) {
118              frameBody.classList.toggle('fold');
119              e.currentTarget.classList.toggle('active');
120          });
121      }
122 
123 
124 -    function queryUpdated(host, ownerDocument, registry) {
125 -        let sourceviews = registry.views[host.dataset.source],
126 -            frameContext = {
127 -                rset: null,     // rset returned by the server
128 -                reqUrl: null,   // full url built from the data-query attribute
129 -                xhr: null       // request emited
130 -            };
131 -
132 -        function neo4jFetch(baseurl, query) {
133 -            return $.ajax({
134 -                url: baseurl,
135 -                accepts: "application/json; charset=UTF-8",
136 -                dataType: "json",
137 -                data: {
138 -                    "query": query,
139 -                    "params": {}
140 -                },
141 -                type: "POST"
142 -            });
143 -        }
144 -
145 -        function sparqlFetch(baseurl, query) {
146 -            return $.ajax({
147 -                url: baseurl,
148 -                accepts: {
149 -                    'json': "application/sparql-results+json"
150 -                },
151 -                data: {
152 -                    'query': query,
153 -                    'defaul-graph-uri': '',
154 -                    'shuod-sponge': '',
155 -                    'format': 'application/sparql-results+json',
156 -                    'debug': 'on',
157 -                    'timeout': 0
158 -                },
159 -                type: "GET"
160 -            });
161 -        }
162 -
163 -
164 -        function cwFetch(baseurl, query) {
165 -            return $.ajax({
166 -                url: baseurl,
167 -                accepts: "application/json; charset=UTF-8",
168 -                dataType: "json",
169 -                xhrFields: {
170 -                    withCredentials: true
171 -                },
172 -                data: {
173 -                    "rql": query,
174 -                    "vid": 'ejsonexport'
175 -                },
176 -                type: "GET"
177 -            });
178 -        }
179 -
180 -        function httpFetch(baseurl, query) {
181 -            // join baseurl and query with a `/`
182 -            var queryPath = query.replace(/^\//, ''),
183 -                baseUrl = baseurl.replace(/\/$/, ''),
184 -                url = queryPath ? baseUrl + '/' + queryPath : baseUrl;
185 -            frameContext.reqUrl = url;
186 -            return $.ajax({
187 -                url: url,
188 -                type: "HEAD"
189 -            });
190 -        }
191 -
192 -
193 -        function applyView(vid, ctx) {
194 -            let body = host.shadowRoot.querySelector('#mosaic-frame-content');
195 -            while (body.firstChild) {
196 -                body.removeChild(body.firstChild);
197 -            }
198 -            if (vid === 'auto') {
199 -                vid = Object.keys(sourceviews)[0];
200 -            }
201 -            if (sourceviews.hasOwnProperty(vid)) {
202 -                body.appendChild(sourceviews[vid](ctx));
203 -            } else {
204 -                console.log('view %s not implemented', vid);
205 -            }
206 -        }
207 -
208 -        function buildViewsMenu() {
209 -            // build menu
210 -            if (!sourceviews) {
211 -                return;
212 -            }
213 -            let menu = host.shadowRoot.querySelector('#view-menu');
214 -            // firt empty menu
215 -            menu.textContent = '';
216 -            for (let viewname of Object.keys(sourceviews)) {
217 -                let item = document.createElement('li');
218 -                menu.appendChild(item);
219 -                let button = document.createElement('button');
220 -                button.classList.add('btn');
221 -                button.classList.add('btn-default');
222 -                item.appendChild(button);
223 -                button.textContent = viewname;
224 -                button.addEventListener('click', function() {
225 -                    applyView(viewname, frameContext);
226 -                });
227 -            }
228 -        }
229 -
230 -        function submitQuery(query) {
231 -            var fetcher = null;
232 -            if (host.dataset.source === 'neo4j') {
233 -                fetcher = neo4jFetch;
234 -            } else if (host.dataset.source === 'sparql') {
235 -                fetcher = sparqlFetch;
236 -            } else if (host.dataset.source === 'cw') {
237 -                fetcher = cwFetch;
238 -            } else if (host.dataset.source === 'http') {
239 -                fetcher = httpFetch;
240 -            }
241 -            fetcher(host.dataset.baseurl, host.dataset.query)
242 -                .done(function(data, status, xhr) {
243 -                    frameContext.rset = data;
244 -                    frameContext.xhr = xhr;
245 -                    let vid = host.dataset.vid || 'table';
246 -                    applyView(vid, frameContext);
247 -                })
248 -                .fail(function(xhr, err, msg) {
249 -                    console.log(xhr, err, msg);
250 -                });
251 -
252 -        }
253 -        buildViewsMenu();
254 -        submitQuery(host.dataset.query);
255 -    }
256 -
257      function register(importDoc) {
258          var proto = Object.create(HTMLElement.prototype);
259          proto.createdCallback = function() {
260              initXmosaicframe(this, importDoc);
261          };
diff --git a/components/xmosaicframe/xmosaicframe.html b/components/xmosaicframe/xmosaicframe.html
@@ -51,35 +51,15 @@
262 
263    #panel:hover .mosaic-sidebar {
264      transform: scaleX(1);
265    }
266    </style>
267 -  <form>
268 -    <div class="form-group">
269 -      <label for="baseurl">source base url</label>
270 -      <input type="url" class="form-control" name="baseurl" placeholder="http://your.source.org" value="http://fr.dbpedia.org/sparql">
271 -    </div>
272 -    <div id="select-source" class="radio">
273 -      <label>
274 -        <input type="radio" name="source" value="http" /> HTTP
275 -      </label>
276 -      <label>
277 -        <input type="radio" name="source" value="neo4j" /> Neo4J
278 -      </label>
279 -      <label>
280 -        <input type="radio" name="source" value="sparql" checked="checked" /> SPARQL
281 -      </label>
282 -      <label>
283 -        <input type="radio" name="source" value="cw" /> CubicWeb
284 -      </label>
285 -    </div>
286 -    <div class="form-group">
287 -      <textarea class="form-control" name="query" rows="3" cols="120">SELECT ?s ?p ?o WHERE {?s ?p ?o} LIMIT 10</textarea>
288 -    </div>
289 -    <div id="select-vid" class="radio"></div>
290 -    <button type="submit" class="btn bnt-default">Submit</button>
291 -  </form>
292 +  <div id="edit-control">
293 +    <button id="hide-source" class="btn btn-default">hide sources</button>
294 +    <button id="add-source" class="btn btn-default">add source</button>
295 +  </div>
296 +  <content></content>
297 
298    <div id="panel" class="mosaic-frame panel panel-default">
299      <div class="panel-body mosaic-cell-body">
300        <div class="mosaic-sidebar">
301          <div class="navbar navbar-default navbar-right navbar-collapse">
diff --git a/components/xmosaicsource/xmosaicsource.html b/components/xmosaicsource/xmosaicsource.html
@@ -1,3 +1,43 @@
302  <template>
303 +  <style>
304 +    @import url("css/vendor.css"); /* XXX fix need for absolute path */
305 +    form {
306 +       box-shadow: 2px 2px 15px #ccc;
307 +       border-radius: 3px;
308 +       padding: 5px;
309 +       margin: 5px;
310 +    }
311 +    .pull-right-button {
312 +      display: flex;
313 +      justify-content: flex-end;
314 +    }
315 +  </style>
316 +  <form>
317 +    <div class="form-group">
318 +      <label for="baseurl">source base url</label>
319 +      <input type="url" class="form-control" name="baseurl" placeholder="http://your.source.org" value="http://fr.dbpedia.org/sparql">
320 +    </div>
321 +    <div id="select-source" class="radio">
322 +      <label>
323 +        <input type="radio" name="source" value="http" /> HTTP
324 +      </label>
325 +      <label>
326 +        <input type="radio" name="source" value="neo4j" /> Neo4J
327 +      </label>
328 +      <label>
329 +        <input type="radio" name="source" value="sparql" checked="checked" /> SPARQL
330 +      </label>
331 +      <label>
332 +        <input type="radio" name="source" value="cw" /> CubicWeb
333 +      </label>
334 +    </div>
335 +    <div class="form-group">
336 +      <textarea class="form-control" name="query" rows="3" cols="120">SELECT ?s ?p ?o WHERE {?s ?p ?o} LIMIT 10</textarea>
337 +    </div>
338 +    <div id="select-vid" class="radio"></div>
339 +    <div class="pull-right-button">
340 +      <button type="submit" class="btn bnt-default">Submit</button>
341 +    </div>
342 +  </form>
343  </template>
344  <script src="./xmosaicsource.js"></script>
diff --git a/components/xmosaicsource/xmosaicsource.js b/components/xmosaicsource/xmosaicsource.js
@@ -102,10 +102,38 @@
345                      }
346                  }));
347              }.bind(this));
348      };
349 
350 +    xSourceProto.createdCallback = function createdCallback() {
351 +        var template = ownerDocument.querySelector('template');
352 +        var clone = document.importNode(template.content, true);
353 +        var root = this.createShadowRoot();
354 +        root.appendChild(clone);
355 +        var qs = root.querySelector.bind(root);
356 +        this.formNode = qs('form');
357 +
358 +        this.formNode.addEventListener('submit', function(ev) {
359 +            var dataset = this.dataset;
360 +            dataset.source = qs('input[name="source"]:checked').value;
361 +            dataset.baseurl = qs('input[name="baseurl"]').value;
362 +            dataset.query = qs('textarea[name="query"]').value;
363 +            this.updateQuery();
364 +            ev.preventDefault();
365 +            if (dataset.autohide) {
366 +                this.hideForm();
367 +            }
368 +        }.bind(this));
369 +    };
370 +
371 +    xSourceProto.displayForm = function displayForm() {
372 +        this.formNode.style.display = 'block';
373 +    };
374 +    xSourceProto.hideForm = function hideForm() {
375 +        this.formNode.style.display = 'none';
376 +    };
377 +
378      xSourceProto.attachedCallback = function attachedCallback() {
379          this.updateQuery();
380      };
381 
382