Implemented saving and loading

This commit is contained in:
Mark van Renswoude 2020-12-28 16:11:12 +01:00
parent 103ab6f762
commit ef79e6891b
15 changed files with 150 additions and 21 deletions

View File

@ -5,7 +5,6 @@ Must have
----
- Implement switching units
- Re-ordering of the layers (preferably drag/drop)
- Save / load designs (clipboard, or preferably file download/upload - maybe Cloud storage integration later?)
Should have
----

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/CuttingBoard/favicon.ico"><title>CuttingBoard</title><link href="/CuttingBoard/css/app.037fc7fb.css" rel="preload" as="style"><link href="/CuttingBoard/js/app.25927fa2.js" rel="preload" as="script"><link href="/CuttingBoard/js/chunk-vendors.d9b83edc.js" rel="preload" as="script"><link href="/CuttingBoard/css/app.037fc7fb.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but CuttingBoard doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/CuttingBoard/js/chunk-vendors.d9b83edc.js"></script><script src="/CuttingBoard/js/app.25927fa2.js"></script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>CuttingBoard</title><link href="css/app.037fc7fb.css" rel="preload" as="style"><link href="js/app.ed26f79c.js" rel="preload" as="script"><link href="js/chunk-vendors.d232541f.js" rel="preload" as="script"><link href="css/app.037fc7fb.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but CuttingBoard doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.d232541f.js"></script><script src="js/app.ed26f79c.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
docs/js/app.ed26f79c.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
package-lock.json generated
View File

@ -4995,6 +4995,12 @@
"schema-utils": "^2.5.0"
}
},
"file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
"dev": true
},
"filesize": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",

View File

@ -16,6 +16,7 @@
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"file-saver": "^2.0.5",
"sass": "^1.26.5",
"sass-loader": "^8.0.2"
}

View File

@ -9,8 +9,21 @@
<h1>Wood types</h1>
<Wood class="block" />
<h1>Save / load</h1>
<div class="loadSave block">
<p>
<input type="text" v-model="saveFilename" />
<button @click="save()">Save</button>
</p>
<p>
<input type="file" id="loadFile" accept=".json" />
<button @click="load()">Load</button>
</p>
</div>
<h1>About / feedback</h1>
<div class="about">
<div class="about block">
<p>
Created by Mark van Renswoude. Open-source and available under the Unlicense to the public domain on <a href="https://github.com/MvRens/CuttingBoard" target="_blank">Github</a>, where feedback is welcome under Issues.
</p>
@ -36,6 +49,8 @@ import Wood from './components/Wood.vue'
import EndGrainPreview from './components/EndGrainPreview.vue'
import EdgeGrainPreview from './components/EdgeGrainPreview.vue'
import { saveAs } from 'file-saver';
export default {
name: 'App',
components: {
@ -44,6 +59,42 @@ export default {
Settings,
Layers,
Wood
},
data()
{
return {
saveFilename: 'My cutting board'
}
},
methods: {
save()
{
const state = this.$store.getters.save;
const blob = new Blob([state], { type: 'text/plain; charset=utf-8' });
saveAs(blob, this.saveFilename + '.json');
},
load()
{
const loadFile = document.getElementById("loadFile").files[0];
if (!loadFile)
return;
this.saveFilename = loadFile.name.toLowerCase().endsWith('.json')
? loadFile.name.substring(0, loadFile.name.length - 5)
: loadFile.name;
const reader = new FileReader();
reader.addEventListener('load', (event) =>
{
this.$store.commit('load', event.target.result);
});
reader.readAsBinaryString(loadFile);
}
}
}
</script>

View File

@ -1,6 +1,27 @@
import { createStore } from 'vuex';
import { units } from './lib/units';
function mergeObject(source, target)
{
for (const property in source)
{
if (!source.hasOwnProperty(property) || !target.hasOwnProperty(property))
continue;
target[property] = source[property];
}
}
function parseFloatDef(value)
{
const parsedValue = parseFloat(value);
return Object.is(parsedValue, NaN) ? 0 : parsedValue;
}
export default createStore({
state: {
settings: {
@ -103,16 +124,67 @@ export default createStore({
updateSettings(state, payload)
{
for (const property in payload)
{
if (!payload.hasOwnProperty(property) || !state.settings.hasOwnProperty(property))
continue;
mergeObject(payload, state.settings);
},
state.settings[property] = payload[property];
load(state, payload)
{
const parsedPayload = JSON.parse(payload);
if (parsedPayload.hasOwnProperty('settings'))
mergeObject(parsedPayload.settings, state.settings);
if (parsedPayload.hasOwnProperty('boards'))
{
const newBoards = parsedPayload.boards.map(board =>
{
if (!board.hasOwnProperty('layers'))
{
return {
layers: []
};
}
return {
layers: board.layers.map(layer =>
{
return {
wood: parseFloatDef(layer.wood),
width: parseFloatDef(layer.width)
}
})
};
})
if (newBoards.length === 0)
newBoards.push({ layers: [] });
state.boards = newBoards;
}
if (parsedPayload.hasOwnProperty('wood'))
{
const newWood = parsedPayload.wood.map(item =>
{
return {
name: item.name,
color: item.color
};
});
state.wood = newWood;
}
// TODO validate layers and wood types and apply the new sets
}
},
actions: {
getters: {
save(state)
{
return JSON.stringify(state);
}
}
})

View File

@ -1,6 +1,6 @@
module.exports = {
outputDir: 'docs',
publicPath: '/CuttingBoard/',
publicPath: '',
chainWebpack: config => {
config