From 2263f412817d6d2d36372e7617feb0d97fa57af8 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 4 Jul 2017 02:11:44 +0200 Subject: break out browser and tasks --- client/client.js | 100 +- client/components/App.jsx | 42 +- client/components/Browser/Browser.jsx | 57 ++ .../components/Browser/Folder/FileUploadButton.jsx | 35 + client/components/Browser/Folder/Folder.jsx | 77 ++ client/components/Browser/Folders/FolderForm.jsx | 47 + client/components/Browser/Folders/Folders.jsx | 56 + client/components/Folder/FileUploadButton.jsx | 44 - client/components/Folder/Folder.jsx | 80 -- client/components/Folders/FolderForm.jsx | 50 - client/components/Folders/Folders.jsx | 58 -- client/components/Header.jsx | 18 - client/components/Modal.jsx | 17 - client/components/Tasks/TaskForm.jsx | 50 + client/components/Tasks/TaskFormView.jsx | 72 ++ client/components/Tasks/Tasks.jsx | 38 + client/components/UI/Header.jsx | 18 + client/components/UI/Modal.jsx | 20 + lib/server/index.js | 2 +- lib/worker/processFiles.js | 13 +- public/assets/css/css.css | 37 +- public/bundle.js | 1079 ++++++++++++-------- public/bundle.js.map | 2 +- python/nsatf.py | 4 +- 24 files changed, 1244 insertions(+), 772 deletions(-) create mode 100644 client/components/Browser/Browser.jsx create mode 100644 client/components/Browser/Folder/FileUploadButton.jsx create mode 100644 client/components/Browser/Folder/Folder.jsx create mode 100644 client/components/Browser/Folders/FolderForm.jsx create mode 100644 client/components/Browser/Folders/Folders.jsx delete mode 100644 client/components/Folder/FileUploadButton.jsx delete mode 100644 client/components/Folder/Folder.jsx delete mode 100644 client/components/Folders/FolderForm.jsx delete mode 100644 client/components/Folders/Folders.jsx delete mode 100644 client/components/Header.jsx delete mode 100644 client/components/Modal.jsx create mode 100644 client/components/Tasks/TaskForm.jsx create mode 100644 client/components/Tasks/TaskFormView.jsx create mode 100644 client/components/Tasks/Tasks.jsx create mode 100644 client/components/UI/Header.jsx create mode 100644 client/components/UI/Modal.jsx diff --git a/client/client.js b/client/client.js index 9ee689c..d727a66 100644 --- a/client/client.js +++ b/client/client.js @@ -1,6 +1,56 @@ +export default { + folder: crud('folder'), + file: crud('file'), + task: crud('task'), + job: crud('job'), + upload: (folder_id, files) => { + var data = new FormData() + for (var i = 0; i < files.length; i++) { + data.append('file', files[i]) + } + return fetch('/folders/' + folder_id, postBody(data)) + .then(req => req.json()) + .catch(error) + }, +} + +function crud(type_s) { + const type = '/' + type_s + 's/' + return { + index: (data) => { + return fetch(_get_url(type, data), _get_headers()) + .then(req => req.json()) + .catch(error) + }, + + show: (id) => { + return fetch(type + id) + .then(req => req.json()) + .catch(error) + }, + + create: (data) => { + return fetch(type, post(data)) + .then(req => req.json()) + .catch(error) + }, + + update: (data) => { + return fetch(type + data.id, put(data)) + .then(req => req.json()) + .catch(error) + }, + + destroy: (data) => { + return fetch(type + data.id, destroy(data)) + .then(req => req.json()) + .catch(error) + }, + } +} + function _get_url(_url, data) { const url = new URL(window.location.origin + _url) - console.log(_url, data, window.location.origin) if (data) { Object.keys(data).forEach(key => url.searchParams.append(key, data[key])) } @@ -56,51 +106,3 @@ function destroy(data) { function error(err) { console.warn(err) } -function crud(type_s) { - const type = '/' + type_s + 's/' - return { - index: (data) => { - return fetch(_get_url(type, data), _get_headers()) - .then(req => req.json()) - .catch(error) - }, - - show: (id) => { - return fetch(type + id) - .then(req => req.json()) - .catch(error) - }, - - create: (data) => { - return fetch(type, post(data)) - .then(req => req.json()) - .catch(error) - }, - - update: (data) => { - return fetch(type + data.id, put(data)) - .then(req => req.json()) - .catch(error) - }, - - destroy: (data) => { - return fetch(type + data.id, destroy(data)) - .then(req => req.json()) - .catch(error) - }, - } -} - -export default { - folder: crud('folder'), - file: crud('file'), - upload: (folder_id, files) => { - var data = new FormData() - for (var i = 0; i < files.length; i++) { - data.append('file', files[i]) - } - return fetch('/folders/' + folder_id, postBody(data)) - .then(req => req.json()) - .catch(error) - }, -} \ No newline at end of file diff --git a/client/components/App.jsx b/client/components/App.jsx index 85766e5..5340ba1 100644 --- a/client/components/App.jsx +++ b/client/components/App.jsx @@ -3,54 +3,26 @@ import { isMobile } from '../vendor/util' // import db from '../db' import { Link, withRouter } from 'react-router-dom' -import Header from './Header.jsx' -import Folders from './Folders/Folders.jsx' -import Folder from './Folder/Folder.jsx' +import Header from './UI/Header.jsx' +import Browser from './Browser/Browser.jsx' +import Tasks from './Tasks/Tasks.jsx' import client from '../client' class App extends Component { constructor(props) { super() - let openFolders = JSON.parse( localStorage['openFolders'] || 'null' ) this.state = { - folders: [], - openFolders: openFolders || [], } - client.folder.index().then( folders => this.setState({ folders }) ) - } - openFolder(folder) { - if (this.state.openFolders.indexOf(folder.id) === -1) { - const newOpenFolders = this.state.openFolders.concat(folder.id) - localStorage['openFolders'] = JSON.stringify(newOpenFolders) - this.setState({ openFolders: newOpenFolders }) - } - } - closeFolder(folder) { - const openFolders = this.state.openFolders.filter( folder_id => folder_id !== folder.id ) - localStorage['openFolders'] = JSON.stringify(openFolders) - this.setState({ openFolders }) - } - addFolder(folder) { - this.setState({ folders: this.state.folders.concat([folder]) }) } render() { - const openFolders = this.state.openFolders.map((folder_id) => { - const folder_list = this.state.folders.filter(folder => folder.id === folder_id) - if (! folder_list.length) return - const folder = folder_list[0] - return ( - this.closeFolder(folder)} - /> - ) - }) return (
- this.openFolder(folder)} addFolder={(folder) => this.addFolder(folder)} /> - {openFolders} +
+ + +
) } diff --git a/client/components/Browser/Browser.jsx b/client/components/Browser/Browser.jsx new file mode 100644 index 0000000..10b86c3 --- /dev/null +++ b/client/components/Browser/Browser.jsx @@ -0,0 +1,57 @@ +import { h, Component } from 'preact' + +import Folders from './Folders/Folders.jsx' +import Folder from './Folder/Folder.jsx' + +import client from '../../client' + +class Browser extends Component { + constructor(props) { + super() + let openFolders = JSON.parse( localStorage['openFolders'] || 'null' ) + this.state = { + folders: [], + openFolders: openFolders || [], + } + client.folder.index().then( folders => this.setState({ folders }) ) + } + openFolder(folder) { + if (this.state.openFolders.indexOf(folder.id) === -1) { + const newOpenFolders = this.state.openFolders.concat(folder.id) + localStorage['openFolders'] = JSON.stringify(newOpenFolders) + this.setState({ openFolders: newOpenFolders }) + } + } + closeFolder(folder) { + const openFolders = this.state.openFolders.filter( folder_id => folder_id !== folder.id ) + localStorage['openFolders'] = JSON.stringify(openFolders) + this.setState({ openFolders }) + } + addFolder(folder) { + this.setState({ folders: this.state.folders.concat([folder]) }) + } + render() { + const openFolders = this.state.openFolders.map((folder_id) => { + const folder_list = this.state.folders.filter(folder => folder.id === folder_id) + if (! folder_list.length) return + const folder = folder_list[0] + return ( + this.closeFolder(folder)} + /> + ) + }) + return ( +
+ this.openFolder(folder)} + addFolder={(folder) => this.addFolder(folder)} + /> + {openFolders} +
+ ) + } +} + +export default Browser diff --git a/client/components/Browser/Folder/FileUploadButton.jsx b/client/components/Browser/Folder/FileUploadButton.jsx new file mode 100644 index 0000000..136cd45 --- /dev/null +++ b/client/components/Browser/Folder/FileUploadButton.jsx @@ -0,0 +1,35 @@ +import { h, Component } from 'preact' + +import client from '../../../client.js' + +export default class Folder extends Component { + constructor(props) { + super() + this.state = { + } + this.updateFiles = this.updateFiles.bind(this) + } + updateFiles(event){ + const name = event.target.name + const files = event.target.files + client.upload(this.props.folder.id, files).then( got_files => { + this.props.addFiles(got_files) + }) + } + + render() { + const files = (this.props.folder.files || []).map( (file, i) => { + return ( +
+ {file.name} +
+ ) + }) + return ( +
+ + + upload +
+ ) + } +} diff --git a/client/components/Browser/Folder/Folder.jsx b/client/components/Browser/Folder/Folder.jsx new file mode 100644 index 0000000..3ed3ddb --- /dev/null +++ b/client/components/Browser/Folder/Folder.jsx @@ -0,0 +1,77 @@ +import { h, Component } from 'preact' + +import client from '../../../client.js' + +import FileUploadButton from './FileUploadButton.jsx' + +export default class Folder extends Component { + constructor(props) { + super() + this.state = { + files: props.folder.files || [], + } + this.addFiles = this.addFiles.bind(this) + if (! props.folder.files) { + client.file.index({ folder_id: props.folder.id }).then( files => this.setState({ files }) ) + } + this.audio = document.createElement('audio') + } + addFiles(newFiles) { + if (! newFiles) return + const files = this.state.files.concat(newFiles).sort( (a,b) => { return b.id - a.id } ) + this.setState({ files }) + } + handleClick(file) { + if (file.type === 'audio') { + this.audio.setAttribute('src', mp3path(file)) + this.audio.play() + document.body.style.backgroundImage = 'url(' + pngpath(file) + ')' + } + } + render() { + const files = (this.state.files).map(toFilenamePair).sort(sortByFilename).map(fromPair).map( (file, i) => { + if (! file) return + return ( +
+ this.handleClick(file)}>{file.name} + {file.mime} + + this.props.setContent(file)}>content > + this.props.setStyle(file)}>style > + +
+ ) + }) + return ( +
+
+ {this.props.folder.name} +
+ + +
+
+
+ {files} +
+
+ ) + } +} + +function toFilenamePair (file) { return [file.name.toLowerCase(), file] } +function sortByFilename (a,b) { return a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1 } +function fromPair (pair) { return pair[1] } + +function filepath (file) { + return '/data/' + file.folder_id + '/' + encodeURIComponent(file.name) +} +function mp3path (file) { + if (file.mime !== 'audio/mp3') { + return filepath(file) + '.mp3' + } + return filepath(file) +} +function pngpath (file) { + return filepath(file) + '.png' +} \ No newline at end of file diff --git a/client/components/Browser/Folders/FolderForm.jsx b/client/components/Browser/Folders/FolderForm.jsx new file mode 100644 index 0000000..ad3e321 --- /dev/null +++ b/client/components/Browser/Folders/FolderForm.jsx @@ -0,0 +1,47 @@ +import { h, Component } from 'preact' + +import client from '../../../client.js' + +export default class FolderForm extends Component { + constructor(props) { + super() + this.state = { + name: '', + } + this.updateState = this.updateState.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + } + updateState(event){ + const name = event.target.name + let value = event.target.value + console.log(name, value) + this.setState({ + [name]: value, + error: null, + }) + } + handleSubmit(event) { + event.preventDefault() + let rec = Object.assign({}, this.state) + delete rec.error + this.props.onClose() + client.folder.create( rec ).then( (data) => { + this.props.addFolder( data ) + }) + } + render() { + return ( +
+

new folder

+
+ + +
+
+ + +
+
+ ) + } +} diff --git a/client/components/Browser/Folders/Folders.jsx b/client/components/Browser/Folders/Folders.jsx new file mode 100644 index 0000000..2c85e80 --- /dev/null +++ b/client/components/Browser/Folders/Folders.jsx @@ -0,0 +1,56 @@ +import { h, Component } from 'preact' + +import Modal from '../../UI/Modal.jsx' +import FolderForm from './FolderForm.jsx' + +import client from '../../../client.js' + +export default class Folders extends Component { + constructor(props) { + super() + this.state = { + adding: false, + } + } + openModal() { + this.setState({ adding: true }) + } + closeModal() { + this.setState({ adding: false }) + } + toggle(folder) { + folder.open = ! folder.open + if (folder.open && ! folder.files) { + client.file.index({ 'folder_id': folder.id }).then( files => { + console.log(files) + folder.files = files + this.props.openFolder(folder) + }) + } + } + render() { + const folders = (this.props.folders || []).map( (folder,i) => { + return ( +
this.toggle(folder)}> + {folder.name} +
+ ) + }) + return ( +
+
+ browser +
+ +
+
+
+ {folders} +
+ this.closeModal()}> + this.closeModal()} /> + +
+ ) + } +} diff --git a/client/components/Folder/FileUploadButton.jsx b/client/components/Folder/FileUploadButton.jsx deleted file mode 100644 index 24f4c4f..0000000 --- a/client/components/Folder/FileUploadButton.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { h, Component } from 'preact' -import { Link } from 'react-router-dom' - -import Modal from '../Modal.jsx' - -import client from '../../client.js' - -import FileUploadButton from './FileUploadButton.jsx' - -export default class Folder extends Component { - constructor(props) { - super() - this.state = { - } - this.updateFiles = this.updateFiles.bind(this) - } - updateFiles(event){ - const name = event.target.name - const files = event.target.files - console.log(name, files) - - client.upload(this.props.folder.id, files).then( got_files => { - console.log(got_files) - this.props.addFiles(got_files) - }) - } - - render() { - console.log(this.props) - const files = (this.props.folder.files || []).map( (file, i) => { - return ( -
- {file.name} -
- ) - }) - return ( -
- - + upload -
- ) - } -} diff --git a/client/components/Folder/Folder.jsx b/client/components/Folder/Folder.jsx deleted file mode 100644 index 4a2e4d2..0000000 --- a/client/components/Folder/Folder.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import { h, Component } from 'preact' -import { Link } from 'react-router-dom' - -import Modal from '../Modal.jsx' - -import client from '../../client.js' - -import FileUploadButton from './FileUploadButton.jsx' - -export default class Folder extends Component { - constructor(props) { - super() - this.state = { - files: props.folder.files || [], - } - this.addFiles = this.addFiles.bind(this) - if (! props.folder.files) { - client.file.index({ folder_id: props.folder.id }).then( files => this.setState({ files }) ) - } - this.audio = document.createElement('audio') - } - addFiles(newFiles) { - console.log(newFiles) - if (! newFiles) return - const files = this.state.files.concat(newFiles).sort( (a,b) => { return b.id - a.id } ) - this.setState({ files }) - } - handleClick(file) { - console.log(file) - if (file.type === 'audio') { - this.audio.setAttribute('src', mp3path(file)) - this.audio.play() - console.log(pngpath(file)) - document.body.style.backgroundImage = 'url(' + pngpath(file) + ')' - } - } - render() { - console.log(this.props) - const files = (this.state.files).map(toFilenamePair).sort(sortByFilename).map(fromPair).map( (file, i) => { - if (! file) return - return ( -
- this.handleClick(file)}>{file.name} - {file.mime} -
- ) - }) - return ( -
-
- {this.props.folder.name} -
- - -
-
-
- {files} -
-
- ) - } -} - -function toFilenamePair (file) { return [file.name.toLowerCase(), file] } -function sortByFilename (a,b) { return a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1 } -function fromPair (pair) { return pair[1] } - -function filepath (file) { - return '/data/' + file.folder_id + '/' + encodeURIComponent(file.name) -} -function mp3path (file) { - if (file.mime !== 'audio/mp3') { - return filepath(file) + '.mp3' - } - return filepath(file) -} -function pngpath (file) { - return filepath(file) + '.png' -} \ No newline at end of file diff --git a/client/components/Folders/FolderForm.jsx b/client/components/Folders/FolderForm.jsx deleted file mode 100644 index 1ed263e..0000000 --- a/client/components/Folders/FolderForm.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import { h, Component } from 'preact' -import { Link } from 'react-router-dom' - -import client from '../../client.js' - -export default class FolderForm extends Component { - constructor(props) { - super() - this.state = { - name: '', - } - this.updateState = this.updateState.bind(this) - this.handleSubmit = this.handleSubmit.bind(this) - } - updateState(event){ - const name = event.target.name - let value = event.target.value - console.log(name, value) - this.setState({ - [name]: value, - error: null, - }) - } - handleSubmit(event) { - event.preventDefault() - let rec = Object.assign({}, this.state) - delete rec.error - this.props.onClose() - client.folder.create( rec ).then( (data) => { - this.props.addFolder( data ) - }) - } - render() { - return ( -
-

Create a new folder

-
- - - -