changeset 1714:f2265601ead6

edit-choice/etc fixes and tests Ignore-this: 8676aaddd402c023712efb4f4112d982
author Drew Perttula <drewp@bigasterisk.com>
date Fri, 04 May 2018 08:05:18 +0000
parents bd0c83b063df
children 46c1ed2b0fb8
files light9/web/edit-choice-demo.html light9/web/edit-choice.coffee light9/web/edit-choice.html light9/web/edit-choice_test.html light9/web/graph.coffee light9/web/paint/paint-report-elements.html light9/web/rdfdb-synced-graph.html light9/web/rdfdb-synced-graph_test.html light9/web/resource-display.html light9/web/resource-display_test.html light9/web/style.css
diffstat 11 files changed, 375 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/light9/web/edit-choice-demo.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/edit-choice-demo.html	Fri May 04 08:05:18 2018 +0000
@@ -3,7 +3,8 @@
   <head>
     <title></title>
     <meta charset="utf-8" />
-    <script src="/lib/webcomponentsjs/webcomponents-hi-sd-ce.js"></script>
+       <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
+
     <link rel="import" href="rdfdb-synced-graph.html">
     <link rel="import" href="edit-choice.html">
     <script src="/node_modules/n3/n3-browser.js"></script>
--- a/light9/web/edit-choice.coffee	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/edit-choice.coffee	Fri May 04 08:05:18 2018 +0000
@@ -42,13 +42,14 @@
 
 
 
-Polymer
-    is: "edit-choice",
-    properties:
+class EditChoice extends Polymer.Element
+    @is: "edit-choice",
+    @properties:
         graph: {type: Object, notify: true},
         uri: {type: String, notify: true},
 
-    ready: ->
+    connectedCallback: ->
+      super.connectedCallback()
       @uri = null
       setupDrop @$.box, @$.box, null, (uri) =>
         @uri=uri
@@ -57,3 +58,4 @@
     unlink: ->
       @uri = null
 
+customElements.define(EditChoice.is, EditChoice)
\ No newline at end of file
--- a/light9/web/edit-choice.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/edit-choice.html	Fri May 04 08:05:18 2018 +0000
@@ -9,6 +9,7 @@
          display: inline-block;
          background: #141448;
          min-width: 10em;
+         padding: 3px 8px;
      }
      #box.dragging {
          background: rgba(126, 52, 245, 0.0784313725490196);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/light9/web/edit-choice_test.html	Fri May 04 08:05:18 2018 +0000
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+  <head>
+    <title>edit-choice test</title>
+    <meta charset="utf-8">
+    <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
+    <script src="/node_modules/mocha/mocha.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+
+    <link rel="stylesheet" media="all" href="/node_modules/mocha/mocha.css">
+    <link rel="import" href="/lib/polymer/lib/elements/dom-bind.html">
+
+    <link rel="import" href="rdfdb-synced-graph.html">
+    <link rel="import" href="edit-choice.html">
+  </head>
+  <body>
+    <div id="mocha"><p><a href=".">Index</a></p></div>
+    <div id="messages"></div>
+    <div id="fixtures">
+      <dom-bind>
+        <template>
+          <p>
+            <rdfdb-synced-graph id="graph" test-graph="true" graph="{{graph}}"></rdfdb-synced-graph>
+          </p>
+          <p>
+            edit-choice: <edit-choice id="ec" graph="{{graph}}" uri="http://example.com/a"></edit-choice>
+          </p>
+        </template>
+      </dom-bind>
+    </div>
+    
+    <script>
+     mocha.setup('bdd')
+     const assert = chai.assert;
+     
+     describe("resource-display", () => {
+         let ec;
+         let graph;
+         beforeEach((done) => {
+             ec = document.querySelector("#ec");
+             window.ec=ec;
+             graph = document.querySelector("#graph");
+             graph.graph.clearGraph();
+             graph.graph.loadTrig(`
+                       @prefix : <http://example.com/> .
+                       @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+                       :a rdfs:label "label a" :ctx .
+                     `, done);
+         });
+         it("shows the uri as a resource-display");
+         it("accepts a drop event and changes the uri");
+         it("clears uri when you click unlink");
+         
+     }); 
+     mocha.run();
+    </script>
+  </body>
+</html>
--- a/light9/web/graph.coffee	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/graph.coffee	Fri May 04 08:05:18 2018 +0000
@@ -139,8 +139,10 @@
     @clearGraph()
 
     if @patchSenderUrl
