diff --git a/src/core/reports/report-from-form/report-from-form.ts b/src/core/reports/report-from-form/report-from-form.ts index d181b2f79a..1bad56b435 100644 --- a/src/core/reports/report-from-form/report-from-form.ts +++ b/src/core/reports/report-from-form/report-from-form.ts @@ -20,7 +20,7 @@ * */ -import {AjfField, AjfFieldType, AjfFieldWithChoices, AjfForm} from '@ajf/core/forms'; +import {AjfField, AjfFieldType, AjfFieldWithChoices, AjfForm, AjfRangeField} from '@ajf/core/forms'; import {createFormula} from '@ajf/core/models'; import {AjfChartType} from '../interface/charts/chart-type'; @@ -45,33 +45,26 @@ import { function createBooleanWidget(field: AjfField): AjfWidget { return createWidget({ widgetType: AjfWidgetType.Column, - content: [ - createWidget({ - widgetType: AjfWidgetType.Text, - htmlText: `
[[COUNTFORMS(forms,"${field.name} != null")]] answers
`, - styles: {margin: '10px', paddingLeft: '15px'}, - } as AjfWidgetCreate), - createWidget({ - widgetType: AjfWidgetType.Chart, - type: AjfChartType.Pie, - labels: {formula: '[\'True\', \'False\']'}, - dataset: [createDataset({ - label: 'true', - formula: [createFormula({ - formula: `[COUNTFORMS(forms,"${field.name}===true"),COUNTFORMS(forms,"${ - field.name}===false")]` - })], - options: {backgroundColor: ['green', 'red']} - } as Partial) as AjfDataset], - options: { - responsive: true, - maintainAspectRatio: false, - legend: {display: true, position: 'bottom'} - }, - styles: {width: '100%', height: '400px'}, - exportable: true - } as AjfWidgetCreate) - ], + content: [createWidget({ + widgetType: AjfWidgetType.Chart, + type: AjfChartType.Pie, + labels: {formula: '[\'True\', \'False\']'}, + dataset: [createDataset({ + label: 'true', + formula: [createFormula({ + formula: `[COUNTFORMS(forms,"${field.name}===true"),COUNTFORMS(forms,"${ + field.name}===false")]` + })], + options: {backgroundColor: ['green', 'red']} + } as Partial) as AjfDataset], + options: { + responsive: true, + maintainAspectRatio: false, + legend: {display: true, position: 'bottom'} + }, + styles: {width: '100%', height: '400px'}, + exportable: true + } as AjfWidgetCreate)], } as AjfWidgetCreate); } function createMultipleChoiceWidget(field: AjfFieldWithChoices): AjfWidget { @@ -92,26 +85,19 @@ function createMultipleChoiceWidget(field: AjfFieldWithChoices): AjfWidget return createWidget({ widgetType: AjfWidgetType.Column, - content: [ - createWidget({ - widgetType: AjfWidgetType.Text, - htmlText: `
[[COUNTFORMS(forms,"${field.name} != null")]] answers
`, - styles: {margin: '10px', paddingLeft: '15px'}, - } as AjfWidgetCreate), - createWidget({ - widgetType: AjfWidgetType.Chart, - type: chartType, - labels, - dataset, - options: { - responsive: true, - maintainAspectRatio: false, - legend: {display: true, position: 'bottom'} - }, - styles: {width: '100%', height: '400px'}, - exportable: true - } as AjfWidgetCreate) - ], + content: [createWidget({ + widgetType: AjfWidgetType.Chart, + type: chartType, + labels, + dataset, + options: { + responsive: true, + maintainAspectRatio: false, + legend: {display: true, position: 'bottom'} + }, + styles: {width: '100%', height: '400px'}, + exportable: true + } as AjfWidgetCreate)], } as AjfWidgetCreate); } function createNumberWidget(field: AjfField): AjfWidget { @@ -182,7 +168,7 @@ function createSingleChoiceWidget(field: AjfFieldWithChoices): AjfWidget { let labels = {formula: `[]`}; if (choices.length > 5) { - labels = {formula: `[${choices.map(c => `\'${c.label}\'`)}]`}; + labels = {formula: `[${choices.map(c => `${JSON.stringify(c.label)}`)}]`}; chartType = AjfChartType.Pie; dataset = [createDataset({ @@ -210,15 +196,104 @@ function createSingleChoiceWidget(field: AjfFieldWithChoices): AjfWidget { return createWidget({ widgetType: AjfWidgetType.Column, + content: [createWidget({ + widgetType: AjfWidgetType.Chart, + type: chartType, + labels, + dataset, + options: { + responsive: true, + maintainAspectRatio: false, + legend: {display: true, position: 'bottom'} + }, + styles: {width: '100%', height: '400px'}, + exportable: true + } as AjfWidgetCreate)], + } as AjfWidgetCreate); +} + +function createRangeWidget(field: AjfRangeField): AjfWidget { + const end = field.end ?? 11; + const start = field.start ?? 1; + let choices = []; + for (let i = start; i <= end; i++) { + choices.push(i); + } + + let labels = {formula: `[${JSON.stringify(field.label)}]`}; + let dataset: AjfDataset[] = choices.map( + (_, index) => createDataset({ + label: `${index + start}`, + formula: [createFormula( + {formula: `[COUNTFORMS(forms,"${field.name}===${index + 1 + start}")]`})], + options: { + backgroundColor: backgroundColor[index], + stack: `Stack ${index}`, + } + } as Partial) as AjfDataset); + return createWidget({ + widgetType: AjfWidgetType.Column, + styles: widgetStyle, content: [ createWidget({ - widgetType: AjfWidgetType.Text, - htmlText: `
[[COUNTFORMS(forms,"${field.name} != null")]] answers
`, - styles: {margin: '10px', paddingLeft: '15px'}, + widgetType: AjfWidgetType.Layout, + columns: [0.33, 0.33, 0.33], + content: [ + createWidget({ + widgetType: AjfWidgetType.Column, + styles: boxStyle, + content: [ + createWidget({ + widgetType: AjfWidgetType.Text, + htmlText: `
Mean
`, + styles: widgetTitleStyle, + } as AjfWidgetCreate), + createWidget({ + widgetType: AjfWidgetType.Text, + 'htmlText': + `

[[MEAN(forms,"${field.name}")]] / [[MAX(forms,"${field.name}")]]

`, + styles: widgetTitleStyle, + } as AjfWidgetCreate) + ] + } as AjfWidgetCreate), + createWidget({ + widgetType: AjfWidgetType.Column, + styles: boxStyle, + content: [ + createWidget({ + widgetType: AjfWidgetType.Text, + htmlText: `
Median
`, + styles: widgetTitleStyle, + } as AjfWidgetCreate), + createWidget({ + widgetType: AjfWidgetType.Text, + 'htmlText': + `

[[MEDIAN(forms,"${field.name}")]] / [[MAX(forms,"${field.name}")]]

`, + styles: widgetTitleStyle, + } as AjfWidgetCreate) + ] + } as AjfWidgetCreate), + createWidget({ + widgetType: AjfWidgetType.Column, + styles: boxStyle, + content: [ + createWidget({ + widgetType: AjfWidgetType.Text, + htmlText: `
Mode
`, + styles: widgetTitleStyle, + } as AjfWidgetCreate), + createWidget({ + widgetType: AjfWidgetType.Text, + htmlText: `

[[MODE(forms,"${field.name}")]]

`, + styles: widgetTitleStyle, + } as AjfWidgetCreate) + ] + } as AjfWidgetCreate), + ] } as AjfWidgetCreate), createWidget({ widgetType: AjfWidgetType.Chart, - type: chartType, + type: AjfChartType.Bar, labels, dataset, options: { @@ -229,7 +304,7 @@ function createSingleChoiceWidget(field: AjfFieldWithChoices): AjfWidget { styles: {width: '100%', height: '400px'}, exportable: true } as AjfWidgetCreate) - ], + ] } as AjfWidgetCreate); } @@ -253,14 +328,15 @@ export function reportFromForm(form: Partial, id?: number): AjfReport { // create the title of the widget. const fieldTitleWidget: AjfWidget = createWidget({ widgetType: AjfWidgetType.Text, - htmlText: `
${field.label}
`, + htmlText: `
${field.label} - [[COUNTFORMS(forms,"${ + field.name} != null")]] answers
`, styles: widgetTitleStyle } as AjfWidgetCreate); slideWidgets.push(fieldTitleWidget); switch (field.fieldType) { default: - slideWidgets.pop(); // remove the title of empty widget + slideWidgets.pop(); // remove the title of empty widget break; case AjfFieldType.Number: slideWidgets.push(createNumberWidget(field)); @@ -274,6 +350,9 @@ export function reportFromForm(form: Partial, id?: number): AjfReport { case AjfFieldType.MultipleChoice: slideWidgets.push(createMultipleChoiceWidget(field as AjfFieldWithChoices)); break; + case AjfFieldType.Range: + slideWidgets.push(createRangeWidget(field as AjfRangeField)); + break; } }); // if the slide have a widgets add him to the reports with the relative title diff --git a/src/dev-app/mat-report-from-form/mockup.ts b/src/dev-app/mat-report-from-form/mockup.ts index 1127d8541a..0352ed102a 100644 --- a/src/dev-app/mat-report-from-form/mockup.ts +++ b/src/dev-app/mat-report-from-form/mockup.ts @@ -91,16 +91,22 @@ export const formSchema: any = { label: '64-bit floating point number', nodeType: 0, fieldType: 2, - validation: {notEmpty: true} + validation: {notEmpty: true}, + warning: {conditions: [{condition: 'number1 > 300', warningMessage: 'Are you sure?'}]} }, { parent: 1001, id: 1002, - name: 'number2', + name: 'number', label: 'A number with the added constraint of being an integer', nodeType: 0, fieldType: 2, validation: { + maxValue: { + 'condition': 'number < 150', + 'clientValidation': true, + 'errorMessage': 'minore di 150' + }, conditions: [ { 'condition': 'isInt(number)', @@ -126,7 +132,7 @@ export const formSchema: any = { { parent: 1003, id: 1004, - name: 'bool', + name: 'boolean', label: 'Boolean answer (a checkbox)', nodeType: 0, fieldType: 3 @@ -142,7 +148,16 @@ export const formSchema: any = { }, {parent: 1005, id: 1006, name: 'date input', label: 'A date', nodeType: 0, fieldType: 9}, {parent: 1006, id: 1007, name: 'time', label: 'Time', nodeType: 0, fieldType: 10}, - {parent: 1007, id: 1008, name: 'barcode', label: 'Barcode', nodeType: 0, fieldType: 13} + {parent: 1007, id: 1008, name: 'barcode', label: 'Barcode', nodeType: 0, fieldType: 13}, { + parent: 1008, + id: 1009, + name: 'range', + label: 'Range', + start: 1, + end: 15, + nodeType: 0, + fieldType: 17 + } ] }, { @@ -168,6 +183,7 @@ export const formSchema: any = { label: 'Multiple choice answer 6 options', nodeType: 0, fieldType: 5, + forceExpanded: true, choicesOriginRef: 'mchoice2' }, { @@ -204,7 +220,7 @@ export const formSchema: any = { label: 'Name of your cat:', nodeType: 0, fieldType: 0, - 'visibility': {'condition': 'pet_type === \'cat\''} + visibility: {condition: 'pet_type === \'cat\''} }, { parent: 3002, @@ -213,7 +229,7 @@ export const formSchema: any = { label: 'Name of your dog:', nodeType: 0, fieldType: 0, - 'visibility': {'condition': 'pet_type === \'dog\''} + visibility: {condition: 'pet_type === \'dog\''} } ] }, @@ -263,7 +279,7 @@ export const formSchema: any = { { parent: 5, id: 5001, - name: name, + name: 'name', label: 'Child\'s name', nodeType: 0, fieldType: 0, diff --git a/src/dev-app/mat-report-from-form/report-from-form-demo.ts b/src/dev-app/mat-report-from-form/report-from-form-demo.ts index 40441a29de..743ea2907b 100644 --- a/src/dev-app/mat-report-from-form/report-from-form-demo.ts +++ b/src/dev-app/mat-report-from-form/report-from-form-demo.ts @@ -27,6 +27,7 @@ import { AjfFieldWithChoices, AjfForm, AjfFormSerializer, + AjfRangeField, flattenNodes, isField } from '@ajf/core/forms'; @@ -108,6 +109,13 @@ export class ReportFromFormDemo { multipleChoices[Math.floor(Math.random() * multipleChoices.length)], multipleChoices[Math.floor(Math.random() * multipleChoices.length)] ]; + break; + case AjfFieldType.Range: + const rangeField = field as AjfRangeField; + const end = rangeField.end ?? 10; + const start = rangeField.start ?? 1; + const value = Math.floor(start + Math.random() * (end + 1 - start)); + ctx[field.name] = value; } }); ctxMap.push(ctx);