ncounter.git

git clone https://git.crispbyte.dev/ncounter.git

commit
67a40cf
parent
a291d68
author
CheddarCrisp
date
2020-02-28 16:00:41 +0100 CET
Redesign UI to add some color,
eliminate the FAB, and make
dialogs look better
Add an about page
9 files changed,  +318, -51
M package-lock.json
+104, -0
  1@@ -2767,6 +2767,15 @@
  2       "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o=",
  3       "dev": true
  4     },
  5+    "get-npm-tarball-url": {
  6+      "version": "2.0.1",
  7+      "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.0.1.tgz",
  8+      "integrity": "sha512-POrVRGyS9X5w+855/H46JGVYBGuVgJXyIkbsTCzW+sv5x2qH+rfQjc7652DzkgOskF+cqLevA2En7V0hu0gZCg==",
  9+      "dev": true,
 10+      "requires": {
 11+        "normalize-registry-url": "^1.0.0"
 12+      }
 13+    },
 14     "get-stream": {
 15       "version": "4.1.0",
 16       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
 17@@ -3925,6 +3934,34 @@
 18         "to-regex": "^3.0.1"
 19       }
 20     },
 21+    "needle": {
 22+      "version": "2.3.2",
 23+      "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.2.tgz",
 24+      "integrity": "sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w==",
 25+      "dev": true,
 26+      "requires": {
 27+        "debug": "^3.2.6",
 28+        "iconv-lite": "^0.4.4",
 29+        "sax": "^1.2.4"
 30+      },
 31+      "dependencies": {
 32+        "debug": {
 33+          "version": "3.2.6",
 34+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
 35+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
 36+          "dev": true,
 37+          "requires": {
 38+            "ms": "^2.1.1"
 39+          }
 40+        },
 41+        "ms": {
 42+          "version": "2.1.2",
 43+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 44+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
 45+          "dev": true
 46+        }
 47+      }
 48+    },
 49     "negotiator": {
 50       "version": "0.6.2",
 51       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
 52@@ -4013,6 +4050,12 @@
 53       "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
 54       "dev": true
 55     },
 56+    "normalize-registry-url": {
 57+      "version": "1.0.0",
 58+      "resolved": "https://registry.npmjs.org/normalize-registry-url/-/normalize-registry-url-1.0.0.tgz",
 59+      "integrity": "sha512-0v6T4851b72ykk5zEtFoN4QX/Fqyk7pouIj9xZyAvAe9jlDhAwT4z6FlwsoQCHjeuK2EGUoAwy/F4y4B1uZq9A==",
 60+      "dev": true
 61+    },
 62     "npm-run-path": {
 63       "version": "2.0.2",
 64       "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
 65@@ -4857,6 +4900,12 @@
 66       "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
 67       "dev": true
 68     },
 69+    "sax": {
 70+      "version": "1.2.4",
 71+      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
 72+      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
 73+      "dev": true
 74+    },
 75     "schema-utils": {
 76       "version": "1.0.0",
 77       "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
 78@@ -5258,6 +5307,37 @@
 79       "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
 80       "dev": true
 81     },
 82+    "spdx-exceptions": {
 83+      "version": "2.2.0",
 84+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
 85+      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
 86+      "dev": true
 87+    },
 88+    "spdx-expression-parse": {
 89+      "version": "3.0.0",
 90+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
 91+      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
 92+      "dev": true,
 93+      "requires": {
 94+        "spdx-exceptions": "^2.1.0",
 95+        "spdx-license-ids": "^3.0.0"
 96+      }
 97+    },
 98+    "spdx-expression-validate": {
 99+      "version": "2.0.0",
100+      "resolved": "https://registry.npmjs.org/spdx-expression-validate/-/spdx-expression-validate-2.0.0.tgz",
101+      "integrity": "sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==",
102+      "dev": true,
103+      "requires": {
104+        "spdx-expression-parse": "^3.0.0"
105+      }
106+    },
107+    "spdx-license-ids": {
108+      "version": "3.0.5",
109+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
110+      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
111+      "dev": true
112+    },
113     "spdy": {
114       "version": "4.0.0",
115       "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz",
116@@ -5414,6 +5494,16 @@
117       "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
118       "dev": true
119     },
120+    "string-replace-loader": {
121+      "version": "2.2.0",
122+      "resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-2.2.0.tgz",
123+      "integrity": "sha512-Ukt4ZC8+xVWdBRut3/iwnPJCNL1yV8AbVKXn8UcWdYrHgtuW4UDDAbBSi/J/CQDEWQBt824AJvPYahF23eJLRg==",
124+      "dev": true,
125+      "requires": {
126+        "loader-utils": "^1.2.3",
127+        "schema-utils": "^1.0.0"
128+      }
129+    },
130     "string-width": {
131       "version": "2.1.1",
132       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
133@@ -6125,6 +6215,20 @@
134         }
135       }
136     },
137+    "webpack-license-plugin": {
138+      "version": "4.1.1",
139+      "resolved": "https://registry.npmjs.org/webpack-license-plugin/-/webpack-license-plugin-4.1.1.tgz",
140+      "integrity": "sha512-CYqPx4f8e7thGIrv5aruoUAF8sTw94o3dGhZbALc4szYIjdQPGLO3lCB/YLUj7UaI+JJeuboVz0lu3QPx5k+ZA==",
141+      "dev": true,
142+      "requires": {
143+        "chalk": "^2.4.1",
144+        "get-npm-tarball-url": "^2.0.1",
145+        "lodash": "^4.17.10",
146+        "needle": "^2.2.4",
147+        "spdx-expression-validate": "^2.0.0",
148+        "webpack-sources": "^1.3.0"
149+      }
150+    },
151     "webpack-log": {
152       "version": "2.0.0",
153       "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
M package.json
+2, -0
 1@@ -20,6 +20,7 @@
 2     "idb-keyval": "^3.2.0",
 3     "reset-css": "^5.0.1",
 4     "serviceworker-webpack-plugin": "^1.0.1",
 5+    "string-replace-loader": "^2.2.0",
 6     "style-loader": "^1.1.3",
 7     "svelte": "^3.4.1",
 8     "svelte-loader": "^2.13.4",
 9@@ -27,6 +28,7 @@
10     "webpack": "^4.31.0",
11     "webpack-cli": "^3.3.2",
12     "webpack-dev-server": "^3.4.1",
13+    "webpack-license-plugin": "^4.1.1",
14     "webpack-merge": "^4.2.2",
15     "workbox-cacheable-response": "^5.0.0",
16     "workbox-expiration": "^5.0.0",
A src/ncounter/About.svelte
+64, -0
 1@@ -0,0 +1,64 @@
 2+<div class="about">
 3+    <button class="close" on:click={ () => { dispatch('close'); } }><i class="material-icons">close</i></button>
 4+    <header>
 5+        <h1>NCounter</h1>
 6+        <h2>Release |BUILD_DATE|</h2>
 7+        <h2>&copy; |BUILD_YEAR|</h2>
 8+    </header>
 9+    <div class="licenses">
10+        <h2>Open Source License Information</h2>
11+        <Licenses></Licenses>
12+    </div>
13+</div>
14+<script>
15+import Licenses from './Licenses.svelte';
16+import { createEventDispatcher } from 'svelte';
17+const dispatch = createEventDispatcher();
18+</script>
19+<style>
20+.about {
21+    background-color: white;
22+    position: fixed;
23+    top: 0;
24+    right: 0;
25+    bottom: 0;
26+    left: 0;
27+    z-index: 3;
28+
29+    display: flex;
30+    flex-direction: column;
31+    align-items: stretch;
32+
33+    overflow: auto;
34+
35+    padding: 5px;
36+}
37+
38+.about > header {
39+    flex: center;
40+    text-align: center;
41+}
42+
43+h1 {
44+    font-weight: 600;
45+    font-size: 24px;
46+}
47+
48+h2 {
49+    font-size: 18px;
50+}
51+
52+.licenses h2{
53+    font-weight: 600;
54+}
55+
56+.close {
57+    position: absolute;
58+    top: 15px;
59+    right: 15px;
60+}
61+
62+.licenses {
63+    margin-top: 32px;
64+}
65+</style>
M src/ncounter/App.svelte
+51, -32
  1@@ -1,27 +1,36 @@
  2 <div class="app">
  3-<button class="add" on:click="{ showAdd }"><i class="material-icons">add</i></button>
  4-{#each $counters as counter}
  5-<Counter counterId={ counter.id }></Counter>
  6-{/each}
  7+    <div class="counter-list">
  8+        {#each $counters as counter}
  9+        <Counter counterId={ counter.id }></Counter>
 10+        {/each}
 11+    </div>
 12+    <div class="tool-bar">
 13+        <button class="add" on:click="{ showAdd }"><i class="material-icons">add</i></button>
 14+        <button class="about" on:click="{ () => { showAbout = true; } }">?</button>
 15+    </div>
 16 </div>
 17 {#if showAddDialog}
 18 <div class="dialog">
 19     <div class="dialog-content">
 20-        <label>Name: <input type="text" bind:value={newCounter.title} use:focus/></label>
 21-        <label>Initial Value: <input type="number" bind:value={newCounter.initialValue} /></label>
 22-        <label>Target: <input type="number" bind:value={newCounter.max} /></label>
 23-        <label>Save history: <input type="checkbox" bind:checked={newCounter.saveHistory} /></label>
 24+        <label>Name<input type="text" bind:value={newCounter.title} use:focus/></label>
 25+        <label>Initial Value<input type="number" bind:value={newCounter.initialValue} /></label>
 26+        <label>Target<input type="number" bind:value={newCounter.max} /></label>
 27+        <label>Save history<input type="checkbox" bind:checked={newCounter.saveHistory} /></label>
 28         <button on:click={ () => { showAddDialog = false; } }>Cancel</button>
 29         <button class="ok" on:click={ add }>OK</button>
 30     </div>
 31 </div>
 32 {/if}
 33+{#if showAbout}
 34+<About on:close="{ () => { showAbout = false; } }"></About>
 35+{/if}
 36 <script>
 37+import About from './About.svelte';
 38 import Counter from './Counter.svelte';
 39 import { counters } from './db.js';
 40 
 41 let showAddDialog = false;
 42-
 43+let showAbout = false;
 44 let newCounter = null;
 45 
 46 function focus(node){
 47@@ -50,34 +59,16 @@ function add(){
 48     showAddDialog = false;
 49 }
 50 </script>
 51-<style>
 52-    .add {
 53-        display: flex;
 54-        align-items: center;
 55-        justify-content: center;
 56-
 57-        position: fixed;
 58-        bottom: 15px;
 59-        right: 15px;
 60-
 61-        z-index: 2;
 62-
 63-        background-color: #90C090;
 64-        border-radius: 50%;
 65-    
 66-        box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
 67-
 68-        width: 40px;
 69-        height: 40px;
 70-        color: white;
 71-    }
 72-
 73+<style lang="scss">
 74     .ok {
 75         margin-left: auto;
 76     }
 77 
 78     .app {
 79-        padding: 5px;
 80+        display: flex;
 81+        flex-direction: column;
 82+        align-items: stretch;
 83+
 84         position: fixed;
 85         top: 0;
 86         right: 0;
 87@@ -85,7 +76,35 @@ function add(){
 88         left: 0;
 89 
 90         z-index: 1;
 91+    }
 92 
 93+    .counter-list {
 94+        padding: 5px;
 95         overflow: auto;
 96+        flex: 1 0 0;
 97+
 98+        background-color: #8baec6;
 99+    }
100+
101+    .tool-bar {
102+        flex: none;
103+
104+        display: flex;
105+
106+        border-top: 2px solid #3A86B7;
107+    }
108+
109+    .tool-bar > button {
110+        background-color: #3A86B7;
111+        color: white;
112+    }
113+
114+    .tool-bar > button:focus, .tool-bar > button:hover {
115+        border: 2px solid #303030;
116+    }
117+
118+    .about {
119+        margin-left: auto;
120+        font-size: 20px;
121     }
122 </style>
M src/ncounter/Counter.svelte
+10, -11
 1@@ -27,10 +27,10 @@
 2     {#if showEditDialog}
 3     <div class="dialog">
 4         <div class="dialog-content">
 5-            <label>Name: <input type="text" bind:value={editingCounter.title} use:focus/></label>
 6-            <label>Initial Value: <input type="number" bind:value={editingCounter.initialValue} /></label>
 7-            <label>Target: <input type="number" bind:value={editingCounter.max} /></label>
 8-            <label>Save history: <input type="checkbox" bind:checked={editingCounter.saveHistory} /></label>
 9+            <label>Name<input type="text" bind:value={editingCounter.title} use:focus/></label>
10+            <label>Initial Value<input type="number" bind:value={editingCounter.initialValue} /></label>
11+            <label>Target<input type="number" bind:value={editingCounter.max} /></label>
12+            <label>Save history<input type="checkbox" bind:checked={editingCounter.saveHistory} /></label>
13             <button on:click={ () => { showEditDialog = false; } }>Cancel</button>
14             <button class="ok" on:click={ finishEdit }>OK</button>
15         </div>
16@@ -122,7 +122,10 @@ function remove(){
17 <style>
18 .counter{
19     box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
20-    margin-bottom: 12px;
21+
22+    background-color: #FCFCFC;
23+
24+    margin-bottom: 4px;
25 
26     display: flex;
27     flex-direction: column;
28@@ -130,10 +133,6 @@ function remove(){
29     padding: 5px;
30 }
31 
32-.counter:last-child {
33-    margin-bottom: 72px;
34-}
35-
36 .controls {
37     display: flex;
38 }
39@@ -151,7 +150,7 @@ header {
40 }
41 
42 .reset {
43-    margin-left: 24px;
44+    margin-left: 12px;
45 }
46 
47 .reset + button {
48@@ -159,7 +158,7 @@ header {
49 }
50 
51 .history {
52-    margin-right: 24px;
53+    margin-right: 12px;
54 }
55 
56 .dialog-value {
M src/ncounter/History.svelte
+2, -2
 1@@ -107,8 +107,6 @@ function close(){
 2         display: flex;
 3         flex-direction: column;
 4         align-items: stretch;
 5-
 6-        overflow: auto;
 7     }
 8 
 9     header {
10@@ -124,6 +122,8 @@ function close(){
11 
12     .table-container {
13         position: relative;
14+
15+        overflow: auto;
16     }
17 
18     .close {
A src/ncounter/Licenses.svelte
+39, -0
 1@@ -0,0 +1,39 @@
 2+<div>
 3+    {#each licenses as license}
 4+    <header>
 5+        <h1>{license.name} by {license.author}</h1>
 6+        <div>Source: <a href="{license.repository}" target="_blank">{license.repository}</a></div>
 7+    </header>
 8+    <pre>{license.licenseText}</pre>
 9+    {/each}
10+    {#if !licenses}
11+    <progress></progress>
12+    {/if}
13+</div>
14+<script>
15+let licenses = [];
16+
17+(async () => {
18+    licenses = await fetch('oss-licenses.json')
19+                        .then(response => {
20+                            if(response.ok)
21+                                return response.json();
22+                        });
23+})();
24+</script>
25+<style>
26+header {
27+    margin-top: 12px;
28+}
29+
30+header h1 {
31+    font-weight: 600;
32+}
33+
34+pre {
35+    margin: 5px;
36+    padding: 5px;
37+    white-space: pre-wrap;
38+    background-color: #F0F0F0;
39+}
40+</style>
M src/ncounter/site.css
+31, -4
 1@@ -25,7 +25,21 @@ body {
 2 button {
 3     background: 0;
 4     border: 0;
 5+    
 6+    width: 36px;
 7     height: 36px;
 8+
 9+    display: flex;
10+    align-items: center;
11+    justify-content: center;
12+
13+    cursor: pointer;
14+    
15+    font-family: inherit;
16+}
17+
18+button:focus, button:hover {
19+    border: 2px solid #3A86B7;
20 }
21 
22 .dialog {
23@@ -47,14 +61,13 @@ button {
24 }
25 
26 .dialog-content {
27-    background-color: #E0E0E0;
28+    background-color: #FCFCFC;
29     pointer-events: all;
30 
31-    width: 300px;
32+    width: 315px;
33 
34-    border-radius: 5px;
35     box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
36-    padding: 5px;
37+    padding: 10px;
38 
39     display: flex;
40     flex-wrap: wrap;
41@@ -64,16 +77,30 @@ button {
42     display: flex;
43     width: 100%;
44     margin-bottom: 5px;
45+    align-items: center;
46+    height: 26px;
47+    font-weight: 600;
48 }
49 
50 .dialog-content > label > input {
51     margin-left: auto;
52 }
53 
54+.dialog-content input[type='text'], .dialog-content input[type='number'] {
55+    width: 175px;
56+}
57+
58 .dialog-content button {
59     padding: 10px;
60     font-size: 14px;
61     font-weight: 600;
62+
63+    width: auto;
64+}
65+
66+.dialog-content button:focus, .dialog-content button:hover {
67+    border: 0;
68+    outline: 2px solid #3A86B7;
69 }
70 
71 input[type="text"],
M webpack.common.js
+15, -2
 1@@ -3,6 +3,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
 2 const GoogleFontsPlugin = require('@beyonk/google-fonts-webpack-plugin');
 3 const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 4 const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
 5+const LicensePlugin = require('webpack-license-plugin');
 6 
 7 module.exports = {
 8     entry: './src/index.js',
 9@@ -21,7 +22,8 @@ module.exports = {
10         new ServiceWorkerWebpackPlugin({
11             entry: path.join(__dirname, 'src/sw.js'),
12             publicPath: './'
13-        })
14+        }),
15+        new LicensePlugin()
16     ],
17     output: {
18         filename: 'index.js',
19@@ -32,7 +34,18 @@ module.exports = {
20             {
21                 test: /\.svelte$/,
22                 exclude: /node_modules/,
23-                loader: 'svelte-loader'
24+                use: [
25+                    'svelte-loader',
26+                    {
27+                        loader: 'string-replace-loader',
28+                        options: {
29+                            multiple: [
30+                                { search: '|BUILD_YEAR|', replace: '2020' },
31+                                { search: '|BUILD_DATE|', replace: '2020-02-28'}
32+                            ]
33+                        }
34+                    }
35+                ]
36             },
37             {
38                 test: /\.css$/,