-      @_client = new RdfDbClient(@patchSenderUrl, @_clearGraphOnNewConnection.bind(@),
-                                 @_applyPatch.bind(@), @setStatus)
+      @_client = new RdfDbClient(@patchSenderUrl,
+                                 @_clearGraphOnNewConnection.bind(@),
+                                 @_applyPatch.bind(@),
+                                 @setStatus)
     
   clearGraph: ->
     # just deletes the statements; watchers are unaffected.
@@ -185,6 +187,8 @@
     patch = {delQuads: [], addQuads: []}
     parser = N3.Parser()
     parser.parse trig, (error, quad, prefixes) =>
+                  if error
+                    throw new Error(error)
                   if (quad)
                     patch.addQuads.push(quad)
                   else
@@ -287,10 +291,13 @@
 
   labelOrTail: (uri) ->
     try
-      @graph.stringValue(uri, @graph.Uri('rdfs:label'))
+      ret = @stringValue(uri, @Uri('rdfs:label'))
     catch
-      words = uri.split('/')
-      words[words.length-1]
+      words = uri.value.split('/')
+      ret = words[words.length-1]
+    if not ret
+      ret = uri.value
+    return ret
 
   objects: (s, p) ->
     @_autoDeps.askedFor(s, p, null, null)
--- a/light9/web/paint/paint-report-elements.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/paint/paint-report-elements.html	Fri May 04 08:05:18 2018 +0000
@@ -49,7 +49,7 @@
             
           </svg>
           <div id="sources">
-            <div>
+            <div class="effectLike" draggable="true">
               <light9-capture-image name="aura1" path="show/dance2017/capture/moving1/cap258592/pic1.jpg"></light9-capture-image>
               <light9-device-settings></light9-device-settings>
             </div>
--- a/light9/web/rdfdb-synced-graph.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/rdfdb-synced-graph.html	Fri May 04 08:05:18 2018 +0000
@@ -1,9 +1,12 @@
-<link rel="import" href="/lib/polymer/polymer.html">
+<link rel="import" href="/lib/polymer/polymer-element.html">
+<script src="/node_modules/n3/n3-browser.js"></script>
+<script src="/lib/async/dist/async.js"></script>
+      <script src="/lib/underscore/underscore-min.js"></script>
 
 <dom-module id="rdfdb-synced-graph">
   <template>
     <style>
-     span {
+     :host {
          display: inline-block;
          border: 1px solid gray;
          width: 18em;
@@ -11,27 +14,37 @@
          color: #4fc1d4;
      }
     </style>
-    <span>[[status]]</span>
+    graph: [[status]]
   </template>
   <script src="rdfdbclient.js"></script>
   <script src="graph.js"></script>
   <script>
-   Polymer({
-       is: "rdfdb-synced-graph",
-       properties: {
-           graph: {type: Object, notify: true},
-           status: {type: String, notify: true}
-       },
-       ready: function() {
-           this.graph = new SyncedGraph('/rdfdb/syncedGraph', {
-               '': 'http://light9.bigasterisk.com/',
-               'dev': 'http://light9.bigasterisk.com/device/',
-               'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
-               'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
-               'xsd': 'http://www.w3.org/2001/XMLSchema#',
-           }, function(s) { this.status = s; }.bind(this));
+   class RdfdbSyncedGraph extends Polymer.Element {
+       static get is() { return "rdfdb-synced-graph"; }
+       
+       static get properties() {
+           return {
+               graph: {type: Object, notify: true},
+               status: {type: String, notify: true},
+               testGraph: {type: Boolean},
+           }
+       }
+       
+       connectedCallback() {
+           super.connectedCallback();
+           this.graph = new SyncedGraph(
+               this.testGraph ? null : '/rdfdb/syncedGraph',
+               {
+                   '': 'http://light9.bigasterisk.com/',
+                   'dev': 'http://light9.bigasterisk.com/device/',
+                   'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+                   'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
+                   'xsd': 'http://www.w3.org/2001/XMLSchema#',
+               },
+               function(s) { this.status = s; }.bind(this));
            window.graph = this.graph;
        }
-   });
+   }
+   customElements.define(RdfdbSyncedGraph.is, RdfdbSyncedGraph);
   </script>
 </dom-module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/light9/web/rdfdb-synced-graph_test.html	Fri May 04 08:05:18 2018 +0000
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+  <head>
+    <title>rdfdb-synced-graph test</title>
+    <meta charset="utf-8">
+    <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
+    <script src="/node_modules/mocha/mocha.js"></script>
+    <script src="/node_modules/chai/chai.js"></script>
+    <link rel="stylesheet" media="all" href="/node_modules/mocha/mocha.css">
+    <link rel="import" href="/lib/polymer/lib/elements/dom-bind.html">
+
+    <link rel="import" href="rdfdb-synced-graph.html">
+  </head>
+  <body>
+    <div id="mocha"><p><a href=".">Index</a></p></div>
+    <div id="messages"></div>
+    <div id="fixtures">
+      <dom-bind>
+        <template>
+          <rdfdb-synced-graph id="graph" test-graph="true" graph="{{graph}}"></rdfdb-synced-graph>
+        </template>
+      </dom-bind>
+    </div>
+    
+    <script>
+     mocha.setup('bdd');
+     const assert = chai.assert;
+     
+     describe("rdfdb-synced-graph", () => {
+         let elem;
+         beforeEach(() => {
+             elem = document.querySelector("#graph");
+             window.g = elem;
+             elem.graph.clearGraph();
+         });
+         it("makes a node", () => {
+             assert.equal(elem.tagName, "RDFDB-SYNCED-GRAPH");
+         });
+         it("loads trig", (done) => {
+             elem.graph.loadTrig(`
+                       @prefix : <http://example.com/> .
+                       :a :b :c :d .
+                     `, () => {
+                         assert.equal(elem.graph.quads().length, 1);
+                         done();
+                     });
+         });
+     }); 
+     mocha.run();
+    </script>
+  </body>
+</html>
--- a/light9/web/resource-display.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/resource-display.html	Fri May 04 08:05:18 2018 +0000
@@ -1,23 +1,48 @@
-<link rel="import" href="/lib/polymer/polymer.html">
+<link rel="import" href="/lib/polymer/polymer-element.html">
 <link rel="import" href="/lib/paper-dialog/paper-dialog.html">
 <link rel="import" href="/lib/paper-button/paper-button.html">
-<link rel="stylesheet" href="/style.css">
 
 <dom-module id="resource-display">
   <template>
     <style>
      :host {
          display: inline-block;
-         zvertical-align: top;
-         zborder: 2px rgba(84, 84, 84, 0.27) outset;
-         zborder-radius: 9px;
-         zpadding: 2px;
+     }
+     
+     a.resource {
+         color: inherit;
+         text-decoration: none;
+     }
+
+     .resource {
+         border: 1px solid #545454;
+         border-radius: 5px;
+         padding: 1px;
+         margin: 2px;
+         background: rgb(49, 49, 49);
+         display: inline-block;
+         text-shadow: 1px 1px 2px black;
+     }
+     .resource.minor {
+         background: none;
+         border: none;
+     }
+     .resource a {
+         color: rgb(150, 150, 255);
+         padding: 1px;
+         display: inline-block;
+     }
+     .resource.minor a {
+         text-decoration: none;
+         color: rgb(155, 155, 193);
+         padding: 0;
      }
     </style>
-    <span class$="[[resClasses]]"><a href="{{uri.value}}">
-      <!-- type icon goes here -->
-      {{label}}
-    </a></span>
+
+    <span class$="[[resClasses]]">
+      <a href="{{href}}" id="uri">
+        <!-- type icon goes here -->{{label}}</a>
+    </span>
     <template is="dom-if" if="{{rename}}">
       <button on-click="onRename">Rename</button>
 
@@ -33,71 +58,96 @@
           <paper-button dialog-dismiss>Cancel</paper-button>
           <paper-button dialog-confirm>OK</paper-button>
         </div>
-      </paper-dialog>
-      
+      </paper-dialog>     
     </template>
+    
   </template>
   <script>
-   Polymer({
-       is: "resource-display",
-       properties: {
-           graph: { type: Object },
-           uri: { type: Object }, // Use .value for the string
-           label: { type: String },
-           rename: { type: Boolean },
-           minor: { type: Boolean },
-           resClasses: { type: String, computed: '_resClasses(minor)', value: 'resource' },
-           renameTo: { type: String, notify: true },
-       },
-       observers: ['onUri(graph, uri)'],
-       _resClasses: function(minor) {
+   class ResourceDisplay extends Polymer.Element {
+       static get is() { return "resource-display"; }
+       static get properties() {
+           return {
+               graph: { type: Object },
+               // callers might set this as string or NamedNode.
+               uri: { type: Object }, // Use .value for the string
+               href: { type: String },
+               label: { type: String },
+               rename: { type: Boolean },
+               minor: { type: Boolean },
+               resClasses: { type: String, computed: '_resClasses(minor)', value: 'resource' },
+               renameTo: { type: String, notify: true },
+           };
+       }
+       static get observers() { return ['onUri(graph, uri)']; }
+       
+       _resClasses(minor) {
            return minor ? 'resource minor' : 'resource';
-       },
-       onUri: function(graph, uri) {
-           if (!this.graph || !this.uri) return;
-           this.graph.runHandler(this.setLabel.bind(this), `label ${this.uri.value}`);
-       },
-       setLabel: function() {
+       }
+       
+       onUri(graph, uri) {
+           if (!this.graph) {
+               this.label = "...";
+               this.href = "javascript:;'";
+               return;
+           }
+           if (!this.uri) {
+               this.setLabel();
+               return;
+           }
+           if (typeof uri === 'string') {
+               uri = this.graph.Uri(uri);
+           }
+           this.graph.runHandler(this.setLabel.bind(this),
+                                 `label ${uri.value}`);
+       }
+       
+       setLabel() {
            if (!this.uri) {
                this.label = "<no uri>";
+               this.href = "javascript:;";
                return;
            }
-           try {
-               this.label = this.graph.stringValue(this.uri,
-                                                   this.graph.Uri('rdfs:label'));
-           } catch(e) {
-               this.label = null;
-           }
-           if (!this.label) {
-               this.label = this.uri.value.replace(/.*\//, '');
+           let uri = this.uri;
+           if (typeof uri === 'string') {
+               uri = this.graph.Uri(uri);
            }
-       },
-       onRename: function() {
+           this.label = this.graph.labelOrTail(uri);
+           this.href = uri.value;
+       }
+       
+       onRename() {
            this.renameTo = this.label;
-           this.querySelector("#renameDialog").open();
-           this.querySelector("#renameTo").setSelectionRange(0, -1);
-       },
-       onRenameKey: function(ev) {
+           this.shadowRoot.querySelector("#renameDialog").open();
+           this.shadowRoot.querySelector("#renameTo").setSelectionRange(0, -1);
+       }
+       
+       onRenameKey(ev) {
            if (ev.key == 'Enter') {
-               this.querySelector("[dialog-confirm]").click();
+               this.shadowRoot.querySelector("[dialog-confirm]").click();
            }
            if (ev.key == 'Escape') {
-               this.querySelector("[dialog-dismiss]").click();
+               this.shadowRoot.querySelector("[dialog-dismiss]").click();
            }
-       },
-       onRenameClosed: function() {
-           var dialog = this.querySelector("#renameDialog");
+       }
+       
+       onRenameClosed() {
+           var dialog = this.shadowRoot.querySelector("#renameDialog");
            if (dialog.closingReason.confirmed) {
                var label = this.graph.Uri('rdfs:label');
                var ctxs = this.graph.contextsWithPattern(this.uri, label, null);
                if (ctxs.length != 1) {
-                   throw new Error(`${ctxs.length} label stmts for ${this.uri.label}`);
+                   throw new Error(
+                       `${ctxs.length} label stmts for ${this.uri.label}`);
                }
-               this.graph.patchObject(this.uri, label,
-                                      this.graph.Literal(this.renameTo),
-                                      ctxs[0]);
+               this.graph.patchObject(
+                   ((typeof this.uri) === 'string' ?
+                    this.graph.Uri(this.uri) : this.uri),
+                   label,
+                   this.graph.Literal(this.renameTo),
+                   ctxs[0]);
            }
        }
-   });
+   }
+   customElements.define(ResourceDisplay.is, ResourceDisplay);
   </script>
 </dom-module>
--- a/light9/web/resource-display_test.html	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/resource-display_test.html	Fri May 04 08:05:18 2018 +0000
@@ -3,32 +3,120 @@
   <head>
     <title>resource-display test</title>
     <meta charset="utf-8">
-    <link rel="stylesheet" media="all" href="/node_modules/mocha/mocha.css">
-    <link rel="import" href="edit-choice.html">
-
-  </head>
-  <body>
-    <div id="test" style="margin:70px; background:#555"></div>
-    <div id="mocha"><p><a href=".">Index</a></p></div>
-    <div id="messages"></div>
-    <div id="fixtures"></div>
+    <script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
     <script src="/node_modules/mocha/mocha.js"></script>
     <script src="/node_modules/chai/chai.js"></script>
 
+    <link rel="stylesheet" media="all" href="/node_modules/mocha/mocha.css">
+    <link rel="import" href="/lib/polymer/lib/elements/dom-bind.html">
+
+    <link rel="import" href="rdfdb-synced-graph.html">
+    <link rel="import" href="resource-display.html">
+  </head>
+  <body>
+    <div id="mocha"><p><a href=".">Index</a></p></div>
+    <div id="messages"></div>
+    <div id="fixtures">
+      <dom-bind>
+        <template>
+          <p>
+            <rdfdb-synced-graph id="graph" test-graph="true" graph="{{graph}}"></rdfdb-synced-graph>
+          </p>
+          <p>
+            resource: <resource-display
+                          id="elem"
+                          graph="{{graph}}"
+                          uri="http://example.com/a"></resource-display>
+          </p>
+        </template>
+      </dom-bind>
+    </div>
     
-    <script>mocha.setup('bdd')
+    <script>
+     mocha.setup('bdd')
+     const assert = chai.assert;
+     
      describe("resource-display", () => {
-         let ec;
-         beforeEach(() => {
-             const top = document.querySelector("#test");
-             top.innerHTML = '';
-             ec = document.createElement("edit-choice");
-             top.appendChild(ec);
+         let elem;
+         let graph;
+         beforeEach((done) => {
+             elem = document.querySelector("#elem");
+             window.elem = elem;
+             graph = document.querySelector("#graph");
+             graph.graph.clearGraph();
+             graph.graph.loadTrig(`
+      @prefix : <http://example.com/> .
+      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+      :a rdfs:label "label a" :ctx .
+      :b rdfs:label "label b" :ctx .
+      `, done);
+         });
+         const assertLabelTextEquals = (expected) => {
+             assert.equal(elem.shadowRoot.querySelector("#uri").innerText,
+                          expected);
+             
+         };
+         describe('link display', () => {
+         it("says no uri", () => {
+             elem.setAttribute('uri', '');
+             assertLabelTextEquals("<no uri>");
+         });
+         it("has no link when there's no uri", () => {
+             elem.setAttribute('uri', '');
+             assert.equal(elem.shadowRoot.querySelector("#uri").href,
+                          'javascript:;');
+         });
+         it("shows uri's label if graph has one", () => {
+             elem.setAttribute('uri', 'http://example.com/a');
+             assertLabelTextEquals("label a");
+         });
+         it("links to uri", () => {
+             elem.setAttribute('uri', 'http://example.com/a');
+             assert.equal(elem.shadowRoot.querySelector("#uri").href,
+                          'http://example.com/a');
          });
-         it("makes a node", () => {
-             assert(ec.tag == "E");
+         it("falls back to uri tail if there's no label", () => {
+             elem.setAttribute('uri', 'http://example.com/nolabel');
+             assertLabelTextEquals("nolabel");
+         });
+         it("falls back to full uri if the tail would be empty", () => {
+             elem.setAttribute('uri', 'http://example.com/');
+             assertLabelTextEquals('http://example.com/');
+
+         });
+         it("changes the label if the graph updates uri's label", () => {
+             const g = graph.graph;
+             elem.setAttribute('uri', 'http://example.com/a');
+
+             g.patchObject(g.Uri('http://example.com/a'),
+                           g.Uri('rdfs:label'),
+                           g.Literal('new label'));
+             assertLabelTextEquals('new label');
+
          });
+         it("changes the label if the uri changes", (done) => {
+             elem.setAttribute('uri', 'http://example.com/a');
+             setTimeout(() => {
+                 elem.setAttribute('uri', 'http://example.com/b');
+                 assertLabelTextEquals('label b');
+                 done();
+             }, 100);
+         });
+         });
+         describe('type icons', () => {
+             it("omits icon for unknown type");
+             it("uses icon uri from graph and shows the icon");
+         });
+         describe('rename ui', () => {
+             it("shows rename button if caller wants");
+             it("opens dialog when you click rename");
+             it("shows old label in dialog, ready to be replaced");
+             it("does nothing if you cancel");
+             it("patches the graph if you accept a new name");
+         });
+         
      }); 
-     mocha.run();</script>
+     mocha.run();
+    </script>
   </body>
 </html>
--- a/light9/web/style.css	Fri May 04 07:58:13 2018 +0000
+++ b/light9/web/style.css	Fri May 04 08:05:18 2018 +0000
@@ -145,34 +145,7 @@
 .vari {
     color: white;
 }
-a.resource {
-    color: inherit;
-    text-decoration: none;
-}
 
-.resource {
-    border: 1px solid #545454;
-    border-radius: 5px;
-    padding: 1px;
-    margin: 2px;
-    background: rgb(49, 49, 49);
-    display: inline-block;
-    text-shadow: 1px 1px 2px black;
-}
-.resource.minor {
-    background: none;
-    border: none;
-}
-.resource a {
-    color: rgb(150, 150, 255);
-    padding: 1px;
-    display: inline-block;
-}
-.resource.minor a {
-    text-decoration: none;
-    color: rgb(155, 155, 193);
-    padding: 0
-}
 .sub {
     display: inline-block;
     vertical-align: top;