summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--animism-align/frontend/app.js4
-rw-r--r--animism-align/frontend/store.js10
-rw-r--r--animism-align/frontend/types.js2
-rw-r--r--animism-align/frontend/util/index.js14
-rw-r--r--animism-align/frontend/views/align/align.container.js8
-rw-r--r--animism-align/frontend/views/align/align.css44
-rw-r--r--animism-align/frontend/views/align/align.reducer.js13
-rw-r--r--animism-align/frontend/views/align/components/ticks.component.js83
-rw-r--r--animism-align/frontend/views/align/components/timeline.component.js75
-rw-r--r--animism-align/frontend/views/align/constants.js13
-rw-r--r--animism-align/frontend/views/site/component.template.js28
-rw-r--r--animism-align/frontend/views/site/site.actions.js8
-rw-r--r--animism-align/frontend/views/site/site.reducer.js1
-rw-r--r--animism-align/frontend/views/timestamp/containers/timestamp.index.js2
-rw-r--r--animism-align/static/index.html2
15 files changed, 263 insertions, 44 deletions
diff --git a/animism-align/frontend/app.js b/animism-align/frontend/app.js
index 7c68c61..975b5b2 100644
--- a/animism-align/frontend/app.js
+++ b/animism-align/frontend/app.js
@@ -18,7 +18,7 @@ const viewList = Object.keys(views).map(name => {
export default class App extends Component {
componentDidMount() {
actions.site.loadText()
- actions.site.loadPeaks()
+ actions.site.loadPeaks()
}
render() {
return (
@@ -27,7 +27,7 @@ export default class App extends Component {
{viewList}
<Route exact key='root' path='/' render={() => {
// redirect to index!!
- setTimeout(() => this.props.history.push('/index'), 10)
+ setTimeout(() => this.props.history.push('/align'), 10)
return null
}} />
</div>
diff --git a/animism-align/frontend/store.js b/animism-align/frontend/store.js
index b4aff91..871d72c 100644
--- a/animism-align/frontend/store.js
+++ b/animism-align/frontend/store.js
@@ -2,10 +2,13 @@ import { applyMiddleware, compose, combineReducers, createStore } from 'redux'
import { connectRouter, routerMiddleware } from 'connected-react-router'
import { createBrowserHistory } from 'history'
// import createDebounce from 'redux-debounced'
-// import thunk from 'redux-thunk'
+import thunk from 'redux-thunk'
// import { login } from './util'
import uploadReducer from './views/upload/upload.reducer'
+import alignReducer from './views/align/align.reducer'
+import paragraphReducer from './views/paragraph/paragraph.reducer'
+import timestampReducer from './views/timestamp/timestamp.reducer'
import siteReducer from './views/site/site.reducer'
// import collectionReducer from './views/collection/collection.reducer'
@@ -15,6 +18,9 @@ const createRootReducer = history => (
router: connectRouter(history),
site: siteReducer,
upload: uploadReducer,
+ align: alignReducer,
+ paragraph: paragraphReducer,
+ timestamp: timestampReducer,
// collection: collectionReducer,
})
)
@@ -27,7 +33,7 @@ const configureStore = (initialState = {}, history) => {
initialState,
composeEnhancers(
applyMiddleware(
- // thunk,
+ thunk,
// createDebounce(),
routerMiddleware(history)
),
diff --git a/animism-align/frontend/types.js b/animism-align/frontend/types.js
index c14a8b1..337f711 100644
--- a/animism-align/frontend/types.js
+++ b/animism-align/frontend/types.js
@@ -5,6 +5,8 @@ export const api = crud_type('api', [])
export const upload = crud_type('upload', [])
export const peaks = crud_type('peaks', [])
export const text = crud_type('text', [])
+export const timestamp = crud_type('timestamp', [])
+export const paragraph = crud_type('paragraph', [])
export const site = with_type('site', [
])
diff --git a/animism-align/frontend/util/index.js b/animism-align/frontend/util/index.js
index 194ecf0..baa121c 100644
--- a/animism-align/frontend/util/index.js
+++ b/animism-align/frontend/util/index.js
@@ -52,7 +52,7 @@ export const courtesyS = (n, s) => n + ' ' + (n === 1 ? s : s + 's')
export const padSeconds = n => n < 10 ? '0' + n : n
-export const timestamp = (n = 0, fps = 25) => {
+export const timestamp = (n = 0, fps = 1) => {
n /= fps
let s = padSeconds(Math.round(n) % 60)
n = Math.floor(n / 60)
@@ -224,12 +224,17 @@ export const api = (dispatch, type=api_type, tag, url, data) => {
if (data) {
url.search = new URLSearchParams(data).toString()
}
- return fetch(url, {
+ let req = fetch(url, {
method: 'GET',
// mode: 'cors',
})
- .then(res => res.json())
- .then(res => dispatch({
+ // console.log(tag)
+ if (tag === 'text') {
+ req = req.then(res => res.text())
+ } else {
+ req = req.then(res => res.json())
+ }
+ req = req.then(res => dispatch({
type: type.loaded,
tag,
data: res,
@@ -239,6 +244,7 @@ export const api = (dispatch, type=api_type, tag, url, data) => {
tag,
err,
}))
+ return req
}
/* sorting */
diff --git a/animism-align/frontend/views/align/align.container.js b/animism-align/frontend/views/align/align.container.js
index af966c5..c422c3f 100644
--- a/animism-align/frontend/views/align/align.container.js
+++ b/animism-align/frontend/views/align/align.container.js
@@ -5,6 +5,7 @@ import { connect } from 'react-redux'
import './align.css'
+import Timeline from './components/timeline.component.js'
import actions from '../../actions'
import { Header } from '../../common'
// import * as uploadActions from './upload.actions'
@@ -21,8 +22,7 @@ class Container extends Component {
<div>
<Header />
<div className='body'>
- <div className='index'>
- </div>
+ <Timeline />
</div>
</div>
)
@@ -30,7 +30,3 @@ class Container extends Component {
}
export default Container
-
- // <Route exact path='/index/new' component={GraphNew} />
- // <Route exact path='/index/:id/edit' component={GraphEdit} />
- // <Route exact path='/index' component={GraphIndex} />
diff --git a/animism-align/frontend/views/align/align.css b/animism-align/frontend/views/align/align.css
index 028f6c2..bd561ad 100644
--- a/animism-align/frontend/views/align/align.css
+++ b/animism-align/frontend/views/align/align.css
@@ -1,38 +1,34 @@
* {
}
-.index {
+.body {
width: 100%;
height: 100%;
background: linear-gradient(
- -45deg,
+ 0deg,
rgba(0, 0, 64, 0.5),
- rgba(128, 0, 64, 0.5)
+ rgba(64, 64, 128, 0.5)
);
- padding: 1rem;
+ padding: 0;
}
-.index > div {
- display: inline-block;
- padding: 1rem;
- max-height: calc(100% - 2rem);
- overflow: scroll;
- background: rgba(64,12,64,0.9);
- box-shadow: 3px 3px 6px rgba(0,0,0,0.4),
- inset 0 0 60px rgba(128,255,255,0.1);
+canvas {
+ display: block;
}
-.graphIndex {
- min-width: 20rem;
- display: flex;
- flex-direction: column;
+.timeline {
+ border-top: 1px solid #333;
}
-.graphIndex > * {
- margin-bottom: 0.5rem;
+
+
+.ticks {
+ position: relative;
}
-.graphIndex > div {
- display: flex;
- flex-direction: row;
- justify-content: space-between
+.ticks .tick {
+ position: absolute;
+ top: 0;
+ height: 4px;
}
-.graphIndex > div > a:first-child {
- color: #fff;
+.ticks .tickLabel {
+ position: absolute;
+ top: 4px;
+ font-size: 0.75rem;
} \ No newline at end of file
diff --git a/animism-align/frontend/views/align/align.reducer.js b/animism-align/frontend/views/align/align.reducer.js
index d1e8889..e9e98f3 100644
--- a/animism-align/frontend/views/align/align.reducer.js
+++ b/animism-align/frontend/views/align/align.reducer.js
@@ -4,6 +4,11 @@ import { session, getDefault, getDefaultInt } from '../../session'
import { crudState, crudReducer } from '../../api/crud.reducer'
const initialState = {
+ timeline: {
+ start_ts: 0,
+ zoom: 0,
+ duration: 0,
+ },
options: {
}
}
@@ -11,6 +16,14 @@ const initialState = {
export default function alignReducer(state = initialState, action) {
// console.log(action.type, action)
switch (action.type) {
+ case types.peaks.loaded:
+ return {
+ ...state,
+ timeline: {
+ ...state.timeline,
+ duration: action.data.length / 2,
+ }
+ }
default:
return state
}
diff --git a/animism-align/frontend/views/align/components/ticks.component.js b/animism-align/frontend/views/align/components/ticks.component.js
new file mode 100644
index 0000000..3baa1f6
--- /dev/null
+++ b/animism-align/frontend/views/align/components/ticks.component.js
@@ -0,0 +1,83 @@
+import React, { Component } from 'react'
+
+import { ZOOM_STEPS, ZOOM_TICK_INTERVAL } from '../constants'
+import { timestamp } from '../../../util'
+
+export default class Ticks extends Component {
+ render() {
+ let { start_ts, zoom, duration } = this.props.timeline
+ start_ts = 65.0
+ duration /= 10
+ zoom = 2
+ const width = window.innerWidth
+
+ let secondsPerPixel = ZOOM_STEPS[zoom] / 10 // 0.1 sec / step
+ let pixelTimeDuration = 1 / secondsPerPixel // secs per pixel
+ let widthTimeDuration = width / pixelTimeDuration // secs per pixel
+ console.log(secondsPerPixel, pixelTimeDuration)
+ console.log('width in seconds', widthTimeDuration)
+
+ let secondsPerTick = ZOOM_STEPS[zoom] * 10 // secs
+ let pixelsPerTick = secondsPerTick * pixelTimeDuration
+ console.log('pixels per tick', pixelsPerTick)
+
+ let labelSpacing = pixelsPerTick
+ let subdivision = secondsPerTick
+ while (labelSpacing < 200) {
+ labelSpacing *= 2
+ subdivision *= 2
+ }
+
+ console.log('start ts', start_ts)
+ let pixelOffset = (start_ts / secondsPerPixel)
+ let pixelRemainder = pixelOffset % labelSpacing
+ // let startOffset = pixelsPerTick - (startTiming % pixelsPerTick)
+ let startOffset = labelSpacing - pixelRemainder
+ let startTiming = (pixelOffset + startOffset) * secondsPerPixel
+
+ let tickCount = Math.ceil(width / labelSpacing)
+ let offset, timing, tickLabels = [], ticks = []
+ for (var i = -1; i < tickCount; i++) {
+ offset = i * labelSpacing + startOffset
+ if (offset + 20 > width) continue
+ timing = i * subdivision + startTiming
+ if (timing > duration) {
+ break
+ }
+ tickLabels.push(
+ <div className='tickLabel' key={"tickLabel_" + i}
+ style={{
+ left: Math.floor(offset)
+ }}>
+ {timestamp(timing)}
+ </div>
+ )
+ }
+
+ // tickLabels.push(
+ // <div className='tickLabel tickLabelTotal' key={"tickLabel_total"}
+ // style={{
+ // left: width
+ // }}>
+ // {timestamp(duration, 1)}
+ // </div>
+ // )
+ // for (var i = 0; i < minuteCount; i += 1) {
+ // offset = i * labelSpacing
+ // timing = i * subdivision
+ // ticks.push(
+ // <div className='tick' key={"tick_" + i}
+ // style={{
+ // left: Math.floor(offset),
+ // }}
+ // />
+ // )
+ // }
+ return (
+ <div className='ticks'>
+ {ticks}
+ {tickLabels}
+ </div>
+ )
+ }
+}
diff --git a/animism-align/frontend/views/align/components/timeline.component.js b/animism-align/frontend/views/align/components/timeline.component.js
new file mode 100644
index 0000000..af3c57b
--- /dev/null
+++ b/animism-align/frontend/views/align/components/timeline.component.js
@@ -0,0 +1,75 @@
+import React, { Component } from 'react'
+// import { Link } from 'react-router-dom'
+// import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import actions from '../../../actions'
+// import * as uploadActions from './upload.actions'
+
+import Ticks from './ticks.component'
+
+import * as constants from '../constants'
+
+class Timeline extends Component {
+ constructor(props){
+ super(props)
+ this.canvasRef = React.createRef()
+ this.handleKeydown = this.handleKeydown.bind(this)
+ }
+ componentDidMount() {
+ this.bind()
+ this.resize()
+ this.draw()
+ }
+ componentDidUpdate() {
+ this.draw()
+ }
+ componentWillUnmount() {
+ this.unbind()
+ }
+ bind() {
+ document.addEventListener('keydown', this.handleKeydown)
+ }
+ unbind() {
+ document.removeEventListener('keydown', this.handleKeydown)
+ }
+ handleKeydown(e) {
+ // console.log(e.shiftKey, e.keyCode)
+ }
+ resize() {
+ const canvas = this.canvasRef.current
+ canvas.width = window.innerWidth
+ canvas.height = constants.DEFAULT_HEIGHT
+ }
+ draw() {
+ const canvas = this.canvasRef.current
+ const ctx = canvas.getContext('2d')
+ const w = window.innerWidth
+ this.clearCanvas(ctx, w)
+ }
+ clearCanvas(ctx, w) {
+ const h = constants.WAVEFORM_HEIGHT
+ ctx.clearRect(0, 0, w, h)
+ ctx.fillStyle = 'rgba(0,0,0,0.5)'
+ ctx.fillRect(0, 0, w, h)
+ ctx.fillStyle = 'rgba(64,128,192,0.5)'
+ }
+ render() {
+ return (
+ <div className='timeline'>
+ <canvas ref={this.canvasRef} />
+ <Ticks timeline={this.props.timeline} />
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ timeline: state.align.timeline,
+})
+
+const mapDispatchToProps = dispatch => ({
+ // uploadActions: bindActionCreators({ ...uploadActions }, dispatch),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Timeline)
diff --git a/animism-align/frontend/views/align/constants.js b/animism-align/frontend/views/align/constants.js
new file mode 100644
index 0000000..0b0630f
--- /dev/null
+++ b/animism-align/frontend/views/align/constants.js
@@ -0,0 +1,13 @@
+export const DEFAULT_HEIGHT = 300
+export const WAVEFORM_HEIGHT = DEFAULT_HEIGHT
+
+export const ZOOM_STEPS = [
+ 1,
+ 2,
+ 3,
+ 10,
+ 20,
+ 30,
+ 60,
+]
+
diff --git a/animism-align/frontend/views/site/component.template.js b/animism-align/frontend/views/site/component.template.js
new file mode 100644
index 0000000..a22d582
--- /dev/null
+++ b/animism-align/frontend/views/site/component.template.js
@@ -0,0 +1,28 @@
+import React, { Component } from 'react'
+// import { Link } from 'react-router-dom'
+// import { bindActionCreators } from 'redux'
+import { connect } from 'react-redux'
+
+import actions from '../../../actions'
+// import * as uploadActions from './upload.actions'
+
+class ComponentTemplate extends Component {
+ componentDidMount() {
+ }
+ render() {
+ const { } = this.props
+ return (
+ <div className="">
+ </div>
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+})
+
+const mapDispatchToProps = dispatch => ({
+ // uploadActions: bindActionCreators({ ...uploadActions }, dispatch),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(ComponentTemplate)
diff --git a/animism-align/frontend/views/site/site.actions.js b/animism-align/frontend/views/site/site.actions.js
index 03a6a2b..8157175 100644
--- a/animism-align/frontend/views/site/site.actions.js
+++ b/animism-align/frontend/views/site/site.actions.js
@@ -3,10 +3,10 @@ import * as types from '../../types'
// import { session } from '../../session'
import { api, post, pad, preloadImage } from '../../util'
-export const loadPeaks = () => dispatch => (
+export const loadPeaks = (asdf) => dispatch => {
api(dispatch, types.peaks, 'peaks', '/static/data_store/peaks/peaks.json')
-)
+}
-export const loadText = () => dispatch => (
+export const loadText = (asdf) => dispatch => {
api(dispatch, types.text, 'text', '/static/data_store/peaks/text.txt')
-)
+}
diff --git a/animism-align/frontend/views/site/site.reducer.js b/animism-align/frontend/views/site/site.reducer.js
index b1b4503..e80033f 100644
--- a/animism-align/frontend/views/site/site.reducer.js
+++ b/animism-align/frontend/views/site/site.reducer.js
@@ -8,6 +8,7 @@ const initialState = {
export default function siteReducer(state = initialState, action) {
// console.log(action.type, action)
+ // console.log(action.data)
switch (action.type) {
case types.peaks.loaded:
return {
diff --git a/animism-align/frontend/views/timestamp/containers/timestamp.index.js b/animism-align/frontend/views/timestamp/containers/timestamp.index.js
index 35c2d82..6d0cdd5 100644
--- a/animism-align/frontend/views/timestamp/containers/timestamp.index.js
+++ b/animism-align/frontend/views/timestamp/containers/timestamp.index.js
@@ -19,7 +19,7 @@ class GraphIndex extends Component {
<div className='graphIndex'>
<Loader />
</div>
- )
+ )
}
// console.log(state)
return (
diff --git a/animism-align/static/index.html b/animism-align/static/index.html
index 7c26d05..c544fb9 100644
--- a/animism-align/static/index.html
+++ b/animism-align/static/index.html
@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
- <title>Swimmer</title>
+ <title>Animism Alignment</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style>
html { background: #000; }