summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/app/site/export.py4
-rw-r--r--frontend/app/views/graph/graph.css10
-rw-r--r--frontend/app/views/page/components/page.editor.js18
-rw-r--r--frontend/app/views/page/page.css3
-rw-r--r--frontend/app/views/tile/components/tile.form.js32
-rw-r--r--frontend/app/views/tile/handles/tile.image.js4
-rw-r--r--frontend/app/views/tile/handles/tile.link.js8
-rw-r--r--frontend/app/views/tile/handles/tile.script.js4
-rw-r--r--frontend/app/views/tile/handles/tile.text.js8
-rw-r--r--frontend/app/views/tile/handles/tile.video.js12
-rw-r--r--frontend/app/views/tile/tile.utils.js22
-rw-r--r--frontend/site/viewer/viewer.container.js29
12 files changed, 117 insertions, 37 deletions
diff --git a/cli/app/site/export.py b/cli/app/site/export.py
index c301a60..4ce8b64 100644
--- a/cli/app/site/export.py
+++ b/cli/app/site/export.py
@@ -93,6 +93,10 @@ def sanitize_graph(graph):
if tile['target_page_id']:
if tile['target_page_id'] == -1:
tile['href'] = tile['settings']['external_link_url']
+ elif tile['target_page_id'] == -2:
+ tile['href'] = '__open_popup'
+ elif tile['target_page_id'] == -3:
+ tile['href'] = '__close_popup'
elif tile['target_page_id'] > 0:
tile['href'] = page_path_lookup[tile['target_page_id']]
if 'url' in tile['settings'] and tile['settings']['url'].startswith('/static'):
diff --git a/frontend/app/views/graph/graph.css b/frontend/app/views/graph/graph.css
index a557280..bfdbe5c 100644
--- a/frontend/app/views/graph/graph.css
+++ b/frontend/app/views/graph/graph.css
@@ -114,10 +114,17 @@
padding: 0.25rem;
}
+.box form .single label span,
.box form .pair label span {
min-width: 3rem;
padding: 0.25rem 0;
}
+.box .single label {
+ flex-direction: row;
+ width: 100%;
+ margin-right: 0.5px;
+ min-width: auto;
+}
.box .pair label {
flex-direction: row;
width: 6.5rem;
@@ -138,13 +145,14 @@ button.box_corner {
background: transparent;
border: 0;
border-radius: 4px;
+ transform: scaleX(-1);
}
button.box_corner:hover {
color: #fff;
background: rgba(64,64,128,0.5);
}
.sidebar.left button.box_corner {
- transform: scaleX(-1);
+ transform: scaleX(1);
}
.box .slider {
diff --git a/frontend/app/views/page/components/page.editor.js b/frontend/app/views/page/components/page.editor.js
index 03190e3..7e841ef 100644
--- a/frontend/app/views/page/components/page.editor.js
+++ b/frontend/app/views/page/components/page.editor.js
@@ -16,6 +16,7 @@ import TileHandle from 'app/views/tile/components/tile.handle'
const defaultState = {
dragging: false,
bounds: null,
+ videoBounds: null,
mouseX: 0,
mouseY: 0,
box: {
@@ -37,6 +38,7 @@ class PageEditor extends Component {
this.handleMouseMove = this.handleMouseMove.bind(this)
this.handleMouseUp = this.handleMouseUp.bind(this)
this.handleWindowResize = this.handleWindowResize.bind(this)
+ this.handlePlaybackEnded = this.handlePlaybackEnded.bind(this)
this.pageRef = React.createRef()
}
@@ -59,7 +61,8 @@ class PageEditor extends Component {
document.body.addEventListener('mousemove', this.handleMouseMove)
document.body.addEventListener('mouseup', this.handleMouseUp)
window.addEventListener('resize', this.handleWindowResize)
- this.setState({ bounds: this.getBoundingClientRect() })
+ const bounds = this.getBoundingClientRect()
+ this.setState({ bounds })
}
componentDidUpdate(prevProps) {
@@ -72,6 +75,10 @@ class PageEditor extends Component {
this.setState({ bounds: this.getBoundingClientRect() })
}
+ handlePlaybackEnded() {
+ //
+ }
+
handleMouseDown(e, tile) {
if (e.metaKey || e.ctrlKey || e.altKey || e.button !== 0) return
const bounds = this.getBoundingClientRect()
@@ -171,10 +178,13 @@ class PageEditor extends Component {
const { res } = this.props.page.show
const { settings } = res
const pageStyle = { backgroundColor: settings ? settings.background_color : '#000000' }
+ const videoBounds = (res.tiles.length && res.tiles[0].type === 'video') ? {
+ width: res.tiles[0].settings.width,
+ height: res.tiles[0].settings.height,
+ } : this.state.bounds
return (
<div className='page' ref={this.pageRef} style={pageStyle}>
{res.tiles && res.tiles.map(tile => {
- console.log(tile.type, tile.settings.is_popup)
if (!this.props.page.editor.showingPopups && tile.settings.is_popup) return
if (temporaryTile && temporaryTile.id === tile.id) {
tile = temporaryTile
@@ -184,9 +194,11 @@ class PageEditor extends Component {
key={tile.id}
tile={tile}
bounds={this.state.bounds}
+ videoBounds={videoBounds}
box={currentTile && tile.id === currentTile.id && currentBox}
onMouseDown={e => this.handleMouseDown(e, tile)}
onDoubleClick={e => this.props.pageActions.showEditTileForm(tile.id)}
+ onPlaybackEnded={this.handlePlaybackEnded}
/>
)
})}
@@ -195,8 +207,10 @@ class PageEditor extends Component {
key={temporaryTile.id}
tile={temporaryTile}
bounds={this.state.bounds}
+ videoBounds={videoBounds}
box={currentTile && temporaryTile.id === currentTile.id && currentBox}
onMouseDown={e => this.handleMouseDown(e, temporaryTile)}
+ onPlaybackEnded={this.handlePlaybackEnded}
/>
)}
</div>
diff --git a/frontend/app/views/page/page.css b/frontend/app/views/page/page.css
index 2014289..2998007 100644
--- a/frontend/app/views/page/page.css
+++ b/frontend/app/views/page/page.css
@@ -117,6 +117,9 @@
.box .row.pair {
justify-content: space-between;
}
+.box .row.single {
+ justify-content: space-between;
+}
.box .pair label:last-child {
margin-right: 0;
}
diff --git a/frontend/app/views/tile/components/tile.form.js b/frontend/app/views/tile/components/tile.form.js
index b33f7b8..3066da3 100644
--- a/frontend/app/views/tile/components/tile.form.js
+++ b/frontend/app/views/tile/components/tile.form.js
@@ -64,6 +64,14 @@ const CURSORS = [
{ name: 'unclickable', label: 'Unclickable', },
]
+const UNITS = [
+ { name: 'px', label: 'pixels' },
+ { name: '%', label: 'percent' },
+ { name: 'video', label: 'video' },
+ { name: 'vmin', label: 'screen min' },
+ { name: 'vmax', label: 'screen max' },
+]
+
const NO_LINK = 0
const EXTERNAL_LINK = -1
const OPEN_POPUP_LINK = -2
@@ -95,7 +103,7 @@ const newImage = (data) => ({
cursor: 'hand_up',
},
type: 'image',
- target_page_id: null,
+ target_page_id: 0,
...data,
})
@@ -114,7 +122,7 @@ const newVideo = (data) => ({
loop_end: 0,
},
type: 'video',
- target_page_id: null,
+ target_page_id: 0,
...data,
})
@@ -134,7 +142,7 @@ const newText = (data) => ({
cursor: 'hand_up',
},
type: 'text',
- target_page_id: null,
+ target_page_id: 0,
...data,
})
@@ -146,7 +154,7 @@ const newLink = (data) => ({
units: 'px',
},
type: 'link',
- target_page_id: null,
+ target_page_id: 0,
...data,
})
@@ -395,6 +403,7 @@ class TileForm extends Component {
} else {
validData.id = temporaryTile.id
}
+ validData.target_page_id = validData.target_page_id || 0
this.setState({ modified: false })
console.log('submit', validData)
onSubmit(validData)
@@ -734,14 +743,13 @@ class TileForm extends Component {
autoComplete="off"
/>
</div>
- <div className='row pair'>
- <TextInput
- title="Units"
- name="units"
- data={temporaryTile.settings}
- error={errorFields.has('units')}
- onChange={this.handleSettingsChange}
- autoComplete="off"
+ <div className='row single'>
+ <Select
+ name='units'
+ selected={temporaryTile.settings.units}
+ options={UNITS}
+ title='Units'
+ onChange={this.handleSettingsSelect}
/>
</div>
</div>
diff --git a/frontend/app/views/tile/handles/tile.image.js b/frontend/app/views/tile/handles/tile.image.js
index fd34876..beeb36a 100644
--- a/frontend/app/views/tile/handles/tile.image.js
+++ b/frontend/app/views/tile/handles/tile.image.js
@@ -1,10 +1,10 @@
import React from 'react'
import { generateTransform } from 'app/views/tile/tile.utils'
-export default function TileImage({ tile, box, viewing, onMouseDown, onDoubleClick }) {
+export default function TileImage({ tile, box, videoBounds, viewing, onMouseDown, onDoubleClick }) {
// console.log(tile)
const style = {
- transform: generateTransform(tile, box),
+ transform: generateTransform(tile, box, videoBounds),
opacity: tile.settings.opacity,
}
// console.log(generateTransform(tile))
diff --git a/frontend/app/views/tile/handles/tile.link.js b/frontend/app/views/tile/handles/tile.link.js
index 20d881b..a87b95f 100644
--- a/frontend/app/views/tile/handles/tile.link.js
+++ b/frontend/app/views/tile/handles/tile.link.js
@@ -1,10 +1,10 @@
import React from 'react'
import { generateTransform, unitsDimension } from 'app/views/tile/tile.utils'
-export default function TileScript({ tile, box, viewing, onMouseDown, onDoubleClick }) {
+export default function TileScript({ tile, box, videoBounds, viewing, onMouseDown, onDoubleClick }) {
// console.log(tile)
const style = {
- transform: generateTransform(tile, box),
+ transform: generateTransform(tile, box, videoBounds),
opacity: tile.settings.opacity,
}
// console.log(generateTransform(tile))
@@ -15,8 +15,8 @@ export default function TileScript({ tile, box, viewing, onMouseDown, onDoubleCl
let content = ""
className += ' ' + tile.settings.align
- style.width = unitsDimension(tile, 'width')
- style.height = unitsDimension(tile, 'height')
+ style.width = unitsDimension(tile, 'width', videoBounds)
+ style.height = unitsDimension(tile, 'height', videoBounds)
return (
<div
diff --git a/frontend/app/views/tile/handles/tile.script.js b/frontend/app/views/tile/handles/tile.script.js
index 6996cc0..444a56b 100644
--- a/frontend/app/views/tile/handles/tile.script.js
+++ b/frontend/app/views/tile/handles/tile.script.js
@@ -1,10 +1,10 @@
import React from 'react'
import { generateTransform } from 'app/views/tile/tile.utils'
-export default function TileScript({ tile, box, viewing, onMouseDown, onDoubleClick }) {
+export default function TileScript({ tile, box, videoBounds, viewing, onMouseDown, onDoubleClick }) {
// console.log(tile)
const style = {
- transform: generateTransform(tile, box),
+ transform: generateTransform(tile, box, videoBounds),
opacity: tile.settings.opacity,
}
// console.log(generateTransform(tile))
diff --git a/frontend/app/views/tile/handles/tile.text.js b/frontend/app/views/tile/handles/tile.text.js
index 5d38c85..172212a 100644
--- a/frontend/app/views/tile/handles/tile.text.js
+++ b/frontend/app/views/tile/handles/tile.text.js
@@ -1,10 +1,10 @@
import React from 'react'
import { generateTransform, unitsDimension } from 'app/views/tile/tile.utils'
-export default function TileScript({ tile, box, viewing, onMouseDown, onDoubleClick }) {
+export default function TileScript({ tile, box, videoBounds, viewing, onMouseDown, onDoubleClick }) {
// console.log(tile)
const style = {
- transform: generateTransform(tile, box),
+ transform: generateTransform(tile, box, videoBounds),
opacity: tile.settings.opacity,
}
// console.log(generateTransform(tile))
@@ -18,8 +18,8 @@ export default function TileScript({ tile, box, viewing, onMouseDown, onDoubleCl
}
let content = <span dangerouslySetInnerHTML={{ __html: tile.settings.content }} />
className += ' ' + tile.settings.align
- style.width = unitsDimension(tile, 'width')
- style.height = unitsDimension(tile, 'height')
+ style.width = unitsDimension(tile, 'width', videoBounds)
+ style.height = unitsDimension(tile, 'height', videoBounds)
style.fontFamily = tile.settings.font_family
style.fontSize = tile.settings.font_size + 'px'
style.lineHeight = 1.5
diff --git a/frontend/app/views/tile/handles/tile.video.js b/frontend/app/views/tile/handles/tile.video.js
index a9f0d09..271a671 100644
--- a/frontend/app/views/tile/handles/tile.video.js
+++ b/frontend/app/views/tile/handles/tile.video.js
@@ -10,27 +10,33 @@ export default class TileVideo extends Component {
this.handleTimeUpdate = this.handleTimeUpdate.bind(this)
this.handleEnded = this.handleEnded.bind(this)
}
+
componentDidMount() {
this.bind()
}
+
componentDidUpdate() {
this.unbind()
this.bind()
}
+
componentWillUnmount() {
this.unbind()
}
+
bind() {
if (!this.videoRef.current) return
this.el = this.videoRef.current
this.el.addEventListener('ended', this.handleEnded)
this.el.addEventListener('timeupdate', this.handleTimeUpdate)
}
+
unbind() {
if (!this.el) return
this.el.removeEventListener('timeupdate', this.handleTimeUpdate)
this.el.removeEventListener('ended', this.handleEnded)
}
+
handleTimeUpdate() {
if (this.props.tile.settings.loop && this.props.tile.settings.loop_section) {
const loop_start = timestampToSeconds(this.props.tile.settings.loop_start) || 0
@@ -40,6 +46,7 @@ export default class TileVideo extends Component {
}
}
}
+
handleEnded() {
this.props.onPlaybackEnded(this.props.tile)
if (this.props.tile.settings.loop && this.props.tile.settings.loop_section) {
@@ -47,11 +54,12 @@ export default class TileVideo extends Component {
this.videoRef.current.currentTime = loop_start
}
}
+
render() {
- let { tile, bounds, box, viewing, onMouseDown, onDoubleClick } = this.props
+ let { tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick } = this.props
// console.log(tile)
const style = {
- transform: generateTransform(tile, box),
+ transform: generateTransform(tile, box, videoBounds),
opacity: tile.settings.opacity,
}
let className = ['tile', tile.type].join(' ')
diff --git a/frontend/app/views/tile/tile.utils.js b/frontend/app/views/tile/tile.utils.js
index 8782f85..ed1cbc8 100644
--- a/frontend/app/views/tile/tile.utils.js
+++ b/frontend/app/views/tile/tile.utils.js
@@ -1,4 +1,4 @@
-export const generateTransform = (tile, box) => {
+export const generateTransform = (tile, box, videoBounds) => {
let { x, y, align, rotation, scale, units, is_tiled } = tile.settings
if (is_tiled) {
return 'translateZ(0)'
@@ -18,8 +18,11 @@ export const generateTransform = (tile, box) => {
}
// if (x % 2 == 1) x += 0.5
// if (y % 2 == 1) y += 0.5
- transform.push('translateX(' + x + units + ')')
- transform.push('translateY(' + y + units + ')')
+ const xUnits = units === 'video' ? videoUnits(x, videoBounds) : x + units
+ const yUnits = units === 'video' ? videoUnits(y, videoBounds) : y + units
+
+ transform.push('translateX(' + xUnits + ')')
+ transform.push('translateY(' + yUnits + ')')
if (scale !== 1) {
transform.push('scale(' + scale + ')')
}
@@ -60,9 +63,18 @@ export const generateVideoStyle = (tile, bounds) => {
return style
}
-export const unitsDimension = (tile, dimension) => {
+export const unitsDimension = (tile, dimension, videoBounds) => {
const value = tile.settings[dimension]
if (!value) return "auto"
- if (tile.settings.units) return value + tile.settings.units
+ if (tile.settings.units) {
+ if (tile.settings.units === 'video') {
+ return videoUnits(value, videoBounds)
+ }
+ return value + tile.settings.units
+ }
return value + "px"
}
+
+export const videoUnits = (value, videoBounds) => (
+ (value / 1000 * Math.max(videoBounds.width, videoBounds.height)) + 'px'
+) \ No newline at end of file
diff --git a/frontend/site/viewer/viewer.container.js b/frontend/site/viewer/viewer.container.js
index 6f6b850..d1fa885 100644
--- a/frontend/site/viewer/viewer.container.js
+++ b/frontend/site/viewer/viewer.container.js
@@ -15,6 +15,7 @@ class ViewerContainer extends Component {
page: {},
bounds: { width: window.innerWidth, height: window.innerHeight },
roadblock: false,
+ popups: {},
}
constructor(props) {
@@ -44,9 +45,9 @@ class ViewerContainer extends Component {
const { pages, home_page } = this.props.graph
const page = pages[page_path] || pages[home_page]
if (!this.props.interactive && hasAutoplay(page)) {
- this.setState({ page, roadblock: true })
+ this.setState({ page, popups: {}, roadblock: true })
} else {
- this.setState({ page, roadblock: false })
+ this.setState({ page, popups: {}, roadblock: false })
actions.site.interact()
this.props.audio.player.playPage(page)
}
@@ -67,6 +68,22 @@ class ViewerContainer extends Component {
window.location.href = tile.href
return
}
+ else if (tile.href === '__open_popup') {
+ this.setState({
+ popups: {
+ ...this.state.popups,
+ [tile.settings.target_popup]: true,
+ }
+ })
+ }
+ else if (tile.href === '__close_popup') {
+ this.setState({
+ popups: {
+ ...this.state.popups,
+ [tile.settings.target_popup]: false,
+ }
+ })
+ }
else if (!tile.settings.navigate_when_audio_finishes) {
history.push(tile.href)
}
@@ -86,7 +103,7 @@ class ViewerContainer extends Component {
}
render() {
- const { page, audio } = this.state
+ const { page, audio, popups } = this.state
if (this.state.roadblock) {
return this.renderRoadblock()
}
@@ -103,11 +120,16 @@ class ViewerContainer extends Component {
}
const { settings } = page
const pageStyle = { backgroundColor: settings ? settings.background_color : '#000000' }
+ const videoBounds = (page.tiles.length && page.tiles[0].type === 'video') ? {
+ width: page.tiles[0].settings.width,
+ height: page.tiles[0].settings.height,
+ } : this.state.bounds
// console.log(page)
return (
<div className='body'>
<div className='page' ref={this.pageRef} style={pageStyle}>
{page.tiles.map(tile => {
+ if (tile.settings.is_popup && !popups[tile.settings.popup_group]) return
return (
<TileHandle
viewing
@@ -115,6 +137,7 @@ class ViewerContainer extends Component {
tile={tile}
audio={audio}
bounds={this.state.bounds}
+ videoBounds={videoBounds}
onMouseDown={e => this.handleMouseDown(e, tile)}
onPlaybackEnded={e => this.handlePlaybackEnded(e, tile)}
onDoubleClick={e => {}}