refactor(filter-pane-handler): Add filter pane handler without messing with dimension creation (#959)

* refactor: support multiple dims in filterpane

* refactor: use get dims from handler

* refactor: only rm dims on success

* fix: correct naming

* fix: hard-code to max 1 dim for lo-handler

* test: cover new functionality with unit tests

* chore: rm yarn lock changes

* revert: yarn lock

* refactor: introduce handler without breaking dims

* fix: ignore parcel env files

* fix: ignore parcel env files

* fix: end with empty line

* fix: be explicit without involving maxDimensions

* refactor: remove dims after set props success
This commit is contained in:
Johan Lahti
2022-10-14 13:35:16 +02:00
committed by GitHub
parent 419f994f8f
commit 991bfbbbbe
6 changed files with 225 additions and 8 deletions

View File

@@ -0,0 +1,126 @@
describe('lo-container-handler', () => {
let h;
let loc;
let def;
let handler;
before(() => {
[{ default: handler }] = aw.mock([['**/uid.js', () => () => 'uid']], ['../lo-container-handler.js']);
});
const getMockDim = (cId) => ({
qDef: {
cId,
},
});
beforeEach(() => {
loc = {
qDef: {},
};
def = {
dimensions: {
added: sinon.stub(),
removed: sinon.stub(),
min: () => 0,
max: () => 2,
},
};
h = handler({
dc: loc,
def,
properties: 'props',
dimensions: [],
});
});
it('addDimension should not update dimensions since it is provided from outside', () => {
h.addDimension(getMockDim());
expect(def.dimensions.added).calledOnce;
expect(h.dimensions()).to.deep.equal([]);
expect(def.dimensions.added).calledWithExactly(
{
qDef: {
cId: 'uid',
qSortCriterias: [{ qSortByAscii: 1, qSortByLoadOrder: 1, qSortByNumeric: 1, qSortByState: 1 }],
},
},
'props'
);
});
it('removeDimension should pick correct dimension', () => {
const dim1 = getMockDim('id-1');
const dim2 = getMockDim('id-2');
const dim3 = getMockDim('id-3');
h = handler({
dc: loc,
def,
properties: 'props',
dimensions: [dim1, dim2, dim3],
});
h.removeDimension(1);
expect(def.dimensions.removed).calledWithExactly(dim2, 'props', 1);
});
it('maxDimensions should call max func', () => {
h = handler({
dc: loc,
def: {
dimensions: {
max: () => 'max hey hey',
},
},
});
expect(h.maxDimensions()).to.equal('max hey hey');
});
it('maxDimensions should be read as a number when not a func', () => {
h = handler({
dc: loc,
def: {
dimensions: {
max: 3,
},
},
});
expect(h.maxDimensions()).to.equal(3);
});
it('maxMeasures should be 0', () => {
h = handler({ dc: loc });
expect(h.maxMeasures()).to.equal(0);
});
it('canAddDimension should be true', () => {
h = handler({
dc: loc,
dimensions: [{}, {}, {}],
def: {
dimensions: {
max: 4,
},
},
});
expect(h.canAddDimension()).to.equal(true);
});
it('canAddDimension should be false', () => {
h = handler({
dc: loc,
dimensions: [{}, {}, {}, {}],
def: {
dimensions: {
max: 4,
},
},
});
expect(h.canAddDimension()).to.equal(false);
});
it('canAddMeasure should always be false', () => {
h = handler({ dc: loc });
expect(h.canAddMeasure()).to.equal(false);
});
});

View File

@@ -90,11 +90,13 @@ export default function hcHandler({ dc: hc, def, properties }) {
hc.qLayoutExclude.qHyperCubeDef.qDimensions.push(dimension);
}
return dimension;
},
removeDimension(idx) {
const dimension = hc.qDimensions.splice(idx, 1)[0];
removeIndex(hc.qInterColumnSortOrder, idx);
def.dimensions.removed(dimension, objectProperties, idx);
return dimension;
},
addMeasure(m) {
const measure =

View File

@@ -0,0 +1,68 @@
/* eslint no-param-reassign:0 */
import uid from './uid';
const nxDimension = (f) => ({
qDef: {
qFieldDefs: [f],
},
});
export default function loContainerHandler({ dc: loc, def, properties, dimensions }) {
const objectProperties = properties;
const handler = {
dimensions() {
return dimensions;
},
measures() {
return [];
},
addDimension(d) {
const dimension =
typeof d === 'string'
? nxDimension(d)
: {
...d,
qDef: d.qDef || {},
};
dimension.qDef.cId = dimension.qDef.cId || uid();
dimension.qDef.qSortCriterias = (loc && loc.qDef.qSortCriterias) || [
{
qSortByState: 1,
qSortByLoadOrder: 1,
qSortByNumeric: 1,
qSortByAscii: 1,
},
];
def.dimensions.added(dimension, objectProperties);
return dimension;
},
removeDimension(idx) {
const dimension = dimensions[idx];
def.dimensions.removed(dimension, objectProperties, idx);
return dimension;
},
// addMeasure() {},
// removeMeasure() {},
maxDimensions() {
const { max } = def.dimensions || {};
const maxDims = typeof max === 'function' ? max() : max;
return maxDims || 0;
},
maxMeasures() {
return 0;
},
canAddDimension() {
return handler.dimensions().length < handler.maxDimensions();
},
canAddMeasure() {
return false;
},
};
return handler;
}

View File

@@ -43,12 +43,14 @@ export default function loHandler({ dc: lo, def, properties }) {
lo[k] = dimension[k];
});
def.dimensions.added(dimension, objectProperties);
return dimension;
},
removeDimension(idx) {
const dimension = lo;
delete lo.qDef;
delete lo.qLibraryId;
def.dimensions.removed(dimension, objectProperties, idx);
return dimension;
},
addMeasure() {},
removeMeasure() {},

View File

@@ -1,7 +1,8 @@
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import hcHandler from '@nebula.js/nucleus/src/object/hc-handler';
import loHandler from '@nebula.js/nucleus/src/object/lo-handler';
import loContainerHandler from '@nebula.js/nucleus/src/object/lo-container-handler';
import { Typography } from '@mui/material';
@@ -27,25 +28,39 @@ const getValue = (data, reference, defaultValue) => {
};
export default function DataCube({ setProperties, target, properties }) {
const createHandler = target.propertyPath.match('/qHyperCube') ? hcHandler : loHandler;
// Store dimensions outside of handler to support filterpanes or other containers
// holding list objects, which do not store dimensions in an array (like hc.qDimensions).
const [dimensions, setDimensions] = useState([]);
const supportsMultipleDims = target.dimensions && target.dimensions.max && target.dimensions.max() > 1;
const listBoxHandler = supportsMultipleDims ? loContainerHandler : loHandler;
const createHandler = target.propertyPath.match('/qHyperCube') ? hcHandler : listBoxHandler;
const dc = getValue(properties, target.propertyPath);
const handler = useMemo(
() =>
createHandler({
def: target,
dc: getValue(properties, target.propertyPath),
dc,
properties,
dimensions,
}),
[properties]
[dc, target, properties, dimensions]
);
const onDimensionAdded = (a) => {
handler.addDimension(typeof a === 'object' ? { qLibraryId: a.qId } : a);
setProperties(properties);
const dim = typeof a === 'object' ? { qLibraryId: a.qId } : a;
const addedDim = handler.addDimension(dim);
setProperties(properties).then(() => {
setDimensions([...dimensions, addedDim]);
});
};
const onDimensionRemoved = (idx) => {
handler.removeDimension(idx);
setProperties(properties);
setProperties(properties).then(() => {
setDimensions([...dimensions.slice(0, idx), ...dimensions.slice(idx + 1)]);
});
};
const onMeasureAdded = (a) => {
@@ -64,6 +79,7 @@ export default function DataCube({ setProperties, target, properties }) {
{target.propertyPath}
</Typography>
<Fields
key="dimensions"
onAdded={onDimensionAdded}
onRemoved={onDimensionRemoved}
canAdd={handler.canAddDimension()}
@@ -73,6 +89,7 @@ export default function DataCube({ setProperties, target, properties }) {
addLabel="Add dimension"
/>
<Fields
key="measures"
onAdded={onMeasureAdded}
onRemoved={onMeasureRemoved}
canAdd={handler.canAddMeasure()}

View File

@@ -1 +1,3 @@
yarn.lock
yarn.lock
.parcel-cache
.cache