diff --git a/lab/lab.js b/lab/lab.js index bd3b54f70..d23b845a3 100755 --- a/lab/lab.js +++ b/lab/lab.js @@ -332,7 +332,7 @@ app.post("/api/v1/projects", (req, res, next) => { */ app.put("/api/v1/datasets", upload.array("_files", 1), (req, res, next) => { //console.log(`======app.put datasets ${req.get('Content-Type')}`) - //console.log(`======app.put datasets ${req.body._metadata}`) + //console.log(`app.put datasets ${req.body._metadata}`); // Parse request if (req.body._metadata === undefined) { @@ -398,7 +398,9 @@ app.put("/api/v1/datasets", upload.array("_files", 1), (req, res, next) => { stageDatasetFile(req.files[0]) .then((file_id) => {return registerDataset(file_id, prediction_type, dependent_col, categorical_features, ordinal_features, metadata)}) .then((dataset_id) => { - //console.log(`==added file, dataset_id: ${dataset_id}==`) + //Pass the new dataset id to event emitter + req.params = { ...req.params, dataset_id: dataset_id }; + emitEvent('datasetAdded', req); res.send({ message: "Files uploaded", dataset_id: dataset_id diff --git a/lab/socketServer.js b/lab/socketServer.js index ff0f7227f..66d3581ac 100644 --- a/lab/socketServer.js +++ b/lab/socketServer.js @@ -55,19 +55,18 @@ function emitEvent(event, req) { return rp(FGLAB_URL + "/api/datasets") .then(datasets => { datasets.forEach(dataset => - //sockets.forEach(socket => socket.emit('updateDataset', dataset)) sockets.forEach(socket => socket.emit('updateAIToggle', dataset._id, dataset.ai)) ) }) .catch((err) => {console.log(`Error: ${err}`)}); // Ignore failures case 'aiToggled': - console.log(`=socketServer:aiToggled(${req.params.id})`) + //console.log(`=socketServer:aiToggled(${req.params.id})`) return sockets.forEach(socket => socket.emit('updateAIToggle', JSON.stringify({ _id: req.params.id, nextAIState: req.body.ai })) ); case 'recommenderStatusUpdated': - console.log(`=socketServer:recommenderStatusUpdated(${req.body.status})`) + //console.log(`=socketServer:recommenderStatusUpdated(${req.body.status})`) return sockets.forEach(socket => socket.emit('updateRecommender', JSON.stringify({recommenderStatus: req.body.status })) ); @@ -84,6 +83,7 @@ function emitEvent(event, req) { }) .catch((err) => {console.log(`Error: ${err}`)}); // Ignore failures case 'expUpdated': + //console.log("==== socketServer - case expUpdated"); return rp(FGLAB_URL + "/api/userexperiments/" + req.params.id) .then(experiment => { sockets.forEach(socket => socket.emit('updateExperiment', experiment)); @@ -95,11 +95,17 @@ function emitEvent(event, req) { .catch((err) => {console.log(`Error: ${err}`)}); // Ignore failures }) .catch((err) => {console.log(`Error: ${err}`)}); // Ignore failures + case 'datasetAdded': + //console.log(`* emitEvent - datasetAdded ${req.params.dataset_id}`); + return rp(FGLAB_URL + "/api/userdatasets/" + req.params.dataset_id) + .then(dataset => { + sockets.forEach(socket => socket.emit('addDataset', dataset)); + }) + .catch((err) => {console.log(`socketServer.emitEvent addDataset Error: ${err}`)}); // Ignore failures } } module.exports = { socketServer: socketServer, emitEvent: emitEvent -}; - +}; \ No newline at end of file diff --git a/lab/webapp/src/config/configSocket.js b/lab/webapp/src/config/configSocket.js index 4ca9a74f4..eda389dbc 100644 --- a/lab/webapp/src/config/configSocket.js +++ b/lab/webapp/src/config/configSocket.js @@ -26,9 +26,10 @@ along with this program. If not, see . */ import io from 'socket.io-client'; -import { updateAI, updateDataset } from 'data/datasets/dataset/actions'; +import { updateAI, updateDataset, addDataset } from 'data/datasets/dataset/actions'; import { addExperiment, updateExperiment } from 'data/experiments/actions'; import { fetchRecommender} from 'data/recommender/actions'; +import { fetchDatasets } from 'data/datasets/actions'; let socket = io(`${location.protocol}//${location.hostname}:${location.port}`); /** @@ -43,7 +44,12 @@ const configSocket = (store) => { socket.on('updateDataset', data => { const dataset = JSON.parse(data)[0]; - store.dispatch(updateDataset(dataset)); + store.dispatch(updateDataset(dataset)); + }); + + socket.on('addDataset', data => { + const dataset = JSON.parse(data)[0]; + store.dispatch(addDataset(dataset)); }); socket.on('updateExperiment', data => { diff --git a/lab/webapp/src/data/datasets/api.js b/lab/webapp/src/data/datasets/api.js index 756b3a5d4..3a02311a0 100644 --- a/lab/webapp/src/data/datasets/api.js +++ b/lab/webapp/src/data/datasets/api.js @@ -29,7 +29,7 @@ require('es6-promise').polyfill(); import fetch from 'isomorphic-fetch'; export const fetchDatasets = () => - fetch('/api/userdatasets') + fetch('/api/userdatasets') //See lab\webapp\src\data\datasets\dataset\api.js .then(response => { if(response.status >= 400) { throw new Error(`${response.status}: ${response.statusText}`); diff --git a/lab/webapp/src/data/datasets/dataset/actions.js b/lab/webapp/src/data/datasets/dataset/actions.js index 76cc3c01e..0c0e9ab57 100644 --- a/lab/webapp/src/data/datasets/dataset/actions.js +++ b/lab/webapp/src/data/datasets/dataset/actions.js @@ -31,6 +31,7 @@ export const TOGGLE_AI_SUCCESS = 'TOGGLE_AI_SUCCESS'; export const TOGGLE_AI_FAILURE = 'TOGGLE_AI_FAILURE'; export const AI_UPDATE = 'AI_UPDATE'; export const DATASET_UPDATE = 'DATASET_UPDATE'; +export const DATASET_ADD = 'DATASET_ADD'; export const UPLOAD_DATASET_REQUEST = 'UPLOAD_DATASET_REQUEST'; export const UPLOAD_DATASET_SUCCESS = 'UPLOAD_DATASET_SUCCESS'; export const UPLOAD_DATASET_FAILURE = 'UPLOAD_DATASET_FAILURE'; @@ -100,3 +101,8 @@ export const updateDataset = (dataset) => ({ type: DATASET_UPDATE, dataset }); + +export const addDataset = (dataset) => ({ + type: DATASET_ADD, + dataset +}) diff --git a/lab/webapp/src/data/datasets/dataset/actions.test.js b/lab/webapp/src/data/datasets/dataset/actions.test.js index 386d2413b..699658e8e 100644 --- a/lab/webapp/src/data/datasets/dataset/actions.test.js +++ b/lab/webapp/src/data/datasets/dataset/actions.test.js @@ -61,6 +61,23 @@ describe('testing how some UI action affects redux action stuff', () => { expect(actionStuff.updateDataset(testDataset)) .toEqual(expectedAction); }) + + it('addDataset', () => { + const testDataset = { + id: 'da_data', + info: { + experiment: 'pass', + result: [3,4,5] + } + }; + const expectedAction = { + type: actionStuff.DATASET_ADD, + dataset: testDataset + }; + expect(actionStuff.addDataset(testDataset)) + .toEqual(expectedAction); + }) + }) import * as apiTestHelper from './__mocks__/api'; diff --git a/lab/webapp/src/data/datasets/dataset/index.js b/lab/webapp/src/data/datasets/dataset/index.js index 46895ca06..cbdef7731 100644 --- a/lab/webapp/src/data/datasets/dataset/index.js +++ b/lab/webapp/src/data/datasets/dataset/index.js @@ -31,11 +31,17 @@ import { TOGGLE_AI_FAILURE, AI_UPDATE, DATASET_UPDATE, + DATASET_ADD, UPLOAD_DATASET_REQUEST, UPLOAD_DATASET_SUCCESS, UPLOAD_DATASET_FAILURE } from './actions'; +/*** + NOTE - this isn't a reducer itself. It's called by the reducer datasets.byId, and + this is why it has the params 'state' and 'action'. + So don't be confused like I was! HTH + ***/ const dataset = (state = {}, action) => { switch(action.type) { case TOGGLE_AI_REQUEST: @@ -57,6 +63,7 @@ const dataset = (state = {}, action) => { ai: action.nextAIState }); case DATASET_UPDATE: + case DATASET_ADD: return action.dataset; case UPLOAD_DATASET_REQUEST: //window.console.log('UPLOAD_DATASET_REQUEST action', action); diff --git a/lab/webapp/src/data/datasets/index.js b/lab/webapp/src/data/datasets/index.js index 0f88025c3..14765a7ec 100644 --- a/lab/webapp/src/data/datasets/index.js +++ b/lab/webapp/src/data/datasets/index.js @@ -39,6 +39,7 @@ import { TOGGLE_AI_FAILURE, AI_UPDATE, DATASET_UPDATE, + DATASET_ADD, UPLOAD_DATASET_REQUEST, UPLOAD_DATASET_SUCCESS, UPLOAD_DATASET_FAILURE @@ -52,6 +53,7 @@ const byId = (state = {}, action) => { return map; }, {}); case DATASET_UPDATE: + case DATASET_ADD: return Object.assign({}, state, { [action.dataset._id]: dataset(state[action.dataset._id], action) }); @@ -90,6 +92,9 @@ const allIds = (state = [], action) => { switch(action.type) { case FETCH_DATASETS_SUCCESS: return action.payload.map(d => d._id); + case DATASET_ADD: + //Adding a new dataset + return [...state, action.dataset._id]; default: return state; } @@ -128,14 +133,15 @@ const getAllIds = (state) => state.datasets.allIds; const getById = (state) => state.datasets.byId; export const getSortedDatasets = createSelector( [getAllIds, getById], - (allIds, byId) => - allIds + (allIds, byId) => { + return allIds .map(id => byId[id]) .sort((a, b) => { const A = a.name.toLowerCase(); const B = b.name.toLowerCase(); return A > B ? 1 : A < B ? -1 : 0; - }) + }); + } ); export default datasets; diff --git a/lab/webapp/src/data/experiments/index.js b/lab/webapp/src/data/experiments/index.js index 47a487048..551fa601c 100644 --- a/lab/webapp/src/data/experiments/index.js +++ b/lab/webapp/src/data/experiments/index.js @@ -85,6 +85,8 @@ const experiments = combineReducers({ export default experiments; +// Selectors // + const getExperiments = (state) => state.experiments; const getQuery = (state, props) => props.location.query; export const getFilters = createSelector(