summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2020-06-03 20:32:38 +0200
committerJules Laplace <julescarbon@gmail.com>2020-06-03 20:32:38 +0200
commit03e76928e3747167dceac3d92759a3abe5b685c7 (patch)
tree51578ee4bc38569da71ad97baf9fb5d3e9969174
parente52dcc61ed433980d760a050ff14852a05676b96 (diff)
positioning tiles
-rw-r--r--frontend/store.js2
-rw-r--r--frontend/types.js8
-rw-r--r--frontend/views/page/components/page.editor.js87
-rw-r--r--frontend/views/page/components/tile.edit.js7
-rw-r--r--frontend/views/page/components/tile.form.js46
-rw-r--r--frontend/views/page/components/tile.new.js5
-rw-r--r--frontend/views/page/page.css23
-rw-r--r--frontend/views/page/page.reducer.js2
-rw-r--r--frontend/views/tile/tile.actions.js10
-rw-r--r--frontend/views/tile/tile.reducer.js31
10 files changed, 181 insertions, 40 deletions
diff --git a/frontend/store.js b/frontend/store.js
index 1fb7789..40c8d9c 100644
--- a/frontend/store.js
+++ b/frontend/store.js
@@ -7,6 +7,7 @@ import thunk from 'redux-thunk'
import uploadReducer from './views/upload/upload.reducer'
import graphReducer from './views/graph/graph.reducer'
import pageReducer from './views/page/page.reducer'
+import tileReducer from './views/tile/tile.reducer'
import siteReducer from './views/site/site.reducer'
// import collectionReducer from './views/collection/collection.reducer'
@@ -17,6 +18,7 @@ const createRootReducer = history => (
site: siteReducer,
graph: graphReducer,
page: pageReducer,
+ tile: tileReducer,
upload: uploadReducer,
// collection: collectionReducer,
})
diff --git a/frontend/types.js b/frontend/types.js
index 4a1b39d..a0d83a1 100644
--- a/frontend/types.js
+++ b/frontend/types.js
@@ -1,17 +1,23 @@
import { with_type, crud_type } from './api/crud.types'
export const api = crud_type('api', [])
+
export const graph = crud_type('graph', [
'show_add_page_form', 'hide_add_page_form',
'show_edit_page_form', 'hide_edit_page_form',
'update_graph_page',
])
+
export const page = crud_type('page', [
'show_add_tile_form', 'hide_add_tile_form',
'show_edit_tile_form', 'hide_edit_tile_form',
'update_page_tile',
])
-export const tile = crud_type('tile', [])
+
+export const tile = crud_type('tile', [
+ 'update_temporary_tile', 'remove_temporary_tile',
+])
+
export const upload = crud_type('upload', [])
export const site = with_type('site', [
diff --git a/frontend/views/page/components/page.editor.js b/frontend/views/page/components/page.editor.js
index 952e45c..5929b15 100644
--- a/frontend/views/page/components/page.editor.js
+++ b/frontend/views/page/components/page.editor.js
@@ -85,6 +85,7 @@ class PageEditor extends Component {
mouseX,
mouseY,
box: {
+ dx: 0, dy: 0,
x, y,
w, h,
},
@@ -107,6 +108,7 @@ class PageEditor extends Component {
let dy = (e.pageY - mouseY) / bounds.height
this.setState({
box: {
+ dx, dy,
x: clamp(x + dx, 0, 1.0 - w),
y: clamp(y + dy, 0, 1.0 - h),
w, h,
@@ -143,50 +145,97 @@ class PageEditor extends Component {
render(){
// console.log(this.props.page.show.res)
+ if (!this.state.bounds) {
+ return (
+ <div className='page' ref={this.pageRef} />
+ )
+ }
+ const { temporaryTile } = this.props
const currentTile = this.state.tile
const currentBox = this.state.box
const { res } = this.props.page.show
// console.log(res.tiles)
return (
<div className='page' ref={this.pageRef}>
- {this.state.bounds && res.tiles.map(tile => (
+ {res.tiles.map(tile => {
+ if (temporaryTile && temporaryTile.id === tile) {
+ tile = temporaryTile
+ }
+ return (
+ <TileHandle
+ key={tile.id}
+ tile={tile}
+ bounds={this.state.bounds}
+ box={currentTile && tile.id === currentTile.id && currentBox}
+ onMouseDown={e => this.handleMouseDown(e, tile)}
+ />
+ )
+ })}
+ {!!(temporaryTile && temporaryTile.id === 'new') && (
<TileHandle
- key={tile.id}
- tile={tile}
+ key={temporaryTile.id}
+ tile={temporaryTile}
bounds={this.state.bounds}
box={currentTile && tile.id === currentTile.id && currentBox}
- onMouseDown={e => this.handleMouseDown(e, tile)}
+ onMouseDown={e => this.handleMouseDown(e, temporaryTile)}
/>
- ))}
+ )}
</div>
)
}
}
const TileHandle = ({ tile, bounds, box, onMouseDown }) => {
- let style;
- if (box) {
- style = {
- top: (bounds.height) * box.y,
- left: (bounds.width) * box.x,
- }
- } else {
- style = {
- top: (bounds.height) * Math.min(tile.settings.y, 0.95),
- left: (bounds.width) * Math.min(tile.settings.x, 0.95),
- }
+ console.log(tile)
+ const { width, height } = tile.settings
+ const style = {
+ // width, height,
+ transform: generateTransform(tile),
+ }
+ console.log(generateTransform(tile))
+ let content;
+ switch (tile.type) {
+ case 'image':
+ content = <img src={tile.settings.url} />
+ break
+ case 'text':
+ content = <span dangerouslySetInnerHTML={{ __html: tile.settings.content }} />
+ break
}
- // console.log(style)
return (
- <div className='handle' onMouseDown={onMouseDown} style={style}>
- {tile.title}
+ <div className={'tile ' + tile.type + ' ' + tile.settings.align} onMouseDown={onMouseDown} style={style}>
+ {content}
</div>
)
}
+const generateTransform = tile => {
+ const { x, y, align, rotation, scale } = tile.settings
+ const [yalign, xalign] = align.split('_')
+ let transform = ['translateZ(0)']
+ if (yalign === 'center') {
+ transform.push('translateY(-50%)')
+ }
+ if (xalign === 'center') {
+ transform.push('translateX(-50%)')
+ }
+ // if (x % 2 == 1) x += 0.5
+ // if (y % 2 == 1) y += 0.5
+ transform.push('translateX(' + x + 'px)')
+ transform.push('translateY(' + y + 'px)')
+ if (scale !== 1) {
+ transform.push('scale(' + scale + ')')
+ }
+ if (rotation !== 0) {
+ transform.push('rotateZ(' + rotation + 'rad)')
+ }
+ return transform.join(' ')
+}
+
const mapStateToProps = state => ({
graph: state.graph,
page: state.page,
+ temporaryTile: state.tile.temporaryTile,
})
const mapDispatchToProps = dispatch => ({
diff --git a/frontend/views/page/components/tile.edit.js b/frontend/views/page/components/tile.edit.js
index 6d8d835..c2e3126 100644
--- a/frontend/views/page/components/tile.edit.js
+++ b/frontend/views/page/components/tile.edit.js
@@ -1,8 +1,9 @@
import React, { Component } from 'react'
-import { Link } from 'react-router-dom'
+// import { Link } from 'react-router-dom'
+// import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
-import { history } from '../../../store'
+// import { history } from '../../../store'
import actions from '../../../actions'
import { Loader } from '../../../common'
@@ -50,7 +51,7 @@ const mapStateToProps = state => ({
})
const mapDispatchToProps = dispatch => ({
- // searchActions: bindActionCreators({ ...searchActions }, dispatch),
+ // tileActions: bindActionCreators({ ...tileActions }, dispatch),
})
export default connect(mapStateToProps, mapDispatchToProps)(TileEdit)
diff --git a/frontend/views/page/components/tile.form.js b/frontend/views/page/components/tile.form.js
index 9bd8f14..dc81c1a 100644
--- a/frontend/views/page/components/tile.form.js
+++ b/frontend/views/page/components/tile.form.js
@@ -1,10 +1,14 @@
import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { bindActionCreators } from 'redux'
import { Link } from 'react-router-dom'
import { session } from '../../../session'
import { TextInput, NumberInput, Select, LabelDescription, TextArea, Checkbox, SubmitButton, Loader } from '../../../common'
+import * as tileActions from '../../tile/tile.actions'
+
const SELECT_TYPES = [
"image", "text"
].map(s => ({ name: s, label: s }))
@@ -28,20 +32,21 @@ const REQUIRED_KEYS = {
// target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True)
const newImage = (data) => ({
+ id: 'new',
settings: {
...newPosition(),
tile: false,
- url: "",
+ url: "https://s3.amazonaws.com/i.asdf.us/im/1c/gradient_gold1-SpringGreen1_1321159749.jpg",
},
type: 'image',
...data,
})
const newText = (data) => ({
+ id: 'new',
settings: {
...newPosition(),
- tile: false,
- url: "",
+ content: "",
width: 200,
height: 200,
},
@@ -56,11 +61,11 @@ const newPosition = () => ({
align: "center_center",
})
-export default class TileForm extends Component {
+class TileForm extends Component {
state = {
title: "",
submitTitle: "",
- data: { ...newText() },
+ data: { ...newImage() },
errorFields: new Set([]),
}
@@ -77,7 +82,7 @@ export default class TileForm extends Component {
graph_id: graph.id,
page_id: page.id,
},
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
handleChange(e) {
@@ -100,7 +105,7 @@ export default class TileForm extends Component {
this.setState({
errorFields,
data: newData,
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
this.setState({
errorFields,
@@ -108,7 +113,7 @@ export default class TileForm extends Component {
...this.state.data,
[name]: value,
}
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
handleSettingsChange(e) {
@@ -122,11 +127,11 @@ export default class TileForm extends Component {
data: {
...this.state.data,
settings: {
- ...this.state.settings,
+ ...this.state.data.settings,
[name]: value,
}
}
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
handleSelect(name, value) {
@@ -140,7 +145,7 @@ export default class TileForm extends Component {
...this.state.data,
[name]: value,
}
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
handleSettingsSelect(name, value) {
@@ -157,7 +162,7 @@ export default class TileForm extends Component {
[name]: value,
}
}
- })
+ }, () => this.props.tileActions.updateTemporaryTile(this.state.data))
}
handleSubmit(e) {
@@ -233,6 +238,7 @@ export default class TileForm extends Component {
renderPositionInfo() {
const { x, y, width, height, rotation, scale } = this.state.data.settings
+ // console.log(this.state.data.settings)
return (
<div className='position'>
{''}{parseInt(x)}{', '}
@@ -246,7 +252,7 @@ export default class TileForm extends Component {
renderImageForm() {
// const { isNew } = this.props
- const { data } = this.state
+ const { errorFields, data } = this.state
return (
<div>
<TextInput
@@ -272,7 +278,7 @@ export default class TileForm extends Component {
}
renderTextForm() {
- const { data } = this.state
+ const { errorFields, data } = this.state
return (
<div>
<TextArea
@@ -310,3 +316,15 @@ export default class TileForm extends Component {
)
}
}
+
+const mapStateToProps = state => ({
+ graph: state.graph,
+ page: state.page,
+ tile: state.tile,
+})
+
+const mapDispatchToProps = dispatch => ({
+ tileActions: bindActionCreators({ ...tileActions }, dispatch),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(TileForm)
diff --git a/frontend/views/page/components/tile.new.js b/frontend/views/page/components/tile.new.js
index 4e88729..74d8e96 100644
--- a/frontend/views/page/components/tile.new.js
+++ b/frontend/views/page/components/tile.new.js
@@ -1,5 +1,6 @@
import React, { Component } from 'react'
-import { Link } from 'react-router-dom'
+// import { Link } from 'react-router-dom'
+// import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { history } from '../../../store'
@@ -42,7 +43,7 @@ const mapStateToProps = state => ({
})
const mapDispatchToProps = dispatch => ({
- // searchActions: bindActionCreators({ ...searchActions }, dispatch),
+ // tileActions: bindActionCreators({ ...tileActions }, dispatch),
})
export default connect(mapStateToProps, mapDispatchToProps)(TileNew)
diff --git a/frontend/views/page/page.css b/frontend/views/page/page.css
index b0de716..8f671e4 100644
--- a/frontend/views/page/page.css
+++ b/frontend/views/page/page.css
@@ -1,3 +1,26 @@
.page.loading {
padding: 1rem;
}
+
+
+.tile {
+ position: absolute;
+}
+
+.tile.image {
+ display: block;
+}
+
+.tile.text {
+ display: block;
+}
+
+.tile.top_left { top: 0; left: 0; }
+.tile.center_left { top: 50%; left: 0; }
+.tile.bottom_left { bottom: 0; left: 0; }
+.tile.top_center { top: 0; left: 50%; }
+.tile.center_center { top: 50%; left: 50%; }
+.tile.bottom_center { bottom: 0; left: 50%; }
+.tile.top_right { top: 0; right: 0; }
+.tile.center_right { top: 50%; right: 0; }
+.tile.bottom_right { bottom: 0; right: 0; }
diff --git a/frontend/views/page/page.reducer.js b/frontend/views/page/page.reducer.js
index 1494bc2..07acad3 100644
--- a/frontend/views/page/page.reducer.js
+++ b/frontend/views/page/page.reducer.js
@@ -15,7 +15,7 @@ const initialState = crudState('page', {
const reducer = crudReducer('page')
export default function pageReducer(state = initialState, action) {
- console.log(action.type, action)
+ // console.log(action.type, action)
state = reducer(state, action)
switch (action.type) {
case types.page.update_page_tile:
diff --git a/frontend/views/tile/tile.actions.js b/frontend/views/tile/tile.actions.js
new file mode 100644
index 0000000..ab009e8
--- /dev/null
+++ b/frontend/views/tile/tile.actions.js
@@ -0,0 +1,10 @@
+import * as types from '../../types'
+// import { store } from '../../store'
+
+export const updateTemporaryTile = data => dispatch => {
+ dispatch({ type: types.tile.update_temporary_tile, data })
+}
+
+export const removeTemporaryTile = () => dispatch => {
+ dispatch({ type: types.tile.remove_temporary_tile })
+}
diff --git a/frontend/views/tile/tile.reducer.js b/frontend/views/tile/tile.reducer.js
new file mode 100644
index 0000000..102498d
--- /dev/null
+++ b/frontend/views/tile/tile.reducer.js
@@ -0,0 +1,31 @@
+import * as types from '../../types'
+// import { session, getDefault, getDefaultInt } from '../../session'
+
+import { crudState, crudReducer } from '../../api/crud.reducer'
+
+const initialState = crudState('tile', {
+ temporaryTile: null,
+})
+
+const reducer = crudReducer('tile')
+
+export default function tileReducer(state = initialState, action) {
+ // console.log(action.type, action)
+ state = reducer(state, action)
+ switch (action.type) {
+ case types.tile.update_temporary_tile:
+ return {
+ ...state,
+ temporaryTile: action.data
+ }
+
+ case types.tile.remove_temporary_tile:
+ return {
+ ...state,
+ temporaryTile: null
+ }
+
+ default:
+ return state
+ }
+}