Add mobx. Add scratchpad

master
Alfred Melch 6 years ago
parent b82dc913a6
commit a23905c826

@ -2,6 +2,10 @@
# pylint: disable=invalid-name # pylint: disable=invalid-name
import os import os
import io
import base64
from urllib.parse import urlparse
from PIL import Image from PIL import Image
from flask import Blueprint, render_template, session, redirect, url_for, \ from flask import Blueprint, render_template, session, redirect, url_for, \
request, flash, current_app, abort, send_from_directory request, flash, current_app, abort, send_from_directory
@ -59,12 +63,22 @@ def create_tile(z, x, y):
if not valid_tile(z, x, y): if not valid_tile(z, x, y):
return abort(404) return abort(404)
if 'file' not in request.files: image_bytes = None
# try to read file from request.files (byte-stream)
if 'file' in request.files:
image_bytes = request.files['file'].stream
# try to read file from form (base64 encoded dataURL)
if image_bytes is None and ('file' in request.form):
parsed_url = urlparse(request.form['file'])
head, data = parsed_url.path.split(',', 1)
image_bytes = io.BytesIO(base64.b64decode(data))
if image_bytes is None:
flash('No file part') flash('No file part')
return redirect(url_for('index')) return redirect(url_for('index'))
file = request.files['file']
try: try:
image = Image.open(file.stream) image = Image.open(image_bytes)
image = image.resize((256, 256)) image = image.resize((256, 256))
except OSError: except OSError:
flash('cannot read image') flash('cannot read image')

File diff suppressed because one or more lines are too long

@ -27,3 +27,15 @@ main {
.flex > *[main] { .flex > *[main] {
flex: 1; flex: 1;
} }
.tile-image {
border: 2px solid black;
box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.5);
width: 256px;
height: 256px;
}
.current-tile-upload {
display: flex;
justify-content: space-around;
}

@ -2,18 +2,23 @@
{% block body %} {% block body %}
<h1>Wundertile - A collaborative TileLayer</h1> <section class="intro">
<h1>Wundertile - A collaborative TileLayer</h1>
<p>Hello Friend, this Website Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti adipisci est quo libero odit modi iste corporis debitis tenetur sunt similique alias consequuntur, cupiditate suscipit impedit maiores, recusandae fugiat. Obcaecati?</p>
</section>
<p>Hello Friend, this Website Lorem ipsum dolor sit amet consectetur adipisicing elit. Corrupti adipisci est quo libero odit modi iste corporis debitis tenetur sunt similique alias consequuntur, cupiditate suscipit impedit maiores, recusandae fugiat. Obcaecati?</p> <section class="map">
<div id="map"></div>
</section>
<section id="currentTile">
</section>
<div id="map"></div> <section class="about">
<h2>About</h2>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Iusto sed vero, doloribus, dolor laborum cumque ab quo odio dolorem voluptas asperiores debitis reiciendis? Sint aut, iusto sapiente eaque ipsa dolorum.</p>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Error veniam consectetur accusamus distinctio fugit, omnis voluptas. Iure voluptatum omnis unde quas voluptates suscipit neque libero a recusandae quisquam, dolorum voluptate?</p>
</section>
<h2>Current tile</h2>
<div id="currentTile"></div>
<h2>About</h2>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Iusto sed vero, doloribus, dolor laborum cumque ab quo odio dolorem voluptas asperiores debitis reiciendis? Sint aut, iusto sapiente eaque ipsa dolorum.</p>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Error veniam consectetur accusamus distinctio fugit, omnis voluptas. Iure voluptatum omnis unde quas voluptates suscipit neque libero a recusandae quisquam, dolorum voluptate?</p>
<script src="{{ url_for('static', filename='bundle.js') }}"></script> <script src="{{ url_for('static', filename='bundle.js') }}"></script>
{% endblock %} {% endblock %}

@ -0,0 +1,15 @@
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["last 2 versions", "IE >= 9"]
},
}]
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }],
["@babel/plugin-transform-react-jsx", {"pragma": "h"}]
]
}

@ -1,4 +1,5 @@
{ {
"extends": "standard" "extends": ["standard", "standard-preact"],
"parser": "babel-eslint"
} }

@ -1,4 +1,3 @@
import './src/map.js' import './src/map.js'
import './src/currentTile.js'
console.log('Hello World')
console.log('lala')

1819
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -12,9 +12,19 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.4",
"@babel/plugin-proposal-class-properties": "^7.4.4",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-transform-react-jsx": "^7.3.0",
"@babel/preset-env": "^7.4.4",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.5",
"babel-plugin-jsx-pragmatic": "^1.0.2",
"css-loader": "^2.1.1", "css-loader": "^2.1.1",
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-config-standard": "^12.0.0", "eslint-config-standard": "^12.0.0",
"eslint-config-standard-preact": "^1.1.6",
"eslint-plugin-import": "^2.17.2", "eslint-plugin-import": "^2.17.2",
"eslint-plugin-node": "^8.0.1", "eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.1.1", "eslint-plugin-promise": "^4.1.1",
@ -28,6 +38,9 @@
"webpack-dev-server": "^3.3.1" "webpack-dev-server": "^3.3.1"
}, },
"dependencies": { "dependencies": {
"leaflet": "^1.4.0" "leaflet": "^1.4.0",
"mobx": "^5.9.4",
"mobx-preact": "^3.0.0",
"preact": "^8.4.2"
} }
} }

