Switch backend to NeDB storage, fix image/json creation
This commit is contained in:
parent
828ddf39e2
commit
8afda19685
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
/decks
|
||||
/dist/
|
||||
/.cache/
|
||||
/decks.db
|
||||
|
61
package-lock.json
generated
61
package-lock.json
generated
@ -1297,6 +1297,14 @@
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
|
||||
"integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg=="
|
||||
},
|
||||
"binary-search-tree": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz",
|
||||
"integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=",
|
||||
"requires": {
|
||||
"underscore": "~1.4.4"
|
||||
}
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "http://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz",
|
||||
@ -4000,6 +4008,11 @@
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
|
||||
"integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="
|
||||
},
|
||||
"immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
|
||||
@ -4422,6 +4435,22 @@
|
||||
"type-check": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"lie": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
|
||||
"requires": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"localforage": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz",
|
||||
"integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==",
|
||||
"requires": {
|
||||
"lie": "3.1.1"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
@ -4679,6 +4708,33 @@
|
||||
"to-regex": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"nedb": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz",
|
||||
"integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=",
|
||||
"requires": {
|
||||
"async": "0.2.10",
|
||||
"binary-search-tree": "0.2.5",
|
||||
"localforage": "^1.3.0",
|
||||
"mkdirp": "~0.5.1",
|
||||
"underscore": "~1.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
||||
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
|
||||
}
|
||||
}
|
||||
},
|
||||
"nedb-promises": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-3.0.2.tgz",
|
||||
"integrity": "sha512-9GyvhZF7LRHMbOsk+6peJc9IdmWifZAGG/er0sE8VZSOsNJII+Aywcrm5OcesSbu9GZ7E1PxnL63kYqypeZw9Q==",
|
||||
"requires": {
|
||||
"nedb": "^1.8.0"
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
||||
@ -7026,6 +7082,11 @@
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "http://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
|
||||
"integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
|
||||
},
|
||||
"unicode-canonical-property-names-ecmascript": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||
|
@ -14,6 +14,7 @@
|
||||
"dependencies": {
|
||||
"express": "^4.16.4",
|
||||
"interactjs": "^1.3.4",
|
||||
"nedb-promises": "^3.0.2",
|
||||
"parcel-bundler": "^1.11.0",
|
||||
"phantom": "^4.0.12",
|
||||
"v-runtime-template": "^1.5.2",
|
||||
|
19
src/404.vue
Normal file
19
src/404.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<vue-headful title="404 Not Found"> </vue-headful>
|
||||
<h1>Error 404: Path {{ path }} not found</h1>
|
||||
You seem to have gone to the wrong place, would you like to go
|
||||
back to the <a href="/">Deck Index</a>?
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Err404',
|
||||
data() {
|
||||
return {
|
||||
path: window.location.pathname,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
47
src/Deck.vue
Normal file
47
src/Deck.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<!-- style is inline for phantomjs -->
|
||||
<div style="white-space: nowrap;">
|
||||
<div v-for="cardRow in chunkedCards">
|
||||
<span v-for="card in cardRow" @click="$emit('input', card)">
|
||||
<Hero v-bind="card.card"> </Hero>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Hero from './template/hero/Hero.vue'
|
||||
|
||||
export default {
|
||||
name: 'Deck',
|
||||
props: ['deckInfo'],
|
||||
components: {Hero},
|
||||
|
||||
computed: {
|
||||
cards() {
|
||||
console.log
|
||||
return Object
|
||||
.keys(this.deckInfo)
|
||||
.filter(cardType => cardType !== 'meta')
|
||||
.flatMap(cardType => this.deckInfo[cardType].flatMap((card, index) => {
|
||||
let cardWrapper = {
|
||||
type: cardType,
|
||||
card: this.deckInfo[cardType][index],
|
||||
props: Hero.props,
|
||||
};
|
||||
return Array(card.count || 1).fill(cardWrapper);
|
||||
}));
|
||||
},
|
||||
|
||||
chunkedCards() {
|
||||
// find minimum box to fit cards
|
||||
let columns = Math.ceil(Math.sqrt(this.cards.length));
|
||||
let rows = Math.ceil(this.cards.length / columns) || 0;
|
||||
return Array(rows)
|
||||
.fill()
|
||||
.map((_, index) => index * columns)
|
||||
.map(begin => this.cards.slice(begin, begin + columns));
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
@ -1,14 +1,11 @@
|
||||
<template>
|
||||
<body>
|
||||
<label>Create New Deck:
|
||||
<input type="text"
|
||||
@change="window.location='/deck/' + event.target.value + '/editor'">
|
||||
</label>
|
||||
<router-link to="/edit/new">Create New Deck</router-link>
|
||||
<ul>
|
||||
<li v-for="deck in decks">
|
||||
{{ deck }}:
|
||||
<router-link :to="'/play/' + deck"> Play </router-link>
|
||||
<router-link :to="'/edit/' + deck"> Edit </router-link>
|
||||
{{ deck.deck.meta.name }}:
|
||||
<router-link :to="'/play/' + deck._id"> Play </router-link>
|
||||
<router-link :to="'/edit/' + deck._id"> Edit </router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
@ -26,7 +23,8 @@
|
||||
created() {
|
||||
fetch('/decks.json')
|
||||
.then(r => r.json())
|
||||
.then(d => this.decks = d);
|
||||
.then(d => this.decks = d)
|
||||
.catch(err => console.log("Couldn't get deck list"));
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
108
src/Editor.vue
108
src/Editor.vue
@ -8,7 +8,7 @@
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
@click="downloadFile('deck.tts.json', deckName + '.json')">
|
||||
@click="downloadFile('/decks/' + deckID + '.tts.json', deckInfo.meta.name + '.tts.json')">
|
||||
Download Tabletop Output JSON
|
||||
</button>
|
||||
</div>
|
||||
@ -21,11 +21,11 @@
|
||||
|
||||
<form>
|
||||
<div>
|
||||
<label> Deck Name: <input type="text" v-model="deckName"> </label>
|
||||
<label> Deck Name: <input type="text" v-model="deckInfo.meta.name"> </label>
|
||||
</div>
|
||||
<div>
|
||||
<label> Deck Type:
|
||||
<select v-model="deckInfo.type">
|
||||
<select v-model="deckInfo.meta.type">
|
||||
<option value="hero">hero</option>
|
||||
<option value="villain">villain</option>
|
||||
<option value="environment">environment</option>
|
||||
@ -37,84 +37,53 @@
|
||||
|
||||
<div id="cardEditor" v-if="selected">
|
||||
<button class="close-editor" @click="selected = null">X</button>
|
||||
<div v-for="(type, prop) in selectedCardProps">
|
||||
<div v-for="(type, prop) in selected.props">
|
||||
<label> {{ prop }}
|
||||
<input v-if="type === Number" v-model="selected.card[prop]"/>
|
||||
<input v-if="type === 'file'" v-model="selected.card[prop]"/>
|
||||
<input v-if="type === 'file'" type="file" accept="image/*"
|
||||
@change="fileUploaded(prop, $event)" />
|
||||
<textarea v-else rows="1" v-model="selected.card[prop]"> </textarea>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref="deck" :style="deckStyle">
|
||||
<div v-for="card in cards" @click="selected = card">
|
||||
<Hero v-bind="card.card"> </Hero>
|
||||
</div>
|
||||
</div>
|
||||
<Deck ref="deck" :deckInfo="deckInfo" v-model="selected"> </Deck>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Hero from './template/hero/Hero.vue'
|
||||
import Deck from './Deck.vue';
|
||||
|
||||
export default {
|
||||
name: 'Editor',
|
||||
components: {Deck},
|
||||
|
||||
components: {Hero},
|
||||
|
||||
props: ['deckName'],
|
||||
props: ['deckID'],
|
||||
data() {
|
||||
return {
|
||||
selected: null,
|
||||
deckInfo: {},
|
||||
deckInfo: {meta: {name: "", type: ""}},
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
deckName() {
|
||||
document.title = "Editor|" + deckName;
|
||||
deckInfo() {
|
||||
document.title = "Editor|" + this.deckInfo.meta.name;
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
fetch('/decks/' + this.deckName + '.input.json')
|
||||
.then(r => r.json())
|
||||
.then(j => this.deckInfo = j);
|
||||
if (this.deckID !== 'new') {
|
||||
fetch('/decks/' + this.deckID + '.json')
|
||||
.then(r => r.json())
|
||||
.then(j => this.deckInfo = j.input)
|
||||
.catch((err) => console.log('did not get old JSON, starting new deck'));
|
||||
}
|
||||
|
||||
/* window.addEventListener(
|
||||
* 'beforeunload', e => e.returnValue = "Unsaved changes blah blah"); */
|
||||
},
|
||||
|
||||
computed: {
|
||||
cards() {
|
||||
return Object
|
||||
.keys(this.deckInfo)
|
||||
.filter(cardType => typeof this.deckInfo[cardType] !== 'string')
|
||||
.flatMap(cardType => this.deckInfo[cardType].flatMap((card, index) => {
|
||||
let cardWrapper = {
|
||||
type: cardType,
|
||||
card: this.deckInfo[cardType][index],
|
||||
};
|
||||
return Array(card.count || 1).fill(cardWrapper);
|
||||
}));
|
||||
},
|
||||
|
||||
deckStyle() {
|
||||
// find minimum box to fit cards
|
||||
let rows = Math.ceil(Math.sqrt(this.cards.length));
|
||||
let columns = this.cards.length > rows * (rows - 1) ? rows : rows - 1;
|
||||
return {
|
||||
display: 'grid',
|
||||
'grid-template-columns': `repeat(${rows}, 1fr)`,
|
||||
'grid-template-rows': `repeat(${columns}, 1fr)`,
|
||||
};
|
||||
},
|
||||
|
||||
selectedCardProps() {
|
||||
// todo: make better
|
||||
return Hero.props;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
// deck JSON uploader
|
||||
jsonUpload(event) {
|
||||
@ -131,22 +100,15 @@
|
||||
console.log(JSON.stringify(this.deckInfo));
|
||||
this.downloadFile('data:application/json;charset=utf-8,' +
|
||||
encodeURIComponent(JSON.stringify(this.deckInfo)),
|
||||
this.deckName + '.input.json')
|
||||
this.deckID + '.input.json')
|
||||
},
|
||||
|
||||
// chrome doesn't seem to send input event on file select
|
||||
fileUploaded(event) {
|
||||
let prop = event.target.id.substring(5);
|
||||
if (prop === "image") {
|
||||
let files = event.target.files;
|
||||
let reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
selected.svg.querySelector('#' + prop)
|
||||
.setAttributeNS("http://www.w3.org/1999/xlink", "href", e.target.result);
|
||||
selected.json[prop] = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(files[0]);
|
||||
}
|
||||
fileUploaded(event, prop) {
|
||||
let reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
this.selected.card[prop] = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
},
|
||||
|
||||
downloadFile(file, name) {
|
||||
@ -159,13 +121,19 @@
|
||||
},
|
||||
|
||||
upload() {
|
||||
// POST the generated SVGs to the server
|
||||
let data = (new XMLSerializer()).serializeToString(this.$refs.deck);
|
||||
fetch('upload', {
|
||||
// POST the inputed json to the server
|
||||
fetch('/upload', {
|
||||
method: 'post',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({body: data, json: this.deckInfo})
|
||||
});
|
||||
body: JSON.stringify({
|
||||
id: this.deckID === 'new' ? undefined : this.deckID,
|
||||
deck: this.deckInfo,
|
||||
body: (new XMLSerializer()).serializeToString(this.$refs.deck.$el),
|
||||
})
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(j => this.$router.replace('/edit/' + j.id))
|
||||
.catch(err => console.log('Failed to upload' + err));
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -4,13 +4,16 @@ import VueRouter from 'vue-router';
|
||||
import App from './App.vue';
|
||||
import DeckIndex from './DeckIndex.vue';
|
||||
import Editor from './Editor.vue';
|
||||
import Err404 from './404.vue';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
routes: [
|
||||
{path: '/', component: DeckIndex},
|
||||
{path: '/edit/:deckName', component: Editor, props: true},
|
||||
{path: '/edit/:deckID', component: Editor, props: true},
|
||||
{path: '*', component: Err404},
|
||||
],
|
||||
});
|
||||
|
||||
|
177
src/server.js
177
src/server.js
@ -2,23 +2,25 @@
|
||||
// jshint esversion:6
|
||||
"use strict";
|
||||
|
||||
const express = require('express'),
|
||||
Bundler = require('parcel-bundler'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
phantom = require('phantom'),
|
||||
port = process.env.PORT || 1234;
|
||||
const express = require('express'),
|
||||
Bundler = require('parcel-bundler'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
phantom = require('phantom'),
|
||||
Datastore = require('nedb-promises'),
|
||||
port = process.env.PORT || 1234;
|
||||
|
||||
const decks = ["the_Unholy_Priest_update_2",
|
||||
"NZoths_Invasion_1.2",
|
||||
"Puffer_Fish_input_1.3"];
|
||||
|
||||
const db = Datastore.create('decks.db');
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use(express.json({limit: '50mb'}));
|
||||
|
||||
app.use('/template', express.static('template'));
|
||||
app.use('/decks', express.static('decks'));
|
||||
app.get('/decks.json', (req, res) => res.json(decks));
|
||||
app.get('/decks/:deckID.tts.json', getTTSJSON);
|
||||
app.get('/decks/:deckID.json', getInputJSON);
|
||||
app.get('/decks/:deckID.png', getDeckImage);
|
||||
app.get('/decks.json', getDecksList);
|
||||
app.post('/upload', handleUpload);
|
||||
|
||||
let bundler = new Bundler(path.join(__dirname, 'index.html'));
|
||||
@ -26,84 +28,93 @@ app.use(bundler.middleware());
|
||||
|
||||
app.listen(port, () => console.log(`App listening on port ${port}!`));
|
||||
|
||||
function handleUpload(req, res) {
|
||||
const json = request.body;
|
||||
const deckJSON = json.json;
|
||||
const cardTemplate = fs.readFileSync('template/card.json');
|
||||
const template = JSON.parse(fs.readFileSync(`template/${deckJSON.type}/input.json`));
|
||||
const cardCount = Object.entries(template.cardTypes)
|
||||
.map(ct => deckJSON[ct[0]].length * (ct[1].back ? 2 : 1))
|
||||
.reduce((sum, current) => sum + current, 0);
|
||||
function getDecksList(req, res) {
|
||||
db.find({}, {'deck.meta': 1})
|
||||
.then(docs => res.json(docs))
|
||||
.catch(err => res.status(404).end());
|
||||
}
|
||||
|
||||
let deckOut = JSON.parse(fs.readFileSync('template/deck.json'));
|
||||
deckOut.ObjectStates[0].Nickname = deckJSON.name;
|
||||
function getInputJSON(req, res) {
|
||||
db.findOne({_id: req.params.deckID})
|
||||
.then(doc => res.json(doc.input))
|
||||
.catch(err => res.status(404).end());
|
||||
}
|
||||
|
||||
Object.assign(deckOut.ObjectStates[0].CustomDeck['1'],
|
||||
{NumWidth: Math.ceil(Math.sqrt(cardCount)),
|
||||
NumHeight: Math.ceil(Math.sqrt(cardCount)),
|
||||
FaceURL: `http://${req.headers.host}/deck/${deckJSON.name}/deck.png`,
|
||||
BackURL: "http://cloud-3.steamusercontent.com/ugc/156906385556221451/CE2C3AFE1759790CB0B532FFD636D05A99EC91F4/"});
|
||||
function getDeckImage(req, res) {
|
||||
db.findOne({_id: req.params.deckID})
|
||||
.then(doc => res.send(new Buffer.from(doc.image, 'base64')))
|
||||
.catch(err => res.status(404).end());
|
||||
}
|
||||
|
||||
let index = 100;
|
||||
deckOut.ObjectStates[0].ContainedObjects =
|
||||
Object.entries(template.cardTypes).map(
|
||||
cardType => deckJSON[cardType[0]].map(cardIn => {
|
||||
let cardOut = JSON.parse(cardTemplate);
|
||||
Object.assign(cardOut, {Nickname: cardIn.name,
|
||||
Description: cardIn.keywords,
|
||||
CardID: index});
|
||||
function getTTSJSON(req, res) {
|
||||
db.findOne({_id: req.params.deckID})
|
||||
.then(doc => {
|
||||
let deckIn = doc.deck;
|
||||
const cardTemplate = fs.readFileSync(__dirname + '/template/card.json');
|
||||
const template = JSON.parse(fs.readFileSync(__dirname + `/template/${deckIn.type}/input.json`));
|
||||
const cardCount = Object.entries(template.cardTypes)
|
||||
.map(ct => deckIn[ct[0]].length * (ct[1].back ? 2 : 1))
|
||||
.reduce((sum, current) => sum + current, 0);
|
||||
|
||||
for (let ii=0; ii<(cardIn.count || 1); ii++) {
|
||||
deckOut.ObjectStates[0].DeckIDs.push(index);
|
||||
}
|
||||
index++;
|
||||
let deckOut = JSON.parse(fs.readFileSync(__dirname + '/template/deck.json'));
|
||||
deckOut.ObjectStates[0].Nickname = deckIn.meta.name;
|
||||
|
||||
if(cardType[1].back) {
|
||||
let cardBack = JSON.parse(cardTemplate);
|
||||
Object.assign(cardBack, {Nickname: cardIn.back.name,
|
||||
Description: cardIn.back.keywords,
|
||||
CardID: index});
|
||||
cardOut.States = {"2": cardBack};
|
||||
Object.assign(deckOut.ObjectStates[0].CustomDeck['1'],
|
||||
{NumWidth: Math.ceil(Math.sqrt(cardCount)),
|
||||
NumHeight: Math.ceil(cardCount/Math.ceil(Math.sqrt(cardCount))),
|
||||
FaceURL: `http://${req.headers.host}/decks/${doc.meta.name}.png`,
|
||||
BackURL: "http://cloud-3.steamusercontent.com/ugc/156906385556221451/CE2C3AFE1759790CB0B532FFD636D05A99EC91F4/"});
|
||||
|
||||
let index = 100;
|
||||
deckOut.ObjectStates[0].ContainedObjects = Object
|
||||
.keys(deckIn)
|
||||
.filter(cardType => cardType !== 'meta')
|
||||
.map(cardType => deckIn[cardType].map((card, index) => {
|
||||
let cardOut = {...JSON.parse(cardTemplate),
|
||||
Nickname: card.name,
|
||||
Description: card.keywords,
|
||||
CardID: index};
|
||||
|
||||
deckOut.ObjectStates[0].DeckIDs.push(...Array(card.count || 1).fill(index));
|
||||
index++;
|
||||
}
|
||||
return cardOut;
|
||||
}))
|
||||
.reduce((sum, cur) => sum.concat(cur), []);
|
||||
|
||||
fs.writeFileSync(`decks/${deckJSON.name}.json`, JSON.stringify(deckOut));
|
||||
fs.writeFileSync(`decks/${deckJSON.name}.input.json`, JSON.stringify(deckJSON));
|
||||
|
||||
console.log("making page");
|
||||
phantom.create().then(
|
||||
ph => ph.createPage().then(
|
||||
page => {
|
||||
page.on('onLoadFinished', status => {
|
||||
if (status !== 'success') {
|
||||
console.log('Failed to load page');
|
||||
ph.exit(1);
|
||||
if(card.back) {
|
||||
cardOut.States = {"2": {...JSON.parse(cardTemplate),
|
||||
Nickname: card.back.name,
|
||||
Description: card.back.keywords,
|
||||
CardID: index}};
|
||||
index++;
|
||||
}
|
||||
else {
|
||||
page.render(`decks/${deckJSON.name}.png`);
|
||||
return cardOut;
|
||||
}))
|
||||
.reduce((sum, cur) => sum.concat(cur), []); // flatten
|
||||
|
||||
res.json(deckOut);
|
||||
});
|
||||
}
|
||||
|
||||
function handleUpload(req, res) {
|
||||
const json = req.body;
|
||||
|
||||
console.log("Making deck image");
|
||||
phantom.create().then(ph => ph.createPage().then(
|
||||
page => {
|
||||
page.on('onLoadFinished', status => {
|
||||
if (status === 'success') {
|
||||
page.renderBase64(`PNG`).then(image => {
|
||||
db.update({_id: json.id},
|
||||
{deck: json.deck, image: image},
|
||||
{upsert: true, returnUpdatedDocs: true})
|
||||
.then(doc => res.status(201).json({id: doc._id}));
|
||||
page.close().then(() => ph.exit());
|
||||
}
|
||||
});
|
||||
page.property('zoomFactor', 2); // pretty arbitrary
|
||||
page.property('content', '<body style="margin:0;">' + json.body + '</body>');
|
||||
}));
|
||||
decks.push(deckJSON.name);
|
||||
}
|
||||
|
||||
function send404(res, uri) {
|
||||
res.writeHead(404, {'Content-type': "text/html; charset=utf-8"});
|
||||
const html = `
|
||||
<head>
|
||||
<title>404 Not Found</title>
|
||||
<link rel="stylesheet" href="/css/common.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Error 404: Path ${uri.pathname} not found</h1>
|
||||
You seem to have gone to the wrong place, would you like to go
|
||||
back to the <a href="/">main page</a>?
|
||||
</body>`;
|
||||
res.end(html, 'utf-8');
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log('Failed to load page');
|
||||
ph.exit(1);
|
||||
}
|
||||
});
|
||||
page.property('zoomFactor', 2); // pretty arbitrary
|
||||
page.property('content', '<body style="margin:0;">' + json.body + '</body>');
|
||||
}));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user