feat: add selection api (#3)

This commit is contained in:
Miralem Drek
2019-02-06 13:49:53 +01:00
committed by GitHub
parent 49df28f528
commit d847a7897c
19 changed files with 76 additions and 117 deletions

View File

@@ -1,9 +1,9 @@
version: "2"
version: "3.1"
services:
engine:
image: qlikcore/engine:12.300.0
image: qlikcore/engine:${ENGINE_VERSION:-latest}
restart: always
command: -S AcceptEULA=${ACCEPT_EULA}
command: -S AcceptEULA="${ACCEPT_EULA:-no}"
ports:
- "19076:9076"

View File

@@ -3,7 +3,7 @@
"description": "",
"scripts": {
"build": "cross-env NODE_ENV=production FORCE_COLOR=1 lerna run build --stream",
"build:watch": "FORCE_COLOR=1 lerna run build:watch --stream",
"build:watch": "FORCE_COLOR=1 lerna run build:watch --stream --concurrency 99 --no-sort",
"lint": "eslint packages --ext .js --ext .jsx",
"test": "yarn run test:unit",
"test:integration": "aw puppet -c aw.config.js --type integration",

View File

@@ -14,7 +14,6 @@
"lint": "eslint --ext .js,.jsx src"
},
"devDependencies": {
"@nebula.js/selections": "^0.1.0",
"@nebula.js/supernova": "^0.1.0",
"node-event-emitter": "^0.0.1",
"preact": "^8.4.2"

View File

@@ -1,5 +1,4 @@
import preact from 'preact';
import { createAppSelectionAPI } from '@nebula.js/selections';
import Cell from './components/Cell';
import populateData from './populator';
@@ -11,16 +10,6 @@ import './components/Style.scss';
export function boot({
id,
}, visual, config, nebbie, app) {
if (!app.selections) {
let selections = null;
Object.defineProperty(app, 'selections', {
get() {
selections = selections || createAppSelectionAPI(app);
return selections;
},
});
}
return new config.env.Promise((resolve) => {
let reference;
const unmount = () => {

View File

@@ -1,4 +1,5 @@
import preact from 'preact';
import { createObjectSelectionAPI } from '../selections';
import { prefixer } from '../utils';
@@ -107,6 +108,7 @@ class Cell extends preact.Component {
const sn = SN.create({
model,
app: props.app,
selections: createObjectSelectionAPI(model, props.app),
});
sn.component.on('rendered', (...args) => {
externalAPI.emit('rendered', ...args);
@@ -127,15 +129,16 @@ class Cell extends preact.Component {
};
const onChanged = () => model.getLayout().then((layout) => {
if (model.selections) {
model.selections.setLayout(layout);
const selections = this.state.sn ? this.state.sn.component.selections : null;
if (selections && selections.id === model.id) {
selections.setLayout(layout);
if (layout.qSelectionInfo && layout.qSelectionInfo.qInSelections
&& !model.selections.isModal()) {
model.selections.goModal('/qHyperCubeDef');
&& !selections.isModal()) {
selections.goModal('/qHyperCubeDef');
}
if (!layout.qSelectionInfo || !layout.qSelectionInfo.qInSelections) {
if (model.selections.isModal()) {
model.selections.noModal();
if (selections.isModal()) {
selections.noModal();
}
}
}

View File

@@ -60,7 +60,7 @@ class Item extends preact.Component {
class Component extends preact.Component {
constructor(props) {
super(props);
const api = props.model.selections;
const api = props.sn.component.selections;
this.state = {
confirmable: api.canConfirm(),
@@ -113,7 +113,7 @@ class Component extends preact.Component {
}
static getDerivedStateFromProps(nextProps) {
const api = nextProps.model.selections;
const api = nextProps.sn.component.selections;
return {
confirmable: api.canConfirm(),
cancelable: api.canCancel(),

View File

@@ -1,7 +1,12 @@
import { createAppSelectionAPI } from './selections';
import { create, boot } from './booter';
import types from './sn/types';
function apiGenerator(app) {
createAppSelectionAPI(app);
const config = {
env: {
Promise,
@@ -24,6 +29,7 @@ function apiGenerator(app) {
config.load = $;
return api;
},
selections: () => app._selections, // eslint-disable-line no-underscore-dangle
types: context.types,
};

View File

@@ -1,6 +1,9 @@
/* eslint no-underscore-dangle: 0 */
import eventmixin from './event-mixin';
export default function (app) {
const cache = {};
const create = (app) => {
let canGoForward = false;
let canGoBack = false;
let canClear = false;
@@ -14,11 +17,11 @@ export default function (app) {
if (modalObject) {
modalObject.endSelections(accept);
api.emit('modal-unset');
modalObject.selections.emit('deactivated');
modalObject._selections.emit('deactivated');
}
if (object && object !== null) { // TODO check model state
modalObject = object;
api.emit('modal', modalObject.selections);
api.emit('modal', modalObject._selections);
return modalObject.beginSelections(Array.isArray(path) ? path : [path]);
}
modalObject = null;
@@ -33,7 +36,7 @@ export default function (app) {
if (!modalObject) {
return Promise.resolve();
}
// modalObject.selections.
// modalObject._selections.
modalObject = null;
api.emit('modal-unset');
return app.abortModal(accept);
@@ -89,9 +92,25 @@ export default function (app) {
model.on('changed', onChanged);
model.once('closed', () => {
model.removeListener('changed', onChanged);
app._selections = null; // eslint-disable-line no-param-reassign
cache[app.id] = null;
});
onChanged();
});
return api;
};
export default function (app) {
if (!cache[app.id]) {
cache[app.id] = {
selections: null,
};
Object.defineProperty(app, '_selections', {
get() {
cache[app.id].selections = cache[app.id].selections || create(app);
return cache[app.id].selections;
},
});
}
}

View File

@@ -0,0 +1,4 @@
import createAppSelectionAPI from './app-selections';
import createObjectSelectionAPI from './object-selections';
export { createObjectSelectionAPI, createAppSelectionAPI };

View File

@@ -1,3 +1,4 @@
/* eslint no-underscore-dangle: 0 */
import eventmixin from './event-mixin';
const event = () => {
@@ -11,11 +12,15 @@ const event = () => {
};
export default function (model, app) {
const appAPI = app.selections;
if (model._selections) {
return model._selections;
}
const appAPI = () => app._selections;
let hasSelected = false;
let isActive = false;
let layout = {};
const api = {
// model,
id: model.id,
setLayout(lyt) {
layout = lyt;
@@ -28,7 +33,7 @@ export default function (model, app) {
}
isActive = true;
this.emit('activated');
return appAPI.switchModal(model, paths, true);
return appAPI().switchModal(model, paths, true);
},
clear() {
hasSelected = false;
@@ -40,18 +45,18 @@ export default function (model, app) {
isActive = false;
this.emit('confirmed');
this.emit('deactivated');
return appAPI.switchModal(null, null, true);
return appAPI().switchModal(null, null, true);
},
cancel() {
hasSelected = false;
isActive = false;
this.emit('canceled');
this.emit('deactivated');
return appAPI.switchModal(null, null, false, false);
return appAPI().switchModal(null, null, false, false);
},
select(s) {
this.begin([s.params[0]]);
if (!appAPI.isModal()) {
if (!appAPI().isModal()) {
return;
}
hasSelected = true;
@@ -71,12 +76,14 @@ export default function (model, app) {
return true;
},
isActive: () => isActive,
isModal: () => appAPI.isModal(model),
goModal: paths => appAPI.switchModal(model, paths, false),
noModal: () => appAPI.switchModal(null, null, false),
isModal: () => appAPI().isModal(model),
goModal: paths => appAPI().switchModal(model, paths, false),
noModal: () => appAPI().switchModal(null, null, false),
};
eventmixin(api);
model._selections = api; // eslint-disable-line no-param-reassign
return api;
}

View File

@@ -12,7 +12,12 @@ const load = ({ name, version }, config) => {
if (typeof p === 'string') {
throw new Error('Return value must be a Promise');
}
LOADED[key] = p.catch((e) => {
LOADED[key] = p.then((sn) => {
if (!sn) {
throw new Error('undefined supernova');
}
return sn;
}).catch((e) => {
console.error(e);
throw new Error(`Failed to load supernova: ${name}`);
});

View File

@@ -1,21 +0,0 @@
{
"name": "@nebula.js/selections",
"version": "0.1.0",
"private": true,
"description": "",
"license": "MIT",
"author": "QlikTech International AB",
"keywords": [],
"main": "dist/selections.js",
"module": "dist/selections.esm.js",
"files": [
"dist"
],
"scripts": {
"build": "cross-env NODE_ENV=production rollup --config ../../rollup.config.js --exports named",
"lint": "eslint src"
},
"devDependencies": {
"node-event-emitter": "0.0.1"
}
}

View File

@@ -1,44 +0,0 @@
/* eslint no-param-reassign: 0 */
import createAppSelectionAPI from './app-selections';
import createObjectSelectionAPI from './object-selections';
// MIXINS
// const objectSelectionAPI = {
// types: ['GenericObject'],
// init(args) {
// let selections = null;
// Object.defineProperty(args.api, 'selections', {
// get() {
// selections = selections || createObjectSelectionAPI(args.api);
// return selections;
// },
// });
// },
// };
// const appSelectionAPI = {
// types: ['Doc'],
// init(args) {
// let selections = null;
// Object.defineProperty(args.api, 'selections', {
// get() {
// selections = selections || createAppSelectionAPI(args.api);
// return selections;
// },
// });
// },
// };
// const all = {
// types: ['Doc', 'GenericObject'],
// init({ api }) {
// if (api.getAppLayout) {
// api.session.app = api;
// }
// api.app = api.session.app;
// },
// };
// export default [all, objectSelectionAPI, appSelectionAPI];
export { createObjectSelectionAPI, createAppSelectionAPI };

View File

@@ -11,10 +11,9 @@
"scripts": {
"build": "cross-env NODE_ENV=production rollup --config ../../rollup.config.js",
"build:dev": "rollup --config ../../rollup.config.js",
"lint": "eslint src"
"build:watch": "rollup --config ../../rollup.config.js -w"
},
"devDependencies": {
"@nebula.js/selections": "^0.1.0",
"extend": "^3.0.2",
"node-event-emitter": "^0.0.1"
}

View File

@@ -39,14 +39,14 @@ export default function ({
const actions = {};
const selectionToolbarItems = [];
const w = actionWrapper(component);
((sn.selectionToolbar || {}).items || []).forEach((item) => {
((sn.definition.selectionToolbar || {}).items || []).forEach((item) => {
const wrapped = w(item);
// TODO - check if key exists
actions[item.key] = wrapped;
selectionToolbarItems.push(wrapped);
});
(sn.actions || []).forEach((item) => {
(sn.definition.actions || []).forEach((item) => {
const wrapped = w(item);
// TODO - check if key exists
actions[item.key] = wrapped;

View File

@@ -1,13 +1,13 @@
import extend from 'extend';
import EventEmitter from 'node-event-emitter';
import translator from './translator';
import actionhero from './action-hero';
const defaultComponent = {
app: null,
model: null,
actions: null,
selections: null,
created: () => {},
mounted: () => {},
render: () => {},
@@ -33,7 +33,7 @@ const mixin = (obj) => {
return obj;
};
export default function create(sn, opts, env) {
export default function create(sn, opts) {
const componentInstance = {
...defaultComponent,
};
@@ -64,16 +64,13 @@ export default function create(sn, opts, env) {
app: opts.app,
selections: opts.selections,
actions: hero.actions,
resources: {
translator: env.translator || translator,
Promise: env.Promise || Promise,
},
});
extend(componentInstance, {
actions: hero.actions,
model: opts.model,
app: opts.app,
selections: opts.selections,
});
return {

View File

@@ -65,10 +65,6 @@ const config = (isEsm) => {
commonjs(),
babel({
babelrc: false,
// include: [
// 'src/**',
// // /react-leonardo-ui/
// ],
presets: [
['@babel/preset-env', {
modules: false,

View File

@@ -5656,7 +5656,7 @@ nise@^1.4.6:
path-to-regexp "^1.7.0"
text-encoding "^0.6.4"
node-event-emitter@0.0.1, node-event-emitter@^0.0.1:
node-event-emitter@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/node-event-emitter/-/node-event-emitter-0.0.1.tgz#8b597377d79a1d976f7d45f916d3d3643d73f8ce"