@ -1,12 +1,69 @@
import { Component, h, render } from 'preact'
import { observer } from 'mobx-preact'
import { coordsToPath } from './util.js' import { coordsToPath } from './util.js'
import state from './state.js'
import { Scratchpad } from './scratchpad.js'
const root = document.getElementById('currentTile') const root = document.getElementById('currentTile')
export const render = (coords) => { @observer
root.innerHTML = ` class CurrentTileComponent extends Component {
<div class="flex"> render () {
<img src="/tiles${coordsToPath(coords)}"> let coordsPath = '/tiles/' + coordsToPath(state.coords)
</div> return (
Hello World! ${JSON.stringify(coords)} <div>
` <h2>Current Tile: {coordsToPath(state.coords)}</h2>
<div className='current-tile-upload'>
<SubmitDrawingForm tilePath={coordsPath} />
<UploadForm tilePath={coordsPath} />
<img src={coordsPath} className='tile-image' />
</div>
</div>
)
}
handleClick (e) {
console.log(this.scratchpad.image)
}
} }
class SubmitDrawingForm extends Component {
render (props) {
console.log('submDrawing', props)
return (
(
<div className='uploadForm'>
<Scratchpad ref={s => { this.scratchpad = s }} />
<form
action={props.tilePath}
method='POST'
enctype='multipart/form-data'
onSubmit={(e) => this.handleSubmit(e)}>
<input type='hidden' name='file' ref={f => { this.file = f }} />
<input type='submit' value='Upload Scratch' />
</form>
</div>
)
)
}
handleSubmit (e) {
console.log(this.file, this.scratchpad)
this.file.value = this.scratchpad.image
}
}
class UploadForm extends Component {
render (props) {
console.log(props)
return (
<div className='uploadForm'>
<form action={props.tilePath} method='POST' enctype='multipart/form-data'>
<input type='file' name='file' /><br />
<input type='submit' value='Upload' />
</form>
</div>
)
}
}
export const CurrentTile = render(<CurrentTileComponent />, root)

@ -1,7 +1,7 @@
import { map as LMap, tileLayer } from 'leaflet' import { map as LMap, tileLayer } from 'leaflet'
import 'leaflet/dist/leaflet.css' import 'leaflet/dist/leaflet.css'
import { render } from './currentTile' import state from './state.js'
export const map = LMap('map') export const map = LMap('map')
map.setView([0, 0], 1) map.setView([0, 0], 1)
@ -28,6 +28,5 @@ const getTileCoords = (lat, lon, zoom) => {
// demo: how to get tile coords on click // demo: how to get tile coords on click
map.on('click', (e) => { map.on('click', (e) => {
let coords = getTileCoords(e.latlng.lat, e.latlng.lng, map.getZoom()) state.coords = getTileCoords(e.latlng.lat, e.latlng.lng, map.getZoom())
render(coords)
}) })

@ -0,0 +1,47 @@
import { Component, h } from 'preact'
export class Scratchpad extends Component {
draw = false
render () {
return (
<div>
<canvas
width='256' height='256'
className='tile-image'
onMouseDown={(e) => this.handleMouseDown(e)}
onMouseMove={(e) => this.handleMouseMove(e)}
onMouseUp={(e) => this.handleMouseUp(e)}
onMouseOut={(e) => this.handleMouseOut(e)}
ref={c => { this.canvas = c }}
/>
</div>
)
}
get ctx () {
return this.canvas.getContext('2d')
}
get image () {
return this.canvas.toDataURL()
}
handleMouseDown (e) {
this.draw = true
this.ctx.beginPath()
this.ctx.moveTo(e.layerX, e.layerY)
}
handleMouseMove (e) {
if (this.draw === true) {
this.ctx.lineTo(e.layerX, e.layerY)
this.ctx.stroke()
}
}
handleMouseUp (e) {
this.draw = false
}
handleMouseOut (e) {
}
}

@ -0,0 +1,11 @@
import { observable } from 'mobx'
class State {
@observable coords = { x: 0, y: 0, z: 0 }
setState (newState) {
this.state = { ...this.state, ...newState }
}
}
export default new State()

@ -1 +1 @@
export const coordsToPath = coords => `/${coords.z}/${coords.x}/${coords.y}` export const coordsToPath = coords => `${coords.z}/${coords.x}/${coords.y}`

@ -8,6 +8,9 @@ module.exports = {
}, },
module: { module: {
rules: [{ rules: [{
test: /\.js$/,
use: ['babel-loader']
}, {
test: /\.css$/, test: /\.css$/,
use: ['style-loader', 'css-loader'] use: ['style-loader', 'css-loader']
}, { }, {

Loading…
Cancel
Save