Latest updates

This commit is contained in:
CheddarCrisp 2020-02-06 12:27:58 -05:00
parent aace75679a
commit b2208a7e58
15 changed files with 1267 additions and 131 deletions

3
.gitignore vendored
View file

@ -1 +1,2 @@
node_modules/
node_modules/
dist/

52
dist/index.html vendored
View file

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<title>NCounter</title>
<style>
body {
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
button {
background: 0;
border: 0;
}
.dialog {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.25);
z-index: 12;
pointer-events: none;
}
.dialog-content {
background-color: #E0E0E0;
pointer-events: all;
width: 250px;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
padding: 5px;
display: flex;
flex-wrap: wrap;
}
</style>
</head>
<body>
<script src="index.js"></script>
</body>
</html>

1
dist/index.js vendored

File diff suppressed because one or more lines are too long

987
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,16 +5,30 @@
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack-dev-server --open"
"build": "webpack --config webpack.prod.js",
"start": "webpack-dev-server --open --config webpack.dev.js"
},
"author": "",
"license": "MIT",
"devDependencies": {
"@beyonk/google-fonts-webpack-plugin": "^1.2.3",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"google-fonts-webpack-plugin": "^0.4.4",
"html-webpack-plugin": "^3.2.0",
"idb-keyval": "^3.2.0",
"serviceworker-webpack-plugin": "^1.0.1",
"style-loader": "^1.1.3",
"svelte": "^3.4.1",
"svelte-loader": "^2.13.4",
"uuid": "^3.4.0",
"webpack": "^4.31.0",
"webpack-cli": "^3.3.2",
"webpack-dev-server": "^3.4.1"
"webpack-dev-server": "^3.4.1",
"webpack-merge": "^4.2.2",
"workbox-cacheable-response": "^5.0.0",
"workbox-expiration": "^5.0.0",
"workbox-routing": "^5.0.0",
"workbox-strategies": "^5.0.0"
}
}

View file

@ -1,3 +1,8 @@
import App from './ncounter/App.svelte';
import runtime from 'serviceworker-webpack-plugin/lib/runtime';
if ('serviceWorker' in navigator) {
const registration = runtime.register();
}
new App({ target: document.body });

View file

