fix(nucleus): wait for curr selections (#117)

This commit is contained in:
Miralem Drek
2019-09-26 17:33:15 +02:00
committed by GitHub
parent aad5603e05
commit f9e286d332
9 changed files with 95 additions and 81 deletions

View File

@@ -1,19 +1,6 @@
import vizualizationAPI from '../viz';
import ObjectAPI from './object-api';
export function observe(model, objectAPI) {
const onChanged = () =>
model.getLayout().then(layout => {
objectAPI.setLayout(layout);
});
model.on('changed', onChanged);
model.once('closed', () => {
model.removeListener('changed', onChanged);
objectAPI.close();
});
onChanged();
}
import { observe } from './observer';
export default function initiate(getCfg, optional, context) {
return context.app.getObject(getCfg.id).then(model => {
@@ -24,7 +11,7 @@ export default function initiate(getCfg, optional, context) {
const objectAPI = new ObjectAPI(model, context, viz);
observe(model, objectAPI);
observe(model, layout => objectAPI.setLayout(layout)); // TODO - call unobserve when viz is destroyed
const api = objectAPI.getPublicAPI();

View File

@@ -46,14 +46,22 @@ export function observe(model, callback, property = 'layout') {
affected.forEach(key => {
c.props[key].state = STATES.VALIDATING;
const method = OBSERVABLE[key].filter(m => model[m])[0];
model[method]().then(value => {
model[method]()
.then(value => {
if (cache[model.id] && cache[model.id].props[key]) {
if (cache[model.id].props[key].state < STATES.CLOSED && cache[model.id].props[key].state !== STATES.VALID) {
if (
cache[model.id].props[key].state < STATES.CLOSED &&
cache[model.id].props[key].state !== STATES.VALID
) {
cache[model.id].props[key].state = STATES.VALID;
cache[model.id].props[key].value = value;
cache[model.id].props[key].callbacks.forEach(cb => cb(value));
}
}
})
.catch(() => {
// TODO - retry?
cache[model.id].props[key].state = STATES.INVALID;
});
});
};

View File

@@ -15,11 +15,13 @@ const create = app => {
let modalObject;
// let mounted;
let lyt;
let currentSelectionsModel;
let prom;
const api = {
model: app,
switchModal(object, path, accept = true) {
if (object === modalObject) {
return Promise.resolve();
return prom || Promise.resolve();
}
if (modalObject) {
modalObject.endSelections(accept);
@@ -30,17 +32,22 @@ const create = app => {
// TODO check model state
modalObject = object;
api.emit('modal', modalObject._selections);
return modalObject.beginSelections(Array.isArray(path) ? path : [path]).catch(err => {
prom = currentSelectionsModel.then(() => {
// do not return the call to beginSelection to avoid waiting for it's response
modalObject.beginSelections(Array.isArray(path) ? path : [path]).catch(err => {
if (err.code === 6003) {
// If another object already is in modal -> abort and take over
return api.abortModal().then(() => object.beginSelections(Array.isArray(path) ? path : [path]));
}
throw err;
});
});
return prom;
}
modalObject = null;
api.emit('modal-unset');
return Promise.resolve();
prom = Promise.resolve();
return prom;
},
isModal(objectModel) {
// TODO check model state
@@ -83,7 +90,7 @@ const create = app => {
eventmixin(api);
modelCache(
currentSelectionsModel = modelCache(
{
qInfo: {
qType: 'current-selections',
@@ -94,7 +101,8 @@ const create = app => {
alternateStates: [],
},
app
).then(model => {
)
.then(model => {
observe(app, appLayout => {
const states = [...appLayout.qStateNames].map(s => ({
stateName: s, // need this as reference in selection toolbar since qSelectionObject.qStateName is not in the layout
@@ -134,6 +142,9 @@ const create = app => {
app._selections = null; // eslint-disable-line no-param-reassign
cache[app.id] = null;
});
})
.catch(() => {
// do something
});
return api;

View File

@@ -55,16 +55,18 @@ export default function(model, app) {
return appAPI().switchModal(null, null, false, false);
},
select(s) {
this.begin([s.params[0]]);
const b = this.begin([s.params[0]]);
if (!appAPI().isModal()) {
return;
}
hasSelected = true;
b.then(() =>
model[s.method](...s.params).then(qSuccess => {
if (!qSuccess) {
this.clear();
}
});
})
);
},
canClear() {
return hasSelected && layout.qSelectionInfo.qMadeSelections;

View File

@@ -18,7 +18,7 @@
"build": "nebula build",
"lint": "eslint src",
"start": "nebula serve",
"test:integration": "aw puppet --testExt '*.int.js' --glob 'test/integration/**/*.int.js' --chrome.headless true --mocha.timeout 15000"
"test:integration": "aw puppet --testExt '*.int.js' --glob 'test/integration/**/*.int.js'"
},
"devDependencies": {
"@after-work.js/aw": "^6.0.3",

View File

@@ -2,7 +2,8 @@ const serve = require('@nebula.js/cli-serve'); // eslint-disable-line
let s;
before(async () => {
before(async function setup() {
this.timeout(15000);
s = await serve({
open: false,
});

View File

@@ -9,8 +9,12 @@ describe('interaction', () => {
await page.click('rect[data-label="K"]');
await page.click('rect[data-label="S"]');
await page.waitForSelector('button[title="Confirm selection"]');
await page.click('button[title="Confirm selection"]');
await page.waitFor(100); // wait a bit to make sure websocket traffic has gone through
const rects = await page.$$eval('rect[data-label]', sel => sel.map(r => r.getAttribute('data-label')));
expect(rects).to.eql(['K', 'S']);
});

View File

@@ -18,7 +18,7 @@
"build": "nebula build",
"lint": "eslint src",
"start": "nebula serve",
"test:integration": "aw puppet --testExt '*.int.js' --glob 'test/integration/**/*.int.js' --chrome.headless true --chrome.slowMo 10"
"test:integration": "aw puppet --testExt '*.int.js' --glob 'test/integration/**/*.int.js'"
},
"devDependencies": {
"@after-work.js/aw": "^6.0.3",

View File

@@ -2,7 +2,8 @@ const serve = require('@nebula.js/cli-serve'); // eslint-disable-line
let s;
before(async () => {
before(async function setup() {
this.timeout(15000); // to allow time for the server to start
s = await serve({
build: false,
});