Skip to content

Commit

Permalink
feat(core/reports): add dynamic table widget
Browse files Browse the repository at this point in the history
  • Loading branch information
peppedeka authored and trik committed Apr 8, 2020
1 parent f574539 commit 9c4e76e
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 27 deletions.
35 changes: 35 additions & 0 deletions src/core/reports/interface/widgets/dynamic-table-widget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @license
* Copyright (C) Gnucoop soc. coop.
*
* This file is part of the Advanced JSON forms (ajf).
*
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Advanced JSON forms (ajf).
* If not, see http://www.gnu.org/licenses/.
*
*/

import {AjfFormula} from '@ajf/core/models';

import {AjfTableDataset} from '../dataset/table-dataset';
import {AjfDataWidget} from './data-widget';

export interface AjfDynamicTableWidget extends AjfDataWidget {
/**
* it should return a AjfTableCell[][]
*/
rowDefinition: AjfFormula;
cellStyles: any;
dataset: AjfTableDataset[];
}
1 change: 1 addition & 0 deletions src/core/reports/interface/widgets/widget-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ export enum AjfWidgetType {
Column,
Formula,
ImageContainer,
DynamicTable,
LENGTH
}
40 changes: 40 additions & 0 deletions src/core/reports/utils/widgets-instances/widget-instance-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* @license
* Copyright (C) Gnucoop soc. coop.
*
* This file is part of the Advanced JSON forms (ajf).
*
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Advanced JSON forms (ajf).
* If not, see http://www.gnu.org/licenses/.
*
*/

import {AjfContext, AjfFormula, evaluateExpression} from '@ajf/core/models';
import {TranslateService} from '@ngx-translate/core';