@ -1,6 +1,6 @@
<div class="app">
{#each counters as counter}
<Counter counter={ counter } on:save={() => { save(counter); } }></Counter>
{#each $counters as counter}
<Counter counterId={ counter.id }></Counter>
{/each}
</div>
<button class="add" on:click="{ showAdd }"><i class="material-icons">add</i></button>
@ -12,38 +12,19 @@
<label>Target: <input type="number" bind:value={newCounter.max} /></label>
<label>Click counter: <input type="checkbox" bind:value={newCounter.isClickCounter} /></label>
<button on:click={ () => { showAddDialog = false; } }>Cancel</button>
<button class="ok" on:click={ addCounter }>OK</button>
<button class="ok" on:click={ add }>OK</button>
</div>
</div>
{/if}
<script>
import Counter from './Counter.svelte';
import { counters } from './db.js';
import './site.css';
let showAddDialog = false;
let newCounter = null;
let counters = [
{
title: 'Test 1',
value: 0
},
{
title: 'Test 2',
value: 10
},
{
title: 'Max Test',
value: 0,
max: 100
},
{
title: 'Click Test',
value: 0,
isClickCounter: true
}
];
function focus(node){
node.focus();
}
@ -56,7 +37,8 @@ function showAdd(){
newCounter = {
title: '',
value: 0,
isClickCounter: false
isClickCounter: false,
history: []
}
console.log({ newCounter });
@ -64,8 +46,8 @@ function showAdd(){
showAddDialog = true;
}
function addCounter(){
counters = [...counters, newCounter];
function add(){
counters.add(newCounter);
showAddDialog = false;
}

View file

@ -8,8 +8,10 @@
{#if !counter.isClickCounter}
<button on:click={ () => { showIncrement = true; } }><i class="material-icons">add</i></button>
{/if}
<span class="message">{ message }</span>
<button class="reset" on:click={ reset }><i class="material-icons">undo</i></button>
<button on:click={ save }><i class="material-icons">save</i></button>
<button on:click={ remove }><i class="material-icons">delete</i></button>
</div>
{#if showIncrement}
<div class="dialog">
@ -25,20 +27,43 @@
import MyProgress from './MyProgress.svelte';
import { tick } from 'svelte';
import { createEventDispatcher } from 'svelte';
import { counters } from './db.js';
const dispatch = createEventDispatcher();
export let counter;
export let counterId;
$: counter = $counters.find(x => x.id == counterId);
let incrementValue;
let showIncrement;
let message = '';
const formatter = new Intl.DateTimeFormat('en-US',
{
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric'
});
function focus(node){
node.focus();
}
function update(newCounter){
counters.update(newCounter);
}
function increment(){
counter.value += incrementValue;
const newCounter = {
...counter,
value: counter.value + incrementValue
}
update(newCounter);
showIncrement = false;
incrementValue = null;
}
@ -46,22 +71,52 @@ function increment(){
function reset(e){
e.stopPropagation();
if(confirm(`Reset ${counter.title}?`))
counter.value = 0;
if(confirm(`Reset ${counter.title}?`)){
const newCounter = {
...counter,
value: 0
}
update(newCounter);
}
}
function save(e) {
e.stopPropagation();
dispatch('save');
counter.value = 0;
const time = new Date();
const data = {
time,
value: counter.value
}
const newCounter = {
...counter,
history: [...counter.history, data]
}
message = `Saved ${data.value} at ${formatter.format(data.time)}`;
setTimeout(() => message = '', 5000);
update(newCounter);
}
function remove(){
if(confirm(`Remove ${counter.title}?`))
counters.remove(counter);
}
function clickCount() {
if(!counter.isClickCounter)
return;
counter.value++;
const newCounter = {
...counter,
value: counter.value + 1
}
update(newCounter);
}
</script>
<style>
@ -79,8 +134,9 @@ function clickCount() {
display: flex;
}
.reset {
margin-left: auto;
.message {
flex: 1;
text-align: center;
}
header {

57
src/ncounter/db.js Normal file
View file

@ -0,0 +1,57 @@
import { set as setDb, get as getDb } from 'idb-keyval';
import { writable } from 'svelte/store';
import uuid from 'uuid/v4';
function createCounters(){
const {subscribe,set,update:updateVal} = writable([]);
getDb('counters').then(counters => {
if(counters)
set(counters);
});
function add(counter){
const newCounter = { id: uuid(), ...counter };
updateVal(counters => {
const newCounters = [...counters, newCounter];
setDb('counters', newCounters);
return newCounters;
});
}
function update(counter){
updateVal(counters => {
const counterIndex = counters.findIndex(x => x.id == counter.id);
const newCounters = [...counters.slice(0, counterIndex), counter, ...counters.slice(counterIndex + 1)];
setDb('counters', newCounters);
return newCounters;
});
}
function remove(counter){
updateVal(counters => {
const counterIndex = counters.findIndex(x => x.id == counter.id);
const newCounters = [...counters.slice(0, counterIndex), ...counters.slice(counterIndex + 1)];
setDb('counters', newCounters);
return newCounters;
})
}
return {
subscribe,
add,
update,
remove
};
}
export const counters = createCounters();

40
src/ncounter/site.css Normal file
View file

@ -0,0 +1,40 @@
body {
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
button {
background: 0;
border: 0;
}
.dialog {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,0.25);
z-index: 12;
pointer-events: none;
}
.dialog-content {
background-color: #E0E0E0;
pointer-events: all;
width: 250px;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
padding: 5px;
display: flex;
flex-wrap: wrap;
}

41
src/sw.js Normal file
View file

@ -0,0 +1,41 @@
import {registerRoute} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate, NetworkFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {ExpirationPlugin} from 'workbox-expiration';
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
new StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
})
);
// Cache the underlying font files with a cache-first strategy for 1 year.
registerRoute(
/^https:\/\/fonts\.gstatic\.com/,
new CacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
}),
new ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
maxEntries: 30,
}),
],
})
);
registerRoute(
/\.(?:js|css)$/,
new StaleWhileRevalidate({
cacheName: 'static-resources',
})
);
registerRoute(
'/',
new NetworkFirst()
)

44
webpack.common.js Normal file
View file

@ -0,0 +1,44 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const GoogleFontsPlugin = require('@beyonk/google-fonts-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'NCounter',
}),
new GoogleFontsPlugin({
fonts: [
{ family: "Material Icons" }
],
local: false
}),
new ServiceWorkerWebpackPlugin({
entry: path.join(__dirname, 'src/sw.js'),
})
],
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.svelte$/,
exclude: /node_modules/,
loader: 'svelte-loader'
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
},
}

View file

@ -1,22 +0,0 @@
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
contentBase: './dist'
},
module: {
rules: [
{
test: /\.svelte$/,
exclude: /node_modules/,
loader: 'svelte-loader'
}
]
},
devtool: 'inline-source-map'
}

10
webpack.dev.js Normal file
View file

@ -0,0 +1,10 @@
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
}
});

6
webpack.prod.js Normal file
View file

@ -0,0 +1,6 @@
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});