diff options
| -rw-r--r-- | cli/app/site/export.py | 4 | ||||
| -rw-r--r-- | frontend/app/views/graph/graph.css | 10 | ||||
| -rw-r--r-- | frontend/app/views/page/components/page.editor.js | 18 | ||||
| -rw-r--r-- | frontend/app/views/page/page.css | 3 | ||||
| -rw-r--r-- | frontend/app/views/tile/components/tile.form.js | 32 | ||||
| -rw-r--r-- | frontend/app/views/tile/handles/tile.image.js | 4 | ||||
| -rw-r--r-- | frontend/app/views/tile/handles/tile.link.js | 8 | ||||
| -rw-r--r-- | frontend/app/views/tile/handles/tile.script.js | 4 | ||||
| -rw-r--r-- | frontend/app/views/tile/handles/tile.text.js | 8 | ||||
| -rw-r--r-- | frontend/app/views/tile/handles/tile.video.js | 12 | ||||
| -rw-r--r-- | frontend/app/views/tile/tile.utils.js | 22 | ||||
| -rw-r--r-- | frontend/site/viewer/viewer.container.js | 29 |
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 => {}} |
