From 0296adc3ace0e36b92a56ec3a01a933b9bbd2e99 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 29 May 2018 01:48:20 +0200 Subject: write a buncha crud code --- app/api/crud.js | 98 --------------------- app/api/index.js | 20 ----- app/client/api/crud.actions.js | 35 ++++++++ app/client/api/crud.fetch.js | 100 ++++++++++++++++++++++ app/client/api/crud.type.js | 30 +++++++ app/client/api/crud.upload.js | 70 +++++++++++++++ app/client/api/index.js | 20 +++++ app/client/index.jsx | 2 + app/client/modules/samplernn/samplernn.actions.js | 9 ++ app/client/socket/socket.system.js | 2 +- app/client/types.js | 32 +++---- app/server/site.js | 2 +- 12 files changed, 282 insertions(+), 138 deletions(-) delete mode 100644 app/api/crud.js delete mode 100644 app/api/index.js create mode 100644 app/client/api/crud.actions.js create mode 100644 app/client/api/crud.fetch.js create mode 100644 app/client/api/crud.type.js create mode 100644 app/client/api/crud.upload.js create mode 100644 app/client/api/index.js (limited to 'app') diff --git a/app/api/crud.js b/app/api/crud.js deleted file mode 100644 index 1d7b305..0000000 --- a/app/api/crud.js +++ /dev/null @@ -1,98 +0,0 @@ -import fetch from 'node-fetch' - -export function crud(type_s, tag) { - const type = '/' + type_s + 's/' + (tag || '') - 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) - }, - - under: function(tag){ - return crud(type_s, tag) - }, - } -} - -function _get_url(_url, data) { - const url = new URL(window.location.origin + _url) - if (data) { - Object.keys(data).forEach(key => url.searchParams.append(key, data[key])) - } - return url -} -function _get_headers() { - return { - method: 'GET', - headers: { - 'Accept': 'application/json', - }, - } -} -function post(data) { - return { - method: 'POST', - body: JSON.stringify(data), - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - } -} -export function postBody(data) { - return { - method: 'POST', - body: data, - headers: { - 'Accept': 'application/json', - }, - } -} -function put(data) { - return { - method: 'PUT', - body: JSON.stringify(data), - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - } -} -function destroy(data) { - return { - method: 'DELETE', - body: JSON.stringify(data), - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - } -} -function error(err) { - console.warn(err) -} diff --git a/app/api/index.js b/app/api/index.js deleted file mode 100644 index 9ee943f..0000000 --- a/app/api/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import FormData from 'form-data' -import fetch from 'node-fetch' - -import { crud, postBody } from './crud' - -export const folder = crud('folder') - -folder.upload = (folder_id, files) => { - var data = new FormData() - for (var i = 0; i < files.length; i++) { - data.append('file', files[i]) - } - return fetch('/api/folders/' + folder_id, postBody(data)) - .then(req => req.json()) - .catch(error) -} - -export const file = crud('file') -export const task = crud('task') -export const job = crud('job') diff --git a/app/client/api/crud.actions.js b/app/client/api/crud.actions.js new file mode 100644 index 0000000..ca51dbb --- /dev/null +++ b/app/client/api/crud.actions.js @@ -0,0 +1,35 @@ +import crud from '../../api/crud.fetch' +import { as_type } from './crud.types' + +/* +for our crud events, create corresponding actions +the actions fire a 'loading' event, call the underlying api method, and then resolve. +so you can do ... + var folderActions = crud_actions('folder') + folderActions('upload', (dispatch) => { + new Promise((resolve, reject) => { + fetch(...) + .then(() => resolve(data)) + .catch(e => throw e) + }) + }) + folderActions.index({ module: 'samplernn' }) +*/ + +export function crud_actions(type) { + const fetch_type = crud_fetch(type) + return ['index', 'show', 'create', 'update', 'destroy'].reduce((lookup, param) => { + lookup[param] = crud_action(type, 'index', () => fetch_type[type](param)]), + return lookup + }, { action: (method, fn) => crud_action(type, method, fn) }) +} + +export const crud_action = (type, method, fn) => dispatch => { + dispatch({ type: as_type(type, method + '_loading') }) + fn(dispatch).then(data => { + dispatch({ type: as_type(type, method), data }) + }).catch(e => { + dispatch({ type: as_type(type, method + '_error') }) + }) + } +} diff --git a/app/client/api/crud.fetch.js b/app/client/api/crud.fetch.js new file mode 100644 index 0000000..fadd2b6 --- /dev/null +++ b/app/client/api/crud.fetch.js @@ -0,0 +1,100 @@ +import fetch from 'node-fetch' + +export function crud_fetch(type, tag) { + const uri = '/' + type + 's/' + (tag || '') + return { + index: q => { + return fetch(_get_url(uri, q), _get_headers()) + .then(req => req.json()) + .catch(error) + }, + + show: id => { + return fetch(uri + id) + .then(req => req.json()) + .catch(error) + }, + + create: data => { + return fetch(uri, post(data)) + .then(req => req.json()) + .catch(error) + }, + + update: data => { + return fetch(uri + data.id, put(data)) + .then(req => req.json()) + .catch(error) + }, + + destroy: data => { + return fetch(uri + data.id, destroy(data)) + .then(req => req.json()) + .catch(error) + }, + + upload: data => { + return fetch(uri, postBody(data)) + .then(req => req.json()) + .catch(error) + }, + } +} + +function _get_url(_url, data) { + const url = new URL(window.location.origin + _url) + if (data) { + Object.keys(data).forEach(key => url.searchParams.append(key, data[key])) + } + return url +} +function _get_headers() { + return { + method: 'GET', + headers: { + 'Accept': 'application/json', + }, + } +} +function post(data) { + return { + method: 'POST', + body: JSON.stringify(data), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + } +} +export function postBody(data) { + return { + method: 'POST', + body: data, + headers: { + 'Accept': 'application/json', + }, + } +} +function put(data) { + return { + method: 'PUT', + body: JSON.stringify(data), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + } +} +function destroy(data) { + return { + method: 'DELETE', + body: JSON.stringify(data), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + } +} +function error(err) { + console.warn(err) +} diff --git a/app/client/api/crud.type.js b/app/client/api/crud.type.js new file mode 100644 index 0000000..6c4a2f4 --- /dev/null +++ b/app/client/api/crud.type.js @@ -0,0 +1,30 @@ + +export const as_type = (a, b) => [a, b].join('_').toUpperCase() + +export function crud_type(type, actions=[]){ + return actions + .concat([ + 'index_loading', + 'index', + 'index_error', + 'show_loading', + 'show', + 'show_error', + 'create_loading', + 'create', + 'create_error', + 'update_loading', + 'update', + 'update_error', + 'destroy_loading', + 'destroy', + 'destroy_error', + 'upload_loading', + 'upload_progress', + 'upload_complete', + 'upload_error', + 'sort', + ]) + .reduce((a, b) => (a[b] = as_type(type, b)) && a, {}) + return aa +} diff --git a/app/client/api/crud.upload.js b/app/client/api/crud.upload.js new file mode 100644 index 0000000..42aae2b --- /dev/null +++ b/app/client/api/crud.upload.js @@ -0,0 +1,70 @@ +import { as_type } from './crud.types' + +export function upload(type, id, fd, dispatch) => { + return new Promise( (resolve, reject) => { + const xhr = new XMLHttpRequest() + xhr.upload.addEventListener("progress", uploadProgress, false) + xhr.addEventListener("load", uploadComplete, false) + xhr.addEventListener("error", uploadFailed, false) + xhr.addEventListener("abort", uploadCanceled, false) + xhr.open("POST", '/' + type + '/' + id + '/upload/') + xhr.send(fd) + + dispatch && dispatch({ type: as_type(type, 'upload_loading')}) + + function uploadProgress (e) { + if (e.lengthComputable) { + dispatch && dispatch({ + type: as_type(type, 'upload_progress'), + percent: Math.round(e.loaded * 100 / e.total), + [type]: id, + }) + } + else { + dispatch && dispatch({ + type: as_type(type, 'upload_error'), + error: 'unable to compute upload progress', + [type]: id, + }) + } + } + + function uploadComplete (e) { + try { + const data = JSON.parse(e.target.responseText) + } catch (e) { + dispatch && dispatch({ + type: as_type(type, 'upload_error'), + error: 'upload failed', + [type]: id, + }) + return + } + dispatch && dispatch({ + type: as_type(type, 'upload_complete'), + data + [type]: id, + }) + } + + uploadFailed = function (evt) { + dispatch && dispatch({ + type: as_type(type, 'upload_error'), + error: 'upload failed', + [type]: id, + }) + } + + uploadCancelled = function (evt) { + dispatch && dispatch({ + type: as_type(type, 'upload_error'), + error: 'upload cancelled' + [type]: id, + }) + } + }) +} + +export function uploadAction(type, id, fd) { + return dispatch => upload(type, id, fd, dispatch) +} \ No newline at end of file diff --git a/app/client/api/index.js b/app/client/api/index.js new file mode 100644 index 0000000..2603b38 --- /dev/null +++ b/app/client/api/index.js @@ -0,0 +1,20 @@ +import FormData from 'form-data' +import fetch from 'node-fetch' + +import { crud_fetch, postBody } from './crud.fetch' + +export const folder = crud_fetch('folder') + +folder.upload = (folder_id, files) => { + var data = new FormData() + for (var i = 0; i < files.length; i++) { + data.append('file', files[i]) + } + return fetch('/api/folders/' + folder_id, postBody(data)) + .then(req => req.json()) + .catch(error) +} + +export const file = crud_fetch('file') +export const task = crud_fetch('dataset') +export const task = crud_fetch('task') diff --git a/app/client/index.jsx b/app/client/index.jsx index c5abf91..eabf46e 100644 --- a/app/client/index.jsx +++ b/app/client/index.jsx @@ -3,6 +3,8 @@ import { Provider } from 'react-redux' import { BrowserRouter, Route } from 'react-router-dom' // import client from './client' +window.debug = false + import { store, history } from './store' import * as socket from './socket' diff --git a/app/client/modules/samplernn/samplernn.actions.js b/app/client/modules/samplernn/samplernn.actions.js index 95fef8e..1e0e3a6 100644 --- a/app/client/modules/samplernn/samplernn.actions.js +++ b/app/client/modules/samplernn/samplernn.actions.js @@ -7,3 +7,12 @@ export const uploadFiles = (files) => { export const fetchURL = (url) => { return { type: types.samplernn.fetch_url } } + +export const uploadFiles = (files) => { + return dispatch => { + // return { type: types.samplernn.upload_files } + + } +} + +// export const fetchURL = (url) => { type: types.samplernn.fetch_url } diff --git a/app/client/socket/socket.system.js b/app/client/socket/socket.system.js index 38140c3..a3c4f15 100644 --- a/app/client/socket/socket.system.js +++ b/app/client/socket/socket.system.js @@ -4,7 +4,7 @@ import types from '../types' import { socket } from './socket.connection' socket.on('system_res', (data) => { - console.log('system response', data) + // console.log('system response', data) switch (data.type) { case 'relay_connected': return dispatch({ diff --git a/app/client/types.js b/app/client/types.js index 25e5fb2..d1ac47e 100644 --- a/app/client/types.js +++ b/app/client/types.js @@ -1,3 +1,5 @@ +import { crud_type } from './crud/crud.types' + export default { system: { running_command: 'SYSTEM_RUNNING_COMMAND', @@ -12,12 +14,18 @@ export default { app: { change_tool: "APP_CHANGE_TOOL", }, - task: { - starting_task: 'TASK_STARTING_TASK', - task_begin: 'TASK_BEGIN', - stopping_task: 'TASK_STOPPING_TASK', - task_finish: 'TASK_FINISH', - }, + folder: crud_type('folder', [ + ]), + file: crud_type('file', [ + ]), + dataset: crud_type('dataset', [ + ]), + task: crud_type('task', [ + 'starting_task', + 'task_begin', + 'stopping_task', + 'task_finish', + ]), socket: { connect: 'SOCKET_CONNECT', connect_error: 'SOCKET_CONNECT_ERROR', @@ -57,9 +65,6 @@ export default { saving_video: 'SAVING_VIDEO', save_video: 'SAVE_VIDEO', }, - folder: crud('folder', ['']), - file: crud('file', []), - task: crud('task', []), samplernn: { // dataset uploading upload_files: 'UPLOAD_FILES', @@ -74,12 +79,3 @@ export default { // }, } - -const standard_actions = ['index','show','create','update','destroy','sort'] -function crud(type, actions=[]){ - return actions - .concat(standard_actions) - .reduce((lookup, action) => { - (lookup[action] = [type, action].join('_').toUpperCase()) && lookup - }, {}) -} \ No newline at end of file diff --git a/app/server/site.js b/app/server/site.js index 264f59b..913ae69 100644 --- a/app/server/site.js +++ b/app/server/site.js @@ -28,7 +28,7 @@ const api_tasks = api(app, 'task') upload.init() // app.use('/upload', require('./upload')) -app.post('/folders/:id', +app.post('/folders/:id/upload/', multer.array('file'), function (req, res, next){ if (! req.files || ! req.files.length) { -- cgit v1.2.3-70-g09d2