export function trFormula(f: AjfFormula, context: AjfContext, ts: TranslateService): any {
let formula = f.formula;
if (formula.substr(0, 1) === '"') {
const ft = formula.slice(1, -1);
const transFt = ft != null && typeof ft === 'string' && ft.trim().length > 0
? ts.instant(ft) : ft;
if (ft.length > 0) {
formula = `"${transFt}"`;
}
} else {
formula = formula != null && typeof formula === 'string' && formula.trim().length > 0
? ts.instant(formula) : formula;
}
return evaluateExpression(formula, context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ import {
AjfWidgetWithContentInstance
} from '../../interface/widgets-instances/widget-with-content-instance';
import {AjfChartWidget} from '../../interface/widgets/chart-widget';
import {AjfDynamicTableWidget} from '../../interface/widgets/dynamic-table-widget';
import {AjfFormulaWidget} from '../../interface/widgets/formula-widget';
import {AjfImageContainerWidget} from '../../interface/widgets/image-container-widget';
import {AjfImageWidget} from '../../interface/widgets/image-widget';
import {AjfMapWidget} from '../../interface/widgets/map-widget';
import {AjfTableDataset} from '../../interface/dataset/table-dataset';
import {AjfTableWidget} from '../../interface/widgets/table-widget';
import {AjfTextWidget} from '../../interface/widgets/text-widget';
import {AjfWidget} from '../../interface/widgets/widget';
Expand All @@ -51,10 +53,12 @@ import {AjfWidgetWithContent} from '../../interface/widgets/widget-with-content'
import {evaluateAggregation} from '../aggregation/evaluate-aggregation';

import {createWidgetInstance} from './create-widget-instance';
import {trFormula} from './widget-instance-utils';

export function widgetToWidgetInstance(
widget: AjfWidget, context: AjfContext, ts: TranslateService): AjfWidgetInstance {
const wi = createWidgetInstance(widget, context, ts);

if (widget.widgetType === AjfWidgetType.Column || widget.widgetType === AjfWidgetType.Layout) {
const wwc = widget as AjfWidgetWithContent;
const wwci = wi as AjfWidgetWithContentInstance;
Expand Down Expand Up @@ -134,32 +138,38 @@ export function widgetToWidgetInstance(
} else if (widget.widgetType === AjfWidgetType.Table) {
const tw = widget as AjfTableWidget;
const twi = wi as AjfTableWidgetInstance;
const trFormula = (f: AjfFormula) => {
let formula = f.formula;
if (formula.substr(0, 1) === '"') {
const ft = formula.slice(1, -1);
const transFt = ft != null && typeof ft === 'string' && ft.trim().length > 0
? ts.instant(ft) : ft;
if (ft.length > 0) {
formula = `"${transFt}"`;
}
} else {
formula = formula != null && typeof formula === 'string' && formula.trim().length > 0
? ts.instant(formula) : formula;
}
return evaluateExpression(formula, context);
};

twi.dataset = tw.dataset.map(row => row.map(cell => {
return cell.formula instanceof Array ? cell.formula.map(f => trFormula(f as AjfFormula)) :
trFormula(cell.formula!);
return cell.formula instanceof Array ?
cell.formula.map(f => trFormula(f as AjfFormula, context as AjfContext, ts)) :
trFormula(cell.formula!, context as AjfContext, ts);
}));

twi.data = (tw.dataset || [])
.map(row => row.map(cell => ({
value: evaluateExpression(cell.formula.formula, context),
style: {...tw.cellStyles, ...cell.style},
rowspan: cell.rowspan,
colspan: cell.colspan,
})));
} else if (widget.widgetType === AjfWidgetType.DynamicTable) {
const tdw = widget as AjfDynamicTableWidget;
const tdwi = wi as AjfTableWidgetInstance;

tdwi.dataset = tdw.dataset.map((cell: AjfTableDataset) => {
return cell.formula instanceof Array ?
cell.formula.map(f => trFormula(f as AjfFormula, context, ts)) :
trFormula(cell.formula!, context, ts);
});
const dataset = evaluateExpression(tdw.rowDefinition.formula, context) || [];

const header = (tdw.dataset || []).map(cell => ({
value: evaluateExpression(cell.formula.formula, context),
style: {...tdw.cellStyles, ...cell.style},
rowspan: cell.rowspan,
colspan: cell.colspan,
}));
twi.data = (tw.dataset ||
[]).map(row => row.map(cell => ({
value: evaluateExpression(cell.formula.formula, context),
style: {...tw.cellStyles, ...cell.style},
rowspan: cell.rowspan,
colspan: cell.colspan,
})));
tdwi.data = [[...header], ...dataset];
} else if (widget.widgetType === AjfWidgetType.Image) {
const iw = widget as AjfImageWidget;
const iwi = wi as AjfImageWidgetInstance;
Expand Down
56 changes: 54 additions & 2 deletions src/core/reports/widget-instances.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
*
*/

import {AjfTextWidgetInstance, AjfWidgetType, createWidget,
widgetToWidgetInstance} from './public-api';
import {AjfTableWidgetInstance, AjfTextWidgetInstance, AjfWidgetType,
createWidget, widgetToWidgetInstance} from './public-api';

class TsMock {
instant(str: string): string {
Expand Down Expand Up @@ -59,4 +59,56 @@ describe('widgetToWidgetInstance', () => {
expect(instance.htmlText).toBe(ctx.foo[i]);
}
});

it('should load the row of the table in runtime', () => {
const tsMock = new TsMock() as any;
const widget = createWidget({
widgetType: AjfWidgetType.DynamicTable,
rowDefinition: {'formula': 'dynamicData'},
dataset: [
{
'label': '',
'formula': {
'formula': '"Girl"'
},
'style': {
'text-align': 'left',
'font-weight': 'bold'
},
'aggregation': {
'aggregation': 0
}
},
{
'label': '',
'formula': {
'formula': '"Name"'
},
'style': {
'text-align': 'left',
'font-weight': 'bold'
},
'aggregation': {
'aggregation': 0
}
}
]
} as any);
const ctx = {
dynamicData: [
[
{
'value': 'foo'
},
{
'value': 'baz'
}
]
]
};

const instance = widgetToWidgetInstance(widget, ctx, tsMock) as AjfTableWidgetInstance;
expect(instance.data[1][0].value).toBe(ctx.dynamicData[0][0].value);
});
});

1 change: 1 addition & 0 deletions src/ionic/reports/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class AjfReportWidget extends CoreComponent {
[AjfWidgetType.Text]: {component: AjfTextWidgetComponent},
[AjfWidgetType.Chart]: {component: AjfChartWidgetComponent},
[AjfWidgetType.Table]: {component: AjfTableWidgetComponent},
[AjfWidgetType.DynamicTable]: {component: AjfTableWidgetComponent},
[AjfWidgetType.Map]: {component: AjfMapWidgetComponent},
[AjfWidgetType.Column]: {component: AjfColumnWidgetComponent},
[AjfWidgetType.Formula]: {component: AjfFormulaWidgetComponent},
Expand Down
1 change: 1 addition & 0 deletions src/material/reports/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class AjfReportWidget extends CoreComponent {
[AjfWidgetType.Text]: {component: AjfTextWidgetComponent},
[AjfWidgetType.Chart]: {component: AjfChartWidgetComponent},
[AjfWidgetType.Table]: {component: AjfTableWidgetComponent},
[AjfWidgetType.DynamicTable]: {component: AjfTableWidgetComponent},
[AjfWidgetType.Map]: {component: AjfMapWidgetComponent},
[AjfWidgetType.Column]: {component: AjfColumnWidgetComponent},
[AjfWidgetType.Formula]: {component: AjfFormulaWidgetComponent},
Expand Down
3 changes: 2 additions & 1 deletion tools/public_api_guard/core/reports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ export declare enum AjfWidgetType {
Column = 7,
Formula = 8,
ImageContainer = 9,
LENGTH = 10
DynamicTable = 10,
LENGTH = 11
}

export interface AjfWidgetWithContent extends AjfWidget {
Expand Down
3 changes: 3 additions & 0 deletions tools/public_api_guard/ionic/reports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export declare class AjfReportWidget extends CoreComponent {
5: {
component: typeof AjfTableWidgetComponent;
};
10: {
component: typeof AjfTableWidgetComponent;
};
6: {
component: typeof AjfMapWidgetComponent;
};
Expand Down
3 changes: 3 additions & 0 deletions tools/public_api_guard/material/reports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export declare class AjfReportWidget extends CoreComponent {
5: {
component: typeof AjfTableWidgetComponent;
};
10: {
component: typeof AjfTableWidgetComponent;
};
6: {
component: typeof AjfMapWidgetComponent;
};
Expand Down

0 comments on commit 9c4e76e

Please sign in to comment.