commit ad570aa798fae952b9f996c8681270693fe4da38
parent 042616865221f0eaacfe5105cebdc823f0a4bc2c
Author: Martin Ashby <martin@martin-laptop.lan>
Date:   Fri, 18 May 2018 11:15:19 +0100
Styled everything a bit nicer
Diffstat:
8 files changed, 277 insertions(+), 61 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -90,6 +90,22 @@
         }
       }
     },
+    "active-event-stack": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/active-event-stack/-/active-event-stack-1.0.0.tgz",
+      "integrity": "sha1-a1uS661xmvrpgs1R9Jw4xbaADFA=",
+      "requires": {
+        "immutable": "3.8.2",
+        "lodash": "3.10.1"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+        }
+      }
+    },
     "address": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
@@ -1408,6 +1424,11 @@
         "hoek": "4.2.1"
       }
     },
+    "bowser": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.3.tgz",
+      "integrity": "sha512-/gp96UlcFw5DbV2KQPCqTqi0Mb9gZRyDAHiDsGEH+4B/KOQjeoE5lM1PxlVX8DQDvfEfitmC1rW2Oy8fk/XBDg=="
+    },
     "boxen": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
@@ -1870,6 +1891,11 @@
         }
       }
     },
+    "classnames": {
+      "version": "2.2.5",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz",
+      "integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0="
+    },
     "clean-css": {
       "version": "4.1.11",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz",
@@ -2271,6 +2297,15 @@
       "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
       "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
     },
+    "css-in-js-utils": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
+      "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
+      "requires": {
+        "hyphenate-style-name": "1.0.2",
+        "isobject": "3.0.1"
+      }
+    },
     "css-loader": {
       "version": "0.28.7",
       "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz",
@@ -2812,6 +2847,11 @@
       "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
       "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
     },
+    "dynamics.js": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/dynamics.js/-/dynamics.js-1.1.5.tgz",
+      "integrity": "sha1-uQvcM2Bc7+ZSuEFucB95v27vzjI="
+    },
     "ecc-jsbn": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
@@ -5006,6 +5046,11 @@
       "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz",
       "integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao="
     },
+    "hyphenate-style-name": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
+      "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
+    },
     "iconv-lite": {
       "version": "0.4.23",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
@@ -5037,6 +5082,11 @@
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
       "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg=="
     },
+    "immutable": {
+      "version": "3.8.2",
+      "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+      "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM="
+    },
     "import-lazy": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
@@ -5093,6 +5143,15 @@
       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
       "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
     },
+    "inline-style-prefixer": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz",
+      "integrity": "sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==",
+      "requires": {
+        "bowser": "1.9.3",
+        "css-in-js-utils": "2.0.1"
+      }
+    },
     "inquirer": {
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
@@ -6326,6 +6385,11 @@
       "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
       "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE="
     },
+    "keycode": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
+      "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
+    },
     "killable": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
@@ -6836,6 +6900,14 @@
         "to-regex": "3.0.2"
       }
     },
+    "narcissus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/narcissus/-/narcissus-1.0.0.tgz",
+      "integrity": "sha1-JGKgfEWYzpBl60Gyq72zDQ4w9G4=",
+      "requires": {
+        "inline-style-prefixer": "4.0.2"
+      }
+    },
     "natural-compare": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -8814,6 +8886,14 @@
         "prop-types": "15.6.1"
       }
     },
+    "react-center-component": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/react-center-component/-/react-center-component-3.0.0.tgz",
+      "integrity": "sha1-0omGv0NOD46/9jyRJ38b9q0YnHI=",
+      "requires": {
+        "lodash": "4.17.10"
+      }
+    },
     "react-dev-utils": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.1.tgz",
@@ -8855,6 +8935,26 @@
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.0.tgz",
       "integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw=="
     },
+    "react-modal-dialog": {
+      "version": "github:Dean177/react-modal-dialog#9dbc6fe9e1d48d4643714c02ec46c8d991f338ea",
+      "requires": {
+        "active-event-stack": "1.0.0",
+        "classnames": "2.2.5",
+        "dynamics.js": "1.1.5",
+        "immutable": "3.8.2",
+        "keycode": "2.2.0",
+        "lodash": "3.10.1",
+        "narcissus": "1.0.0",
+        "react-center-component": "3.0.0"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "3.10.1",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+          "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
+        }
+      }
+    },
     "react-scripts": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-1.1.4.tgz",
diff --git a/src/App.css b/src/App.css
@@ -1,38 +1,81 @@
-.toolkit {
-  float: right;
-  background: lightblue;
+body {
+    background: black;
+    color: aliceblue;
+    padding-left: 50px;
+    padding-right: 50px;
 }
 
-.toolkititem {
-  padding: 5px;
+.container {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+
+    grid-template-areas: 
+        "header header"
+        "paint liveFeed";
+    grid-gap: 5px;
+        
+}
+
+@media (max-width: 760px) {
+    .container {
+        display: grid;
+        grid-template-columns: 1fr;
+    
+        grid-template-areas: 
+            "header"
+            "paint"
+            "liveFeed";
+    }   
+}
+
+.header {
+    grid-area: header;
 }
 
-.toolkititem.selected {
-  background: lightcoral;
+.paint {
+    grid-area: paint;
 }
 
-/* .paintarea {
+.liveFeed {
+    grid-area: liveFeed;
+}
+
+.paintContainer {
+    display: grid;
+    grid-template-columns: 1fr 1fr 1frpx;
 
-} */
+    grid-template-areas: 
+        "paint paint tools"
+        "paintCol palette tools";
+}
+
+.paint {
+    grid-area: paint;
+}
 
-.paintareacell {
-  width: 20px;
-  height: 20px;
-  border: 1px solid grey;
+.tools {
+    grid-area: tools;
+    display: flex;
+    flex-direction: column;
+    width: 45px;
 }
 
-.paletteitem {
-  width: 30px;
-  height: 30px;
-  border: 3px solid black;
-  display: inline-block;
+.palette {
+    grid-area: palette;
+    display: flex;
+    flex-direction: row;
 }
 
-.paletteitem.selected {
-  border: 3px solid red;
+.paintCol {
+    grid-area: paintCol;
 }
 
-.colorIndicator {
-  width: 100px;
-  height: 100px;
+.paintAreaCell {
+    width: "20px";
+    height: "20px";
+    min-width: "20px";
+    min-height: "20px";
+    max-width: "20px";
+    max-height: "20px";
+    border: "1px solid grey";
 }
 \ No newline at end of file
diff --git a/src/App.js b/src/App.js
@@ -144,7 +144,9 @@ class App extends Component {
 
   _connectWebsocket() {
     let webSocketProto = window.location.protocol === "https" ? "wss" : "ws"
-    this._websocket = new WebSocket(`${webSocketProto}://${window.location.host}/ws`)
+    let host = window.location.host
+    // let host = "shinypi:3001"
+    this._websocket = new WebSocket(`${webSocketProto}://${host}/ws`)
     this._websocket.onmessage = this._onMessage
     this._websocket.onopen = this._onOpen
     this._websocket.onclose = this._onClose
@@ -196,24 +198,44 @@ class App extends Component {
 
   render() {
     return (
-      <div className="App">
-        <ConnectedIndicator connected={this.state.connected} />
-        <Toolkit
-          tools={tools}
-          selectedTool={this.state.selectedTool}
-          onSelectTool={this._selectTool} />
-        <PaintArea
-          data={this.state.pixels}
-          onTool={this._applyTool} />
-        <Palette
-          selectedColor={this.state.selectedColor}
-          onSelectColor={(color) => this.setState({ selectedColor: color })} />
-        <ColorIndicator color={this.state.selectedColor} />
-        {/* Embedded tweet showing live stream */}
-        <Timeline dataSource={{
-          sourceType: 'profile',
-          screenName: 'UnicornPaint'
-        }}/>
+      <div className="container">
+        <div className="header">
+          <h1>Unicorn Paint!</h1>
+          <ConnectedIndicator connected={this.state.connected} />
+        </div>
+        <div className="paintContainer">
+          <div className="paint">
+            <PaintArea
+              data={this.state.pixels}
+              onTool={this._applyTool} />
+          </div>
+          <div className="tools">
+            <Toolkit
+              tools={tools}
+              selectedTool={this.state.selectedTool}
+              onSelectTool={this._selectTool} />
+          </div>
+          <div className="palette">
+            <Palette
+              selectedColor={this.state.selectedColor}
+              onSelectColor={(color) => this.setState({ selectedColor: color })} />
+          </div>  
+          <div className="paintCol">
+            <ColorIndicator color={this.state.selectedColor} />
+          </div>
+        </div>
+        <div className="liveFeed">
+          <Timeline 
+            dataSource={{
+              sourceType: 'profile',
+              screenName: 'UnicornPaint',
+            }}
+            options={{
+              tweetLimit: 1,
+              chrome: "noheader nofooter noborders noscrollbar",
+              width: "300px"
+            }}/>
+        </div>
         <div>
           {
             this.state.showingLoad
@@ -238,4 +260,4 @@ class App extends Component {
   }
 }
 
-export default App;
+export default App;
+\ No newline at end of file
diff --git a/src/ColorIndicator.js b/src/ColorIndicator.js
@@ -19,12 +19,19 @@ export default class ColorIndicator extends Component {
         }
 
         return <div 
-            className="colorIndicator"
             style={{
                 background: `rgb(${r},${g},${b})`, 
-                color: foreground
+                color: foreground,
+                ...styles.colorIndicator
             }}>
             <span>{colorDesc}</span>
         </div>
     }
+}
+
+const styles = {
+    colorIndicator: {
+        width: "100px",
+        height: "100px"
+    }
 }
 \ No newline at end of file
diff --git a/src/ConnectedIndicator.js b/src/ConnectedIndicator.js
@@ -5,7 +5,8 @@ export default class ConnectedIndicator extends Component {
     let connectedText = this.props.connected ? "Connected" : "Not connected"
     let color = this.props.connected ? "green" : "red"
     return <div><span style={{
-      background:color
+      background:color,
+      display: "inline-block"
     }}>{connectedText}</span></div>
   }
 }
 \ No newline at end of file
diff --git a/src/PaintArea.js b/src/PaintArea.js
@@ -57,9 +57,9 @@ export default class PaintArea extends Component {
         cells.push(<td
           onMouseMove={() => this.handleMouseMove(ix, iy)}
           onClick={() => this.props.onTool(ix, iy)}
-          className="paintareacell"
           style={{
-            background: `rgb(${r},${g},${b})`
+            background: `rgb(${r},${g},${b})`,
+            ...styles.paintAreaCell
           }}
           key={(ix * 100000) + iy}/>)
       }
@@ -68,7 +68,6 @@ export default class PaintArea extends Component {
     
     return (
       <table 
-        className="paintarea"
         draggable={false}>
         <tbody>
           {rows}
@@ -76,4 +75,16 @@ export default class PaintArea extends Component {
       </table>
     )
   }
+}
+
+const styles = {
+  paintAreaCell: {
+    width: "20px",
+    height: "20px",
+    minWidth: "20px",
+    minHeight: "20px",
+    maxWidth: "20px",
+    maxHeight: "20px",
+    border: "1px solid grey",
+  }
 }
 \ No newline at end of file
diff --git a/src/Palette.js b/src/Palette.js
@@ -24,21 +24,39 @@ const colorPalette = [
   export default class Palette extends Component {
     render() {
       let paletteListItems = colorPalette.map((item) => {
-        var className = "paletteitem"
         let { r, g, b } = rgb(item)
         let selected = rgb(this.props.selectedColor)
-        if (r === selected.r && g === selected.g && b === selected.b) {
-          className += " selected"
-        }
+        let isSelected = r === selected.r && g === selected.g && b === selected.b
+
+        let style = Object.assign({},
+          {background: `rgb(${r},${g},${b})`},
+          styles.paletteItem,
+          isSelected && styles.selected
+        )
+
         return <div
           onClick={() => this.props.onSelectColor([r, g, b])}
-          style={{background: `rgb(${r},${g},${b})`}} 
-          className={className}
+          style={style} 
           key={r*10000+g*1000+b}/>
       })
+      let list1 = paletteListItems.slice(0, paletteListItems.length / 2)
+      let list2 = paletteListItems.slice(paletteListItems.length / 2)
       return (
-        <div className="palette">
-          {paletteListItems}
+        <div>
+          {list1}<br/>
+          {list2}
         </div>)
     }
+  }
+
+  const styles = {
+    paletteItem: {
+      width: "30px",
+      height: "30px",
+      border: "3px solid black",
+      display: "inline-block",
+    },
+    selected: {
+      border: "3px solid red"
+    }
   }
 \ No newline at end of file
diff --git a/src/Toolkit.js b/src/Toolkit.js
@@ -4,11 +4,11 @@ import './fontawesome-all.min.js'
 class ToolKitItem extends Component {
   render() {
     let iconClass = this.props.tool.icon + " fa-2x" 
-    var divClass = "toolkititem"
+    let style = styles.toolkititem
     if (this.props.selected) {
-      divClass += " selected"
+      style = Object.assign({}, style, styles.selected)
     }
-    return <div className={divClass}
+    return <div style={style}
         onClick={() => this.props.onSelectTool(this.props.tool)}>
         <i className={iconClass}></i>
       </div>
@@ -24,8 +24,20 @@ export default class Toolkit extends Component {
         selected={tool === this.props.selectedTool}
         onSelectTool={this.props.onSelectTool}/>
     })
-    return <div className="toolkit">
+    return <div style={styles.toolkit}>
       {toolComponents}
     </div>
   }
 }
+
+const styles = {
+  toolkit: {
+    background: "grey"
+  },
+  toolkititem: {
+    padding: "5px",
+  },
+  selected: {
+    background: "lightcoral"
+  }
+}
+\ No newline at end of file