summaryrefslogtreecommitdiff
path: root/app/client
diff options
context:
space:
mode:
authorJules <jules@asdf.us>2018-09-22 10:47:50 -0400
committerJules <jules@asdf.us>2018-09-22 10:47:50 -0400
commit7e39114e27520e382f26368ae8f4d08ae7f3071b (patch)
tree01e7f210b0c3a119622e92d56d01f5c7951ad631 /app/client
parent46889933fd9c36c527014410823e88a7d838d239 (diff)
parent8d1c19852fcce52e369978dfc195d5da4f12180a (diff)
merge
Diffstat (limited to 'app/client')
-rw-r--r--app/client/auth/auth.gate.js20
-rw-r--r--app/client/auth/auth.reducer.js1
-rw-r--r--app/client/common/browser.component.js18
-rw-r--r--app/client/common/fileList.component.js9
-rw-r--r--app/client/common/fileViewer.component.js111
-rw-r--r--app/client/dashboard/dashboard.component.js2
-rw-r--r--app/client/index.jsx7
-rw-r--r--app/client/modules/pix2pixhd/pix2pixhd.actions.js6
-rw-r--r--app/client/modules/pix2pixhd/views/pix2pixhd.train.js24
-rw-r--r--app/client/modules/pix2pixhd/views/sequence.editor.js177
-rw-r--r--app/client/system/system.reducer.js9
-rw-r--r--app/client/util/format.js28
12 files changed, 289 insertions, 123 deletions
diff --git a/app/client/auth/auth.gate.js b/app/client/auth/auth.gate.js
index 076ec54..40f244f 100644
--- a/app/client/auth/auth.gate.js
+++ b/app/client/auth/auth.gate.js
@@ -46,34 +46,36 @@ class AuthRouter extends Component {
class AuthGate extends Component {
render(){
- if (true && !this.props.auth.initialized) {
+ const { auth, env, actions } = this.props
+ if (env.production && !auth.initialized) {
console.log('loading auth')
return <div className='loading'>Loading</div>
}
- if (true || this.props.auth.isAuthenticated) {
- console.log('authenticated...')
- if (this.props.auth.returnTo) {
- let { returnTo } = this.props.auth
+ if (env.development || auth.isAuthenticated) {
+ if (auth.returnTo) {
+ let { returnTo } = auth
if (!returnTo || returnTo.match(/(login|logout|signup)/i)) {
returnTo = '/'
}
console.log('history.push', returnTo)
- this.props.actions.setReturnTo(null)
+ actions.setReturnTo(null)
history.push(returnTo)
return <div>Launching app</div>
}
- console.log('rendering as normal')
return <div>{this.props.children}</div>
}
return <AuthRouter {...this.props} />
}
componentDidMount(){
- this.props.actions.checkin()
+ if (this.props.env.production) {
+ this.props.actions.checkin()
+ }
}
}
const mapStateToProps = (state) => ({
- auth: state.auth
+ env: state.system.env,
+ auth: state.auth,
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/client/auth/auth.reducer.js b/app/client/auth/auth.reducer.js
index a56f94a..80b1ec5 100644
--- a/app/client/auth/auth.reducer.js
+++ b/app/client/auth/auth.reducer.js
@@ -11,7 +11,6 @@ const authInitialState = {
}
const auth = (state = authInitialState, action) => {
- console.log(action)
switch(action.type) {
case types.auth.set_token:
return {
diff --git a/app/client/common/browser.component.js b/app/client/common/browser.component.js
index 50b31cf..19cd0f6 100644
--- a/app/client/common/browser.component.js
+++ b/app/client/common/browser.component.js
@@ -11,19 +11,23 @@ class Browser extends Component {
state = {
dir: '/',
files: [],
+ file: null,
loading: true
}
+
componentDidMount() {
this.fetch(this.state.dir)
}
+
handlePick(file) {
console.log(file)
if (file.dir) {
this.fetch([this.state.dir, file.name].join('/').replace('//','/'))
} else {
- this.fetchFile([this.state.dir, file.name].join('/').replace('//','/'))
+ this.setState({ file: { ...file, path: this.state.dir } })
}
}
+
fetch(dir) {
console.log('fetch', dir)
const { tool: module } = this.props.app
@@ -33,15 +37,7 @@ class Browser extends Component {
this.setState({ dir, files, loading: false })
})
}
- fetchFile(fn) {
- console.log('fetch file', fn)
- const { tool: module } = this.props.app
- this.setState({ file: null, loadingFile: true })
- actions.socket.read_file({ module, fn }).then(file => {
- console.log(file)
- this.setState({ file, loadingFile: false })
- })
- }
+
render() {
const { app } = this.props
const {
@@ -68,7 +64,7 @@ class Browser extends Component {
}}
onClickParent={e => {
console.log('navigate up')
- this.fetch(this.state.dir.split('/').slice(0, -1).join('/') || '/')
+ this.fetch(dir.split('/').slice(0, -1).join('/') || '/')
}}
/>
{loadingFile && <Loading />}
diff --git a/app/client/common/fileList.component.js b/app/client/common/fileList.component.js
index f932274..8f79148 100644
--- a/app/client/common/fileList.component.js
+++ b/app/client/common/fileList.component.js
@@ -122,7 +122,14 @@ export const FileRow = props => {
<div className={"date " + util.carbon_date(date)}>{moment(date).format("YYYY-MM-DD")}</div>
}
{fields.has('datetime') &&
- <div className={"datetime " + util.carbon_date(date)}>{moment(date).format("YYYY-MM-DD h:mm a")}</div>
+ <div className={"datetime"}>
+ <span class={'date ' + util.carbon_date(date)}>
+ {moment(date).format("YYYY-MM-DD")}
+ </span>
+ <span class={'time ' + util.carbon_time(date)}>
+ {moment(date).format("H:mm")}
+ </span>
+ </div>
}
{fields.has('size') &&
<div className={"size " + size[0]}>{size[1]}</div>
diff --git a/app/client/common/fileViewer.component.js b/app/client/common/fileViewer.component.js
index bc71f20..b1cabd4 100644
--- a/app/client/common/fileViewer.component.js
+++ b/app/client/common/fileViewer.component.js
@@ -1,4 +1,7 @@
import { h, Component } from 'preact'
+import { connect } from 'react-redux'
+
+import actions from '../actions'
const image_types = {
'jpg': 'image/jpeg',
@@ -18,33 +21,85 @@ const video_types = {
'mp4': 'video/mp4',
}
-export default function FileViewer({ file }) {
- const {
- error,
- name, path,
- date, size,
- buf,
- } = file
- if (error) {
- return <div className='fileViewer'>{error}</div>
+class FileViewer extends Component {
+ state = {
+ loading: false,
+ stale: false,
+ buffer: {}
+ }
+
+ fetch() {
+ const { file, path } = this.props
+ if (!file) return
+ if (this.state.loading) {
+ this.setState({ stale: true })
+ return
+ }
+ const fn = [path || file.path, file.name].join('/').replace('//','/')
+ console.log('fetch file', fn)
+ const { tool: module } = this.props.app
+ this.setState({ buffer: null, loading: true })
+ actions.socket.read_file({ module, fn }).then(buffer => {
+ console.log('fetched buffer')
+ const { stale } = this.state
+ this.setState({ buffer, loading: false, stale: false, }, () => {
+ if (stale) {
+ console.log('stale, fetching...')
+ this.fetch()
+ }
+ })
+ })
+ }
+
+ componentDidMount(){
+ this.fetch()
}
- if (!buf) {
- return <div className='fileViewer'>File empty</div>
+
+ componentDidUpdate(nextProps){
+ if (this.props.file !== nextProps.file) {
+ this.fetch()
+ }
}
- const ext = name.split('.').slice(-1)[0].toLowerCase()
- let tag;
- if (ext in image_types) {
- tag = <img src={getURLFor(buf, image_types[ext])} />
- } else if (ext in audio_types) {
- tag = <audio src={getURLFor(buf, audio_types[ext])} controls autoplay />
- } else if (ext in video_types) {
- tag = <video src={getURLFor(buf, audio_types[ext])} controls autoplay />
- } else {
- tag = <div className='text'>{ab2str(buf)}</div>
+
+ render() {
+ const { file } = this.props
+ if (!file) {
+ return <div className='fileViewer'></div>
+ }
+ const { loading, buffer } = this.state
+ if (loading) {
+ return <div className='fileViewer'>Loading...</div>
+ }
+ const {
+ error,
+ name, path,
+ date, size,
+ buf,
+ } = buffer
+ if (error) {
+ return <div className='fileViewer'>{error}</div>
+ }
+ if (!name) {
+ return <div className='fileViewer'></div>
+ }
+ if (!buf) {
+ return <div className='fileViewer'>File empty</div>
+ }
+ const ext = extension(name)
+ let tag;
+ if (ext in image_types) {
+ tag = <img src={getURLFor(buf, image_types[ext])} />
+ } else if (ext in audio_types) {
+ tag = <audio src={getURLFor(buf, audio_types[ext])} controls autoplay />
+ } else if (ext in video_types) {
+ tag = <video src={getURLFor(buf, video_types[ext])} controls autoplay />
+ } else {
+ tag = <div className='text'>{ab2str(buf)}</div>
+ }
+ return (
+ <div className='fileViewer'>{tag}</div>
+ )
}
- return (
- <div className='fileViewer'>{tag}</div>
- )
}
const getURLFor = (buf, type) => {
@@ -55,3 +110,11 @@ const getURLFor = (buf, type) => {
}
const ab2str = buf => String.fromCharCode.apply(null, new Uint8Array(buf))
+
+const extension = fn => fn.split('.').slice(-1)[0].toLowerCase()
+
+const mapStateToProps = state => ({
+ app: state.system.app,
+})
+
+export default connect(mapStateToProps)(FileViewer)
diff --git a/app/client/dashboard/dashboard.component.js b/app/client/dashboard/dashboard.component.js
index cbfdd33..8f47049 100644
--- a/app/client/dashboard/dashboard.component.js
+++ b/app/client/dashboard/dashboard.component.js
@@ -48,7 +48,7 @@ class Dashboard extends Component {
linkFiles
files={renders[key]}
orderBy='date desc'
- fields={'name date epoch size'}
+ fields={'name datetime epoch size'}
onClick={key === 'samplernn' ? (file, e) => {
e.preventDefault()
e.stopPropagation()
diff --git a/app/client/index.jsx b/app/client/index.jsx
index cda528c..4e0c38d 100644
--- a/app/client/index.jsx
+++ b/app/client/index.jsx
@@ -30,13 +30,10 @@ const app = (
<Auth.Gate>
<BrowserRouter>
<div className='everybody'>
- <Route path='/' children={(props) => <div>{console.log(props.location.pathname)}</div>} />
<Route exact path='/system' component={System} />
<Route exact path='/dashboard' component={Dashboard} />
<Route exact path='/browse' component={Browser} />
<Route exact path='/logout' component={Auth.Logout} />
- <Route exact path='/login' component={() => { <Redirect to='/' /> }} />
- <Route exact path='/signup' component={() => { <Redirect to='/' /> }} />
{module_list}
<Route exact path='/' component={Dashboard} />
<Route path='/' component={Header} />
@@ -46,5 +43,9 @@ const app = (
</Auth.Gate>
</Provider>
)
+/*
+ <Route exact path='/login' component={() => { <Redirect to='/' /> }} />
+ <Route exact path='/signup' component={() => { <Redirect to='/' /> }} />
+*/
render(app, document.getElementById('container'))
diff --git a/app/client/modules/pix2pixhd/pix2pixhd.actions.js b/app/client/modules/pix2pixhd/pix2pixhd.actions.js
index a17eeab..2c72f06 100644
--- a/app/client/modules/pix2pixhd/pix2pixhd.actions.js
+++ b/app/client/modules/pix2pixhd/pix2pixhd.actions.js
@@ -205,7 +205,7 @@ export const list_epochs = (checkpoint_name) => (dispatch) => {
export const count_dataset = (checkpoint_name) => (dispatch) => {
const module = pix2pixhdModule.name
util.allProgress([
- actions.socket.count_directory({ module, dir: 'sequences/' + checkpoint_name + '/' }),
+ actions.socket.list_directory({ module, dir: 'sequences/' + checkpoint_name + '/' }),
actions.socket.count_directory({ module, dir: 'datasets/' + checkpoint_name + '/train_A/' }),
], (percent, i, n) => {
console.log('pix2pixhd load progress', i, n)
@@ -215,12 +215,14 @@ export const count_dataset = (checkpoint_name) => (dispatch) => {
data: { module: 'pix2pixhd' },
})
}).then(res => {
- const [sequenceCount, datasetCount] = res //, datasets, results, output, datasetUsage, lossReport] = res
+ const [sequence, datasetCount] = res //, datasets, results, output, datasetUsage, lossReport] = res
+ const sequenceCount = sequence.length
console.log(sequenceCount, datasetCount)
dispatch({
type: types.pix2pixhd.load_dataset_count,
data: {
name: checkpoint_name,
+ sequence,
sequenceCount,
datasetCount,
}
diff --git a/app/client/modules/pix2pixhd/views/pix2pixhd.train.js b/app/client/modules/pix2pixhd/views/pix2pixhd.train.js
index 957b068..6aade36 100644
--- a/app/client/modules/pix2pixhd/views/pix2pixhd.train.js
+++ b/app/client/modules/pix2pixhd/views/pix2pixhd.train.js
@@ -19,6 +19,7 @@ import NewDatasetForm from '../../../dataset/dataset.new'
import UploadStatus from '../../../dataset/upload.status'
import DatasetComponent from '../../../dataset/dataset.component'
+import SequenceEditor from './sequence.editor'
import pix2pixhdModule from '../pix2pixhd.module'
@@ -34,9 +35,10 @@ class Pix2PixHDTrain extends Component {
augment_make: 20,
}
}
- componentWillMount(){
+ componentDidMount(){
const id = this.props.match.params.id || localStorage.getItem('pix2pixhd.last_id')
- console.log('load dataset:', id)
+ const dataset = localStorage.getItem('pix2pixhd.last_dataset')
+ console.log('load dataset:', id, dataset)
const { match, pix2pixhd, actions } = this.props
if (id === 'new') return
if (id) {
@@ -47,9 +49,13 @@ class Pix2PixHDTrain extends Component {
} else {
this.props.history.push('/pix2pixhd/new/')
}
+ if (dataset) {
+ this.setState({ checkpoint_name: dataset })
+ }
}
componentDidUpdate(prevProps, prevState){
if (prevState.checkpoint_name !== this.state.checkpoint_name) {
+ localStorage.setItem('pix2pixhd.last_dataset', this.state.checkpoint_name)
this.setState({ epoch: 'latest' })
this.props.actions.list_epochs(this.state.checkpoint_name)
this.props.actions.count_dataset(this.state.checkpoint_name)
@@ -114,6 +120,18 @@ class Pix2PixHDTrain extends Component {
value={this.state.epoch}
/>
</Group>
+ </div>
+ </div>
+ <div>
+ <Group title='Sequence Editor'>
+ <SequenceEditor
+ module={pix2pixhdModule}
+ checkpoint={this.props.pix2pixhd.checkpoint}
+ />
+ </Group>
+ </div>
+ <div className='columns'>
+ <div className='column'>
<Group title='Augmentation Grid'>
<AugmentationGrid
checkpoint={this.props.pix2pixhd.checkpoint}
@@ -132,7 +150,7 @@ class Pix2PixHDTrain extends Component {
this.props.remote.augment_task(this.state.checkpoint_name, {
...this.state,
augment_take: 10,
- augment_make: 150,
+ augment_make: 149,
no_symlinks: true,
mov: true,
folder_id: this.props.pix2pixhd.data.resultsFolder.id
diff --git a/app/client/modules/pix2pixhd/views/sequence.editor.js b/app/client/modules/pix2pixhd/views/sequence.editor.js
index 9693805..6a5da39 100644
--- a/app/client/modules/pix2pixhd/views/sequence.editor.js
+++ b/app/client/modules/pix2pixhd/views/sequence.editor.js
@@ -3,78 +3,137 @@ import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Route, Link } from 'react-router-dom'
-import { Loading, FileList, FileViewer } from '../../common'
+import { Loading, FileList, FileViewer } from '../../../common'
-import actions from '../actions'
+import actions from '../../../actions'
+
+const initialState = {
+ dir: '/',
+ frameA: null,
+ frameB: null,
+ selection: null,
+ loading: true
+}
+
+/*
+ when the sequence editor loads,
+ reset the selection
+ reset the two frames
+ set the two frames to the beginning and end of the video
+ when mousing over the video
+ ideally you would see a tiny thumbnail preview of the frame :)
+ - click to start a selection, drag over, mouseup to end the selection
+ this should update the start/end frame
+ ...
+ so there are two things you could do with this
+ 1) create an entirely new dataset
+ 2) add frames to an existing dataset
+ ...
+ method 1)
+ - requires minimal setup, just a server script which..
+ - creates the new sequence folder
+ - symlinks the frames
+ - runs build_dataset
+ - create appropriate file object, using parent dataset's folder_id
+ - enqueue initial training
+ ---> we can then train on basic subsets, with more control, like we do already...
+ - tell parent dataset thing the new sequence name
+ ...
+ method 2)
+ - requires sequence editor to be aware of its own dataset
+ - requires sequence editor to know whether a sequence is original or not
+*/
class SequenceEditor extends Component {
- state = {
- dir: '/',
- files: [],
- loading: true
+ state = { ...initialState }
+
+ constructor() {
+ super()
+ this.handleMouseDown = this.handleMouseDown.bind(this)
+ this.handleMouseMove = this.handleMouseMove.bind(this)
+ this.handleMouseEnter = this.handleMouseEnter.bind(this)
+ this.handleMouseLeave = this.handleMouseLeave.bind(this)
+ this.handleMouseUp = this.handleMouseUp.bind(this)
}
+
componentDidMount() {
- this.fetch(this.state.dir)
+ const { checkpoint } = this.props
+ window.addEventListener('mousemove', this.handleMouseMove)
+ window.addEventListener('mouseup', this.handleMouseUp)
+ if (checkpoint && checkpoint.sequence) {
+ console.log(checkpoint)
+ const frameA = checkpoint.sequence[0]
+ const frameB = checkpoint.sequence[checkpoint.sequence.length-1]
+ this.setState({
+ ...initialState,
+ frameA,
+ frameB,
+ })
+ }
}
- handlePick(file) {
- console.log(file)
- if (file.dir) {
- this.fetch([this.state.dir, file.name].join('/').replace('//','/'))
- } else {
- this.fetchFile([this.state.dir, file.name].join('/').replace('//','/'))
+
+ componentDidUpdate(prevProps) {
+ const { checkpoint } = this.props
+ if (checkpoint !== prevProps.checkpoint) {
+ console.log(checkpoint)
+ const frameA = checkpoint.sequence[0]
+ const frameB = checkpoint.sequence[checkpoint.sequence.length-1]
+ this.setState({
+ ...initialState,
+ frameA,
+ frameB,
+ })
}
}
- fetch(dir) {
- console.log('fetch', dir)
- const { tool: module } = this.props.app
- this.setState({ dir, file: null, loading: true })
- actions.socket.list_directory({ module, dir }).then(files => {
- console.log(files)
- this.setState({ dir, files, loading: false })
- })
+
+ componentWillUnmount(){
+ window.removeEventListener('mouseup', this.handleMouseUp)
+ window.removeEventListener('mousemove', this.handleMouseMove)
+ }
+
+ handleMouseDown(e) {
+ this.setState({ dragging: true })
+ }
+ handleMouseMove(e) {
+ }
+ handleMouseEnter(e) {
+ }
+ handleMouseLeave(e) {
}
- fetchFile(fn) {
- console.log('fetch file', fn)
- const { tool: module } = this.props.app
- this.setState({ file: null, loadingFile: true })
- actions.socket.read_file({ module, fn }).then(file => {
- console.log(file)
- this.setState({ file, loadingFile: false })
- })
+ handleMouseUp(e) {
+ this.setState({ dragging: false })
}
+
+ handlePick(file) {
+ console.log(file)
+ // this.setState({ dir, file: null, loading: true })
+ }
+
render() {
- const { app } = this.props
+ const { app, checkpoint } = this.props
const {
- loading, dir, files,
- loadingFile, file,
+ loading,
+ selection,
+ frameA, frameB,
} = this.state
- console.log(this.props, this.state)
- // return (
- // <div className='app browser'>
- // <h1>{dir}{dir[dir.length-1] !== '/' && '/'}</h1>
- // {app.tool}<br/>
- // {loading && <Loading />}
- // <FileList
- // files={files}
- // groupDirectories
- // parentDirectory={dir !== '/'}
- // orderBy='name asc'
- // fields={'name datetime size'}
- // onClick={(file, e) => {
- // e.preventDefault()
- // e.stopPropagation()
- // console.log('picked a result', file)
- // this.handlePick(file)
- // }}
- // onClickParent={e => {
- // console.log('navigate up')
- // this.fetch(this.state.dir.split('/').slice(0, -1).join('/') || '/')
- // }}
- // />
- // {loadingFile && <Loading />}
- // {file && <FileViewer file={file} />}
- // </div>
- // )
+ // console.log(this.props, this.state)
+ const width = 200
+ const path = "sequences/" + checkpoint.name
+ return (
+ <div className='sequenceEditor'>
+ <div
+ className='timeline'
+ style={{ width }}
+ mouseDown={this.handleSelectionStart}
+ mouseEnter={this.handleMouseEnter}
+ mouseLeave={this.handleMouseLeave}
+ >
+ {selection && <div className='selection' style={selection}></div>}
+ </div>
+ <FileViewer path={path} file={this.state.frameA} />
+ <FileViewer path={path} file={this.state.frameB} />
+ </div>
+ )
}
}
diff --git a/app/client/system/system.reducer.js b/app/client/system/system.reducer.js
index 387b454..5f9e4ac 100644
--- a/app/client/system/system.reducer.js
+++ b/app/client/system/system.reducer.js
@@ -9,8 +9,13 @@ const systemInitialState = {
site: {
name: 'loading',
},
+ env: {
+ env: process.env.NODE_ENV,
+ production: process.env.NODE_ENV === 'production',
+ development: process.env.NODE_ENV !== 'production',
+ },
app: {
- tool: localStorage.getItem('system.last_tool') || 'pix2pix',
+ tool: localStorage.getItem('system.last_tool') || 'pix2pixhd',
},
server: {
connected: false,
@@ -43,7 +48,7 @@ const systemInitialState = {
stderr: "",
}
-const modules = ['pix2pix','samplernn','pix2wav'].reduce((a,b) => (a[b]=b,a),{})
+const modules = ['pix2pix','pix2pixhd','pix2wav','samplernn','morph'].reduce((a,b) => (a[b]=b,a),{})
const systemReducer = (state = systemInitialState, action) => {
// console.log(action.type)
diff --git a/app/client/util/format.js b/app/client/util/format.js
index e436a3e..ee1f47f 100644
--- a/app/client/util/format.js
+++ b/app/client/util/format.js
@@ -38,6 +38,22 @@ export function carbon_date (date, no_bold) {
{ color = "quiet" }
return color
}
+export function carbon_time (date, no_bold) {
+ var span = (+new Date() - new Date(date)) / 1000, color
+ if (! no_bold && span < 3600) // modified this hour
+ { color = "new" }
+ else if (span < 3 * 3600) // modifed last 3 hours
+ { color = "recent" }
+ else if (span < 12 * 3600) // modifed last 12 hours
+ { color = "med" }
+ else if (span < 24 * 3600) // modifed last day
+ { color = "old" }
+ else if (span < 48 * 3600) // modifed last two days
+ { color = "older" }
+ else
+ { color = "quiet" }
+ return color
+}
export function hush_views (n, bias, no_bold) {
var txt = commatize(n, 1000)
bias = bias || 1
@@ -71,21 +87,19 @@ export function hush_size (n, bias, no_bold) {
if (n < 1000000) {
return ["quiet", txt + " kb."]
}
- else if (n < (20000000/bias)) {
+ if (n < (20000000/bias)) {
return ["quiet", txt + " mb."]
}
- else if (n < (50000000/bias)) {
+ if (n < (50000000/bias)) {
return ["old", txt + " mb."]
}
- else if (n < (80000000/bias)) {
+ if (n < (80000000/bias)) {
return ["med", txt + " mb."]
}
- else if (no_bold || n < (170000000/bias)) {
+ if (no_bold || n < (170000000/bias)) {
return ["recent", txt + " mb."]
}
- else {
- return ["new", txt + " mb."]
- }
+ return ["new", txt + " mb."]
}
export function hush_null (n, unit, no_bold) {
var s = unit ? n + " " + unit + "." : n