From 5ceab66a3ae343870fcae8201d2bc35181e38f24 Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Wed, 1 Apr 2026 21:08:15 +0700 Subject: [PATCH 1/8] add eslint sorting --- .eslintrc.js | 9 +++++++++ AppBuilder/core | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 79cbb055..c4b10d87 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -43,6 +43,15 @@ module.exports = { }, ], + "sort-imports": ["error", { + "ignoreCase": true, + "ignoreDeclarationSort": false, + "ignoreMemberSort": false, + "memberSyntaxSortOrder": ["none", "all", "multiple", "single"], + "allowSeparatedGroups": false + }], + + // eslint rule customization here: "no-console": 0, // allow console.log() in our services "no-unused-vars": 0, // allow unused variables (webpack will remove them) diff --git a/AppBuilder/core b/AppBuilder/core index a740ae92..ac6a1c45 160000 --- a/AppBuilder/core +++ b/AppBuilder/core @@ -1 +1 @@ -Subproject commit a740ae923955823569f86421f4bc29b107f4fbc3 +Subproject commit ac6a1c45b11a9aad0d15d0111fc697331b3d316d From 0d9b2ff5ef44fc9e3410910081aa26ef77f40efa Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Thu, 2 Apr 2026 21:05:05 +0700 Subject: [PATCH 2/8] init --- AppBuilder/platform/plugins/included/index.js | 10 + .../included/view_chart/ABViewChartCore.js | 135 +++++++ .../view_chart/area/FNAbviewchartarea.js | 128 ++++++ .../area/FNAbviewchartareaComponent.js | 63 +++ .../view_chart/bar/FNAbviewchartbar.js | 136 +++++++ .../bar/FNAbviewchartbarComponent.js | 59 +++ .../view_chart/chart/FNAbviewchart.js | 377 ++++++++++++++++++ .../chart/FNAbviewchartComponent.js | 71 ++++ .../container/FNAbviewchartcontainer.js | 33 ++ .../FNAbviewchartcontainerComponent.js | 62 +++ .../view_chart/line/FNAbviewchartline.js | 137 +++++++ .../line/FNAbviewchartlineComponent.js | 46 +++ .../view_chart/pie/FNAbviewchartpie.js | 125 ++++++ .../pie/FNAbviewchartpieComponent.js | 37 ++ .../platform/views/ABViewChartContainer.js | 17 - .../ABViewChartContainerComponent.js | 55 --- 16 files changed, 1419 insertions(+), 72 deletions(-) create mode 100644 AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js create mode 100644 AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js delete mode 100644 AppBuilder/platform/views/ABViewChartContainer.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartContainerComponent.js diff --git a/AppBuilder/platform/plugins/included/index.js b/AppBuilder/platform/plugins/included/index.js index cdc4f0a9..08a8274f 100644 --- a/AppBuilder/platform/plugins/included/index.js +++ b/AppBuilder/platform/plugins/included/index.js @@ -1,4 +1,7 @@ +import viewArea from "./view_chart/area/FNAbviewchartarea.js"; +import viewBar from "./view_chart/bar/FNAbviewchartbar.js"; import viewCarousel from "./view_carousel/FNAbviewcarousel.js"; +import viewChart from "./view_chart/chart/FNAbviewchart.js"; import viewComment from "./view_comment/FNAbviewcomment.js"; import viewCsvExporter from "./view_csvExporter/FNAbviewcsvexporter.js"; import viewCsvImporter from "./view_csvImporter/FNAbviewcsvimporter.js"; @@ -10,13 +13,18 @@ import viewImage from "./view_image/FNAbviewimage.js"; import viewKanban from "./view_kanban/FNABViewKanban.js"; import viewLabel from "./view_label/FNAbviewlabel.js"; import viewLayout from "./view_layout/FNAbviewlayout.js"; +import viewLine from "./view_chart/line/FNAbviewchartline.js"; import viewList from "./view_list/FNAbviewlist.js"; import viewPdfImporter from "./view_pdfImporter/FNAbviewpdfimporter.js"; +import viewPie from "./view_chart/pie/FNAbviewchartpie.js"; import viewTab from "./view_tab/FNAbviewtab.js"; import viewText from "./view_text/FNAbviewtext.js"; const AllPlugins = [ + viewArea, + viewBar, viewCarousel, + viewChart, viewComment, viewCsvExporter, viewCsvImporter, @@ -28,8 +36,10 @@ const AllPlugins = [ viewKanban, viewLabel, viewLayout, + viewLine, viewList, viewPdfImporter, + viewPie, viewTab, viewText, ]; diff --git a/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js b/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js new file mode 100644 index 00000000..5d714453 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js @@ -0,0 +1,135 @@ +const ABViewContainer = require("../../platform/views/ABViewContainer"); + +const ABViewChartPropertyComponentDefaults = { + dataviewID: "", + columnValue: "", + columnLabel: "", + columnValue2: "", + isPercentage: 1, + showLabel: 1, + labelPosition: "left", + labelWidth: 120, + height: 200, + multipleSeries: 0, +}; + +const ABViewChartDefaults = { + key: "chart", // {string} unique key for this view + icon: "bar-chart", // {string} fa-[icon] reference for this view + labelKey: "Chart", // {string} the multilingual label key for the class label +}; + +module.exports = class ABViewChartCore extends ABViewContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewChartDefaults); + } + + static common() { + return ABViewChartDefaults; + } + + static defaultValues() { + return ABViewChartPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.dataviewID = + this.settings.dataviewID ?? + ABViewChartPropertyComponentDefaults.dataviewID; + + this.settings.columnValue = + this.settings.columnValue ?? + ABViewChartPropertyComponentDefaults.columnValue; + + this.settings.columnLabel = + this.settings.columnLabel ?? + ABViewChartPropertyComponentDefaults.columnLabel; + + this.settings.columnValue2 = + this.settings.columnValue2 ?? + ABViewChartPropertyComponentDefaults.columnValue2; + + this.settings.isPercentage = parseInt( + this.settings.isPercentage ?? + ABViewChartPropertyComponentDefaults.isPercentage + ); + + this.settings.showLabel = parseInt( + this.settings.showLabel ?? + ABViewChartPropertyComponentDefaults.showLabel + ); + + this.settings.labelPosition = + this.settings.labelPosition || + ABViewChartPropertyComponentDefaults.labelPosition; + + this.settings.labelWidth = parseInt( + this.settings.labelWidth ?? + ABViewChartPropertyComponentDefaults.labelWidth + ); + + this.settings.height = parseInt( + this.settings.height ?? ABViewChartPropertyComponentDefaults.height + ); + + this.settings.multipleSeries = parseInt( + this.settings.multipleSeries ?? + ABViewChartPropertyComponentDefaults.multipleSeries + ); + + this.translate(this, this, ["chartLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + const viewsToAllow = ["label", "pie", "bar", "line", "area"]; + return this.application.viewAll((c) => { + return viewsToAllow.indexOf(c.common().key) > -1; + }); + } + + labelField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnLabel); + } + + valueField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue); + } + + valueField2() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue2); + } +}; diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js new file mode 100644 index 00000000..aef5eeda --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js @@ -0,0 +1,128 @@ +import FNAbviewchartareaComponent from "./FNAbviewchartareaComponent.js"; +import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; + +// FNAbviewchartarea Web +// A web side import for an ABView. +// +export default function FNAbviewchartarea({ + /*AB,*/ + ABViewPlugin, + ABViewComponentPlugin, + ABViewContainer, + ABViewWidgetPlugin, +}) { + const ABViewChartContainer = FNAbviewchartcontainer({ + ABViewComponentPlugin, + ABViewWidgetPlugin, + }); + + const ABAbviewchartareaComponent = FNAbviewchartareaComponent({ + ABViewComponentPlugin, + }); + + const ABViewChartAreaPropertyComponentDefaults = { + areaType: "area", + isLegend: 1, + // chartWidth: 600, + chartHeight: 200, + labelFontSize: 12, + stepValue: 20, + maxValue: 100, + }; + + const ABViewDefaults = { + key: "area", // {string} unique key for this view + icon: "area-chart", // {string} fa-[icon] reference for this view + labelKey: "Area", // {string} the multilingual label key for the class label + }; + + class ABViewChartAreaCore extends ABViewChartContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewDefaults); + } + + static common() { + return ABViewDefaults; + } + + static defaultValues() { + return ABViewChartAreaPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.areaType = + this.settings.areaType || + ABViewChartAreaPropertyComponentDefaults.areaType; + + this.settings.isLegend = parseInt( + this.settings.isLegend ?? + ABViewChartAreaPropertyComponentDefaults.isLegend + ); + + // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartAreaPropertyComponentDefaults.chartWidth); + this.settings.chartHeight = parseInt( + this.settings.chartHeight ?? + ABViewChartAreaPropertyComponentDefaults.chartHeight + ); + + this.settings.labelFontSize = parseInt( + this.settings.labelFontSize ?? + ABViewChartAreaPropertyComponentDefaults.labelFontSize + ); + this.settings.stepValue = parseInt( + this.settings.stepValue ?? + ABViewChartAreaPropertyComponentDefaults.stepValue + ); + this.settings.maxValue = parseInt( + this.settings.maxValue ?? + ABViewChartAreaPropertyComponentDefaults.maxValue + ); + + this.translate(this, this, ["areaLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + return []; + } + } + + return class ABViewChartArea extends ABViewChartAreaCore { + /** + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ + static getPluginKey() { + return this.common().key; + } + + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component(parentId) { + return new ABAbviewchartareaComponent(this, parentId); + } + + // constructor(values, application, parent, defaultValues) { + // super(values, application, parent, defaultValues); + // } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js new file mode 100644 index 00000000..d7bc0d0a --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js @@ -0,0 +1,63 @@ +import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; + +export default function FNAbviewchartareaComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + const ChartContainerComponent = FNAbviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class ABviewchartareaComponent extends ChartContainerComponent { + constructor(baseView, idBase, ids) { + super(baseView, idBase || `ABViewChartArea_${baseView.id}`, ids); + } + + ui() { + const settings = this.settings; + + return super.ui({ + view: "chart", + type: settings.areaType, + yAxis: { + start: 0, + step: settings.stepValue, //"#stepValue#", + end: settings.maxValue, //"#maxValue#" + }, + xAxis: { + template: settings.isLegend + ? `
#label#
` + : "", + }, + legend: settings.isLegend + ? { + template: `
#label#
`, + values: [], // TODO : bug in webix 5.1.7 + } + : null, + series: [ + { + alpha: 0.7, + value: "#value#", + color: "#ee4339", + }, + { + alpha: 0.4, + value: "#value2#", + color: "#a7ee70", + }, + ], + height: settings.chartHeight, + // width: settings.chartWidth, + }); + } + + async init(AB) { + await super.init(AB); + } + + onShow() { + super.onShow(); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js new file mode 100644 index 00000000..b5b5f4bc --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js @@ -0,0 +1,136 @@ +import FNAbviewchartbarComponent from "./FNAbviewchartbarComponent.js"; +import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; + + +// FNAbviewchartbar Web +// A web side import for an ABView. +// +export default function FNAbviewchartbar({ + /*AB,*/ + ABViewPlugin, + ABViewComponentPlugin, + ABViewContainer, + ABViewWidgetPlugin +}) { + const ABViewChartContainer = FNAbviewchartcontainer({ + ABViewComponentPlugin, + ABViewWidgetPlugin, + }); + const ABAbviewchartbarComponent = FNAbviewchartbarComponent({ ABViewComponentPlugin }); + + const ABViewChartBarPropertyComponentDefaults = { + barType: "bar", + barPreset: "column", + isLegend: 1, + // chartWidth: 600, + height: 200, + labelFontSize: 12, + stepValue: 20, + maxValue: 100, + }; + + const ABViewDefaults = { + key: "bar", // {string} unique key for this view + icon: "bar-chart", // {string} fa-[icon] reference for this view + labelKey: "Bar", // {string} the multilingual label key for the class label + }; + + class ABViewChartBarCore extends ABViewChartContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewDefaults); + } + + static common() { + return ABViewDefaults; + } + + static defaultValues() { + return ABViewChartBarPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.barType = + this.settings.barType || + ABViewChartBarPropertyComponentDefaults.barType; + + this.settings.barPreset = + this.settings.barPreset || + ABViewChartBarPropertyComponentDefaults.barPreset; + + this.settings.isLegend = parseInt( + this.settings.isLegend ?? + ABViewChartBarPropertyComponentDefaults.isLegend + ); + + // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartBarPropertyComponentDefaults.chartWidth); + this.settings.height = parseInt( + this.settings.height ?? ABViewChartBarPropertyComponentDefaults.height + ); + + this.settings.labelFontSize = parseInt( + this.settings.labelFontSize ?? + ABViewChartBarPropertyComponentDefaults.labelFontSize + ); + this.settings.stepValue = parseInt( + this.settings.stepValue ?? + ABViewChartBarPropertyComponentDefaults.stepValue + ); + this.settings.maxValue = parseInt( + this.settings.maxValue ?? + ABViewChartBarPropertyComponentDefaults.maxValue + ); + + this.translate(this, this, ["barLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + return []; + } + }; + + return class ABViewChartBar extends ABViewChartBarCore { + + /** + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ + static getPluginKey() { + return this.common().key; + } + + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component(parentId) { + return new ABAbviewchartbarComponent(this, parentId); + } + + + // constructor(values, application, parent, defaultValues) { + // super(values, application, parent, defaultValues); + // } + + + }; + +} + diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js new file mode 100644 index 00000000..8e8402e8 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js @@ -0,0 +1,59 @@ +import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; + +export default function FNAbviewchartbarComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + const ChartContainerComponent = FNAbviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class FNAbviewchartbarComponent extends ChartContainerComponent { + constructor(baseView, idBase, ids) { + super(baseView, idBase || `ABViewChartBar_${baseView.id}`, ids); + } + + ui() { + const settings = this.settings; + + return super.ui({ + view: "chart", + type: settings.barType, + preset: settings.barPreset, + value: "#value#", + color: "#color#", + yAxis: { + start: 0, + step: settings.stepValue, //"#stepValue#", + end: settings.maxValue, //"#maxValue#" + }, + xAxis: { + template: settings.isLegend + ? `
#label#
` + : "", + }, + legend: + settings.barType === "bar" || !settings.barType + ? settings.isLegend + ? `
#label#
` + : "" + : settings.isLegend + ? { + template: `
#label#
`, + values: [], // TODO : bug in webix 5.1.7 + } + : null, + height: settings.height, + // width: settings.chartWidth, + }); + } + + async init(AB) { + await super.init(AB); + } + + onShow() { + super.onShow(); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js new file mode 100644 index 00000000..f5fcdb63 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js @@ -0,0 +1,377 @@ +import FNAbviewchartComponent from "./FNAbviewchartComponent.js"; +import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; + + +// FNAbviewchart Web +// A web side import for an ABView. +// +export default function FNAbviewchart({ + /*AB,*/ + ABViewPlugin, + ABViewComponentPlugin, + ABViewContainer, + ABViewWidgetPlugin +}) { + const ABViewChartContainer = FNAbviewchartcontainer({ + ABViewComponentPlugin, + ABViewWidgetPlugin, + }); + const ABAbviewchartComponent = FNAbviewchartComponent({ ABViewComponentPlugin }); + + const ABViewChartPropertyComponentDefaults = { + dataviewID: "", + columnValue: "", + columnLabel: "", + columnValue2: "", + isPercentage: 1, + showLabel: 1, + labelPosition: "left", + labelWidth: 120, + height: 200, + multipleSeries: 0, + }; + + const ABViewChartDefaults = { + key: "chart", // {string} unique key for this view + icon: "bar-chart", // {string} fa-[icon] reference for this view + labelKey: "Chart", // {string} the multilingual label key for the class label + }; + + class ABViewChartCore extends ABViewChartContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues ?? ABViewChartDefaults); + } + + static common() { + return ABViewChartDefaults; + } + + static defaultValues() { + return ABViewChartPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.dataviewID = + this.settings.dataviewID ?? + ABViewChartPropertyComponentDefaults.dataviewID; + + this.settings.columnValue = + this.settings.columnValue ?? + ABViewChartPropertyComponentDefaults.columnValue; + + this.settings.columnLabel = + this.settings.columnLabel ?? + ABViewChartPropertyComponentDefaults.columnLabel; + + this.settings.columnValue2 = + this.settings.columnValue2 ?? + ABViewChartPropertyComponentDefaults.columnValue2; + + this.settings.isPercentage = parseInt( + this.settings.isPercentage ?? + ABViewChartPropertyComponentDefaults.isPercentage + ); + + this.settings.showLabel = parseInt( + this.settings.showLabel ?? + ABViewChartPropertyComponentDefaults.showLabel + ); + + this.settings.labelPosition = + this.settings.labelPosition || + ABViewChartPropertyComponentDefaults.labelPosition; + + this.settings.labelWidth = parseInt( + this.settings.labelWidth ?? + ABViewChartPropertyComponentDefaults.labelWidth + ); + + this.settings.height = parseInt( + this.settings.height ?? ABViewChartPropertyComponentDefaults.height + ); + + this.settings.multipleSeries = parseInt( + this.settings.multipleSeries ?? + ABViewChartPropertyComponentDefaults.multipleSeries + ); + + this.translate(this, this, ["chartLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + const viewsToAllow = ["label", "pie", "bar", "line", "area"]; + return this.application.viewAll((c) => { + return viewsToAllow.indexOf(c.common().key) > -1; + }); + } + + labelField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnLabel); + } + + valueField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue); + } + + valueField2() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue2); + } + }; + + return class ABViewChart extends ABViewChartCore { + + /** + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ + static getPluginKey() { + return this.common().key; + } + + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component() { + return new ABAbviewchartComponent(this); + } + + // constructor(values, application, parent, defaultValues) { + // super(values, application, parent, defaultValues); + // } + + /** + * @method component() + * return a UI component based upon this view. + * @param {obj} App + * @return {obj} UI component + */ + fromValues(values) { + super.fromValues(values); + this.refreshData(); + } + + getDCChart() { + if (!this._dcChart) this._dcChart = new webix.DataCollection(); + + return this._dcChart; + } + + refreshData() { + const dc = this.datacollection; + if (dc == null) return this.dcChart; + + const labelCol = this.labelField(); + const valueCol = this.valueField(); + const valueCol2 = this.valueField2(); + + if (!labelCol || !valueCol) return this.dcChart; + + // const labelColName = labelCol.columnName; + const numberColName = valueCol.columnName; + + let numberColName2 = ""; + + if (this.settings.multipleSeries && valueCol2) { + numberColName2 = valueCol2.columnName; + } + + const colorList = [ + "#ee4339", + "#ee9336", + "#eed236", + "#d3ee36", + "#a7ee70", + "#58dccd", + "#36abee", + "#476cee", + "#a244ea", + "#e33fc7", + ]; + + const dInfo = dc.getData(); + + let results = []; + let sumData = {}; + let sumNumber = 0; + let sumNumber2 = 0; + let countNumber = dInfo.length; + + dInfo.forEach((item) => { + const labelKey = labelCol.format(item) || item.id; + + let numberVal = parseFloat(item[numberColName] || 0); + let numberVal2 = null; + + if (this.settings.multipleSeries) + numberVal2 = parseFloat(item[numberColName2]) || 0; + + switch (valueCol.key) { + //Formula Datatype + case "formula": + numberVal = valueCol.format(item); + + break; + + //Calcualte Datatype + case "calculate": + numberVal = parseFloat( + valueCol.constructor.convertToJs( + valueCol.object, + valueCol.settings.formula, + item, + valueCol.settings.decimalPlaces + ) + ); + + break; + + default: + break; + } + + if (sumData[labelKey] == null) { + let label = labelKey; + + // Get label of the connect field + if (labelCol.isConnection) { + let relateValues = labelCol.pullRelationValues(item); + if (relateValues != null) { + if (Array.isArray(relateValues)) + label = relateValues + .map((val) => val.text || "") + .join(", "); + else label = relateValues.text; + } + } + + if (this.settings.multipleSeries) { + sumData[labelKey] = { + label: label || item.id, + value: 0, + value2: 0, + }; + } else { + sumData[labelKey] = { + label: label || item.id, + value: 0, + }; + } + } + + sumData[labelKey].value += numberVal; + sumNumber += numberVal; + + if (this.settings.multipleSeries) { + sumData[labelKey].value2 += numberVal2; + sumNumber2 += numberVal2; + } + }); + + let index = 0; + + for (const key in sumData) { + let val = sumData[key].value; + + if (val <= 0) continue; + + // Display to percent values + if (this.settings.isPercentage) { + val = (val / sumNumber) * 100; + val = Math.round(val * 100) / 100; // round decimal 2 digits + val = val + " %"; + } + + if (this.settings.multipleSeries) { + let val2 = sumData[key].value2; + + if (val2 <= 0) continue; + + // Display to percent values + if (this.settings.isPercentage) { + val2 = (val2 / sumNumber2) * 100; + val2 = Math.round(val2 * 100) / 100; // round decimal 2 digits + val2 = val2 + " %"; + } + + results.push({ + label: sumData[key].label, + value: val, + value2: val2, + color: colorList[index % colorList.length], + count: countNumber, + }); + } else { + results.push({ + label: sumData[key].label, + value: val, + color: colorList[index % colorList.length], + count: countNumber, + }); + } + + index += 1; + } + + const dcChart = this.getDCChart(); + + dcChart.clearAll(); + dcChart.parse(results); + } + + warningsEval() { + super.warningsEval(); + + let labelField = this.labelField(); + if (!labelField) { + this.warningsMessage( + `can't resolve label field[${this.settings.columnLabel}]` + ); + } + + let valueField = this.valueField(); + if (!valueField) { + this.warningsMessage( + `can't resolve value field[${this.settings.columnValue}]` + ); + } + } + }; +} + diff --git a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js new file mode 100644 index 00000000..2a2c6ecf --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js @@ -0,0 +1,71 @@ +import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; + +export default function FNAbviewchartComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + const ChartContainerComponent = FNAbviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class FNAbviewchartComponent extends ChartContainerComponent { + constructor(baseView, idBase, ids) { + super(baseView, idBase || `ABViewChart_${baseView.id}`, ids); + } + + async init(AB, accessLevel) { + await super.init(AB, accessLevel); + + const $component = $$(this.ids.component); + const abWebix = this.AB.Webix; + + if ($component) abWebix.extend($component, abWebix.ProgressBar); + + const baseView = this.view; + const dc = this.datacollection; + + if (dc) { + const eventNames = [ + "changeCursor", + "cursorStale", + "create", + "update", + "delete", + "initializedData", + ]; + + ["changeCursor", "cursorStale"].forEach((key) => { + // QUESTION: is this a problem if the check !(key in (...)) finds + // an event that some OTHER widget has added and not this one? + if ( + dc.datacollectionLink && + !(key in (dc.datacollectionLink._events ?? [])) + ) + baseView.eventAdd({ + emitter: dc.datacollectionLink, + eventName: key, + listener: () => { + baseView.refreshData(); + }, + }); + }); + + eventNames.forEach((evtName) => { + baseView.eventAdd({ + emitter: dc, + eventName: evtName, + listener: () => { + baseView.refreshData(); + }, + }); + }); + } + + baseView.refreshData(); + } + + onShow() { + super.onShow(); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js new file mode 100644 index 00000000..1d72b9b7 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js @@ -0,0 +1,33 @@ +import ABviewchartcontainerComponent from "./FNAbviewchartcontainerComponent.js"; + +// FNAbviewchartcontainer Web +// A web side import for an ABView. +// +export default function FNAbviewchartcontainer({ + /*AB,*/ + ABViewComponentPlugin, + ABViewWidgetPlugin, +}) { + const ABViewChartContainerComponent = ABviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class ABViewChartContainer extends ABViewWidgetPlugin { + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component() { + return new ABViewChartContainerComponent(this); + } + + get datacollection() { + return this.parent.datacollection; + } + + static getPluginType() { + return "view"; + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js new file mode 100644 index 00000000..56bdf321 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js @@ -0,0 +1,62 @@ +export default function FNAbviewchartcontainerComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + return class ABviewchartcontainerComponent extends ABViewComponentPlugin { + constructor(baseView, idBase, ids) { + super( + baseView, + idBase || `ABViewChartContainer_${baseView.id}`, + Object.assign( + { + chartContainer: "", + }, + ids + ) + ); + } + + ui(uiChartComponent) { + const _ui = super.ui([ + Object.assign( + { id: this.ids.chartContainer }, + uiChartComponent ?? {} + ), + ]); + + delete _ui.type; + + return _ui; + } + + async init(AB) { + await super.init(AB); + } + + onShow() { + super.onShow(); + // if (!this._isShow) { + + // Mark this widget is showing + const baseView = this.view; + + baseView._isShow = true; + + this.refreshData(baseView.settings.dataviewID); + // this.refreshData(baseView.parent.getDCChart()); + // } + } + + refreshData(dcChart) { + const $chartContainer = $$(this.ids.chartContainer); + const $chartComponent = $$(this.ids.component); + + if ($chartContainer?.data) $chartContainer.data.sync(dcChart); + + setTimeout(() => { + $chartComponent?.adjust(); + $chartContainer?.adjust(); + }, 160); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js new file mode 100644 index 00000000..daf11c3e --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js @@ -0,0 +1,137 @@ +import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; +import FNAbviewchartlineComponent from "./FNAbviewchartlineComponent.js"; + + +// FNAbviewchartline Web +// A web side import for an ABView. +// +export default function FNAbviewchartline({ + /*AB,*/ + ABViewPlugin, + ABViewComponentPlugin, + ABViewContainer, + ABViewWidgetPlugin +}) { + const ABViewChartContainer = FNAbviewchartcontainer({ + ABViewComponentPlugin, + ABViewWidgetPlugin, + }); + const ABAbviewchartlineComponent = FNAbviewchartlineComponent({ ABViewComponentPlugin }); + + const ABViewChartLinePropertyComponentDefaults = { + lineType: "line", + linePreset: "plot", + isLegend: 1, + // chartWidth: 600, + chartHeight: 200, + labelFontSize: 12, + stepValue: 20, + maxValue: 100, + }; + + const ABViewDefaults = { + key: "line", // {string} unique key for this view + icon: "line-chart", // {string} fa-[icon] reference for this view + labelKey: "Line", // {string} the multilingual label key for the class label + }; + + class ABViewChartLineCore extends ABViewChartContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewDefaults); + } + + static common() { + return ABViewDefaults; + } + + static defaultValues() { + return ABViewChartLinePropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.lineType = + this.settings.lineType || + ABViewChartLinePropertyComponentDefaults.lineType; + + this.settings.linePreset = + this.settings.linePreset || + ABViewChartLinePropertyComponentDefaults.linePreset; + + this.settings.isLegend = parseInt( + this.settings.isLegend ?? + ABViewChartLinePropertyComponentDefaults.isLegend + ); + + // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartLinePropertyComponentDefaults.chartWidth); + this.settings.chartHeight = parseInt( + this.settings.chartHeight ?? + ABViewChartLinePropertyComponentDefaults.chartHeight + ); + + this.settings.labelFontSize = parseInt( + this.settings.labelFontSize ?? + ABViewChartLinePropertyComponentDefaults.labelFontSize + ); + this.settings.stepValue = parseInt( + this.settings.stepValue ?? + ABViewChartLinePropertyComponentDefaults.stepValue + ); + this.settings.maxValue = parseInt( + this.settings.maxValue ?? + ABViewChartLinePropertyComponentDefaults.maxValue + ); + + this.translate(this, this, ["lineLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + return []; + } + }; + + return class ABViewChartLine extends ABViewChartLineCore { + + /** + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ + static getPluginKey() { + return this.common().key; + } + + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component(parentId) { + return new ABAbviewchartlineComponent(this, parentId); + } + + + // constructor(values, application, parent, defaultValues) { + // super(values, application, parent, defaultValues); + // } + + + }; + +} + diff --git a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js new file mode 100644 index 00000000..7617ec17 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js @@ -0,0 +1,46 @@ +import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; + +export default function FNAbviewchartlineComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + const ChartContainerComponent = FNAbviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class FNAbviewchartlineComponent extends ChartContainerComponent { + constructor(baseView, idBase, ids) { + super(baseView, idBase || `ABViewChartLine_${baseView.id}`, ids); + } + + ui() { + const settings = this.settings; + + return super.ui({ + view: "chart", + type: settings.lineType, + preset: settings.linePreset, + value: "#value#", + color: "#color#", + yAxis: { + start: 0, + step: settings.stepValue, + end: settings.maxValue, //"#maxValue#" + }, + xAxis: { + template: settings.isLegend + ? `
#label#
` + : "", + }, + legend: settings.isLegend + ? { + template: `
#label#
`, + values: [], // TODO : bug in webix 5.1.7 + } + : null, + height: settings.chartHeight, + // width: settings.chartWidth, + }); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js new file mode 100644 index 00000000..733ee8a6 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js @@ -0,0 +1,125 @@ +import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; +import FNAbviewchartpieComponent from "./FNAbviewchartpieComponent.js"; + +// FNAbviewchartpie Web +// A web side import for an ABView. +// +export default function FNAbviewchartpie({ + /*AB,*/ + ABViewPlugin, + ABViewComponentPlugin, + ABViewContainer, + ABViewWidgetPlugin +}) { + const ABViewChartContainer = FNAbviewchartcontainer({ + ABViewComponentPlugin, + ABViewWidgetPlugin, + }); + const ABAbviewchartpieComponent = FNAbviewchartpieComponent({ ABViewComponentPlugin }); + + const ABViewChartPiePropertyComponentDefaults = { + pieType: "pie", + isLegend: 1, + // chartWidth: 600, + height: 200, + innerFontSize: 12, + labelFontSize: 12, + }; + + const ABViewDefaults = { + key: "pie", // {string} unique key for this view + icon: "pie-chart", // {string} fa-[icon] reference for this view + labelKey: "Pie", // {string} the multilingual label key for the class label + }; + + class ABViewChartPieCore extends ABViewChartContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewDefaults); + } + + static common() { + return ABViewDefaults; + } + + static defaultValues() { + return ABViewChartPiePropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.pieType = + this.settings.pieType || + ABViewChartPiePropertyComponentDefaults.pieType; + + this.settings.isLegend = parseInt( + this.settings.isLegend ?? + ABViewChartPiePropertyComponentDefaults.isLegend + ); + + // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartPiePropertyComponentDefaults.chartWidth); + this.settings.height = parseInt( + this.settings.height ?? ABViewChartPiePropertyComponentDefaults.height + ); + + this.settings.innerFontSize = parseInt( + this.settings.innerFontSize ?? + ABViewChartPiePropertyComponentDefaults.innerFontSize + ); + this.settings.labelFontSize = parseInt( + this.settings.labelFontSize ?? + ABViewChartPiePropertyComponentDefaults.labelFontSize + ); + + this.translate(this, this, ["pieLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + return []; + } + }; + + return class ABViewChartPie extends ABViewChartPieCore { + + /** + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ + static getPluginKey() { + return this.common().key; + } + + /** + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component(parentId) { + return new ABAbviewchartpieComponent(this, parentId); + } + + + // constructor(values, application, parent, defaultValues) { + // super(values, application, parent, defaultValues); + // } + + + }; + +} + diff --git a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js new file mode 100644 index 00000000..ee2d99d8 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js @@ -0,0 +1,37 @@ +import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; + +export default function FNAbviewchartpieComponent({ + /*AB,*/ + ABViewComponentPlugin, +}) { + const ChartContainerComponent = FNAbviewchartcontainerComponent({ + ABViewComponentPlugin, + }); + + return class FNAbviewchartpieComponent extends ChartContainerComponent { + constructor(baseView, idBase, ids) { + super(baseView, idBase || `ABViewChartPie_${baseView.id}`, ids); + } + + ui() { + const settings = this.settings; + + return super.ui({ + view: "chart", + type: settings.pieType, + value: "#value#", + color: "#color#", + legend: settings.isLegend + ? { + width: this.view.parent.settings.labelWidth, + template: `
#label#
`, + } + : null, + pieInnerText: `
#value#
`, + shadow: 1, + height: settings.height, + // width: settings.chartWidth, + }); + } + }; +} diff --git a/AppBuilder/platform/views/ABViewChartContainer.js b/AppBuilder/platform/views/ABViewChartContainer.js deleted file mode 100644 index bc7a625b..00000000 --- a/AppBuilder/platform/views/ABViewChartContainer.js +++ /dev/null @@ -1,17 +0,0 @@ -const ABViewWidget = require("./ABViewWidget"); -const ABViewChartContainerComponent = require("./viewComponent/ABViewChartContainerComponent"); - -module.exports = class ABViewChartContainer extends ABViewWidget { - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartContainerComponent(this); - } - - get datacollection() { - return this.parent.datacollection; - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartContainerComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartContainerComponent.js deleted file mode 100644 index 4f23324e..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartContainerComponent.js +++ /dev/null @@ -1,55 +0,0 @@ -const ABViewComponent = require("./ABViewComponent").default; - -module.exports = class ABViewChartContainerComponent extends ABViewComponent { - constructor(baseView, idBase, ids) { - super( - baseView, - idBase || `ABViewChartContainer_${baseView.id}`, - Object.assign( - { - chartContainer: "", - }, - ids - ) - ); - } - - ui(uiChartComponent) { - const _ui = super.ui([ - Object.assign({ id: this.ids.chartContainer }, uiChartComponent ?? {}), - ]); - - delete _ui.type; - - return _ui; - } - - async init(AB) { - await super.init(AB); - } - - onShow() { - super.onShow(); - // if (!this._isShow) { - - // Mark this widget is showing - const baseView = this.view; - - baseView._isShow = true; - - this.refreshData(baseView.parent.getDCChart()); - // } - } - - refreshData(dcChart) { - const $chartContainer = $$(this.ids.chartContainer); - const $chartComponent = $$(this.ids.component); - - if ($chartContainer?.data) $chartContainer.data.sync(dcChart); - - setTimeout(() => { - $chartComponent?.adjust(); - $chartContainer?.adjust(); - }, 160); - } -}; From cb47a30cff3ebac226f5d4b81f275043c9347b88 Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Tue, 7 Apr 2026 20:49:03 +0700 Subject: [PATCH 3/8] Move files --- AppBuilder/platform/plugins/included/index.js | 16 +- .../included/view_chart/ABViewChartCore.js | 465 +++++++++++++----- .../view_chart/area/FNAbviewchartarea.js | 19 +- .../area/FNAbviewchartareaComponent.js | 2 +- .../view_chart/bar/FNAbviewchartbar.js | 43 +- .../bar/FNAbviewchartbarComponent.js | 2 +- .../view_chart/chart/FNAbviewchart.js | 190 +------ .../chart/FNAbviewchartComponent.js | 38 +- .../included/view_chart/chartBindings.js | 3 + .../container/FNAbviewchartcontainer.js | 8 - .../FNAbviewchartcontainerComponent.js | 34 +- .../view_chart/line/FNAbviewchartline.js | 41 +- .../line/FNAbviewchartlineComponent.js | 2 +- .../view_chart/pie/FNAbviewchartpie.js | 42 +- .../pie/FNAbviewchartpieComponent.js | 2 +- AppBuilder/platform/views/ABViewChart.js | 214 -------- AppBuilder/platform/views/ABViewChartArea.js | 17 - AppBuilder/platform/views/ABViewChartBar.js | 17 - AppBuilder/platform/views/ABViewChartLine.js | 17 - AppBuilder/platform/views/ABViewChartPie.js | 17 - .../viewComponent/ABViewChartAreaComponent.js | 56 --- .../viewComponent/ABViewChartBarComponent.js | 52 -- .../viewComponent/ABViewChartComponent.js | 62 --- .../viewComponent/ABViewChartLineComponent.js | 39 -- .../viewComponent/ABViewChartPieComponent.js | 30 -- test/_setup.js | 9 +- 26 files changed, 480 insertions(+), 957 deletions(-) create mode 100644 AppBuilder/platform/plugins/included/view_chart/chartBindings.js delete mode 100644 AppBuilder/platform/views/ABViewChart.js delete mode 100644 AppBuilder/platform/views/ABViewChartArea.js delete mode 100644 AppBuilder/platform/views/ABViewChartBar.js delete mode 100644 AppBuilder/platform/views/ABViewChartLine.js delete mode 100644 AppBuilder/platform/views/ABViewChartPie.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartAreaComponent.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartBarComponent.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartComponent.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartLineComponent.js delete mode 100644 AppBuilder/platform/views/viewComponent/ABViewChartPieComponent.js diff --git a/AppBuilder/platform/plugins/included/index.js b/AppBuilder/platform/plugins/included/index.js index 08a8274f..7d5174dc 100644 --- a/AppBuilder/platform/plugins/included/index.js +++ b/AppBuilder/platform/plugins/included/index.js @@ -1,7 +1,9 @@ -import viewArea from "./view_chart/area/FNAbviewchartarea.js"; -import viewBar from "./view_chart/bar/FNAbviewchartbar.js"; import viewCarousel from "./view_carousel/FNAbviewcarousel.js"; import viewChart from "./view_chart/chart/FNAbviewchart.js"; +import viewChartArea from "./view_chart/area/FNAbviewchartarea.js"; +import viewChartBar from "./view_chart/bar/FNAbviewchartbar.js"; +import viewChartLine from "./view_chart/line/FNAbviewchartline.js"; +import viewChartPie from "./view_chart/pie/FNAbviewchartpie.js"; import viewComment from "./view_comment/FNAbviewcomment.js"; import viewCsvExporter from "./view_csvExporter/FNAbviewcsvexporter.js"; import viewCsvImporter from "./view_csvImporter/FNAbviewcsvimporter.js"; @@ -13,18 +15,18 @@ import viewImage from "./view_image/FNAbviewimage.js"; import viewKanban from "./view_kanban/FNABViewKanban.js"; import viewLabel from "./view_label/FNAbviewlabel.js"; import viewLayout from "./view_layout/FNAbviewlayout.js"; -import viewLine from "./view_chart/line/FNAbviewchartline.js"; import viewList from "./view_list/FNAbviewlist.js"; import viewPdfImporter from "./view_pdfImporter/FNAbviewpdfimporter.js"; -import viewPie from "./view_chart/pie/FNAbviewchartpie.js"; import viewTab from "./view_tab/FNAbviewtab.js"; import viewText from "./view_text/FNAbviewtext.js"; const AllPlugins = [ - viewArea, - viewBar, viewCarousel, viewChart, + viewChartArea, + viewChartBar, + viewChartLine, + viewChartPie, viewComment, viewCsvExporter, viewCsvImporter, @@ -36,10 +38,8 @@ const AllPlugins = [ viewKanban, viewLabel, viewLayout, - viewLine, viewList, viewPdfImporter, - viewPie, viewTab, viewText, ]; diff --git a/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js b/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js index 5d714453..f2f9ea6e 100644 --- a/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js +++ b/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js @@ -1,135 +1,330 @@ -const ABViewContainer = require("../../platform/views/ABViewContainer"); - -const ABViewChartPropertyComponentDefaults = { - dataviewID: "", - columnValue: "", - columnLabel: "", - columnValue2: "", - isPercentage: 1, - showLabel: 1, - labelPosition: "left", - labelWidth: 120, - height: 200, - multipleSeries: 0, -}; - -const ABViewChartDefaults = { - key: "chart", // {string} unique key for this view - icon: "bar-chart", // {string} fa-[icon] reference for this view - labelKey: "Chart", // {string} the multilingual label key for the class label -}; - -module.exports = class ABViewChartCore extends ABViewContainer { - constructor(values, application, parent, defaultValues) { - super(values, application, parent, defaultValues || ABViewChartDefaults); - } - - static common() { - return ABViewChartDefaults; - } - - static defaultValues() { - return ABViewChartPropertyComponentDefaults; - } - - /// - /// Instance Methods - /// - - /** - * @method fromValues() - * - * initialze this object with the given set of values. - * @param {obj} values - */ - fromValues(values) { - super.fromValues(values); - - this.settings.dataviewID = - this.settings.dataviewID ?? - ABViewChartPropertyComponentDefaults.dataviewID; - - this.settings.columnValue = - this.settings.columnValue ?? - ABViewChartPropertyComponentDefaults.columnValue; - - this.settings.columnLabel = - this.settings.columnLabel ?? - ABViewChartPropertyComponentDefaults.columnLabel; - - this.settings.columnValue2 = - this.settings.columnValue2 ?? - ABViewChartPropertyComponentDefaults.columnValue2; - - this.settings.isPercentage = parseInt( - this.settings.isPercentage ?? - ABViewChartPropertyComponentDefaults.isPercentage - ); - - this.settings.showLabel = parseInt( - this.settings.showLabel ?? - ABViewChartPropertyComponentDefaults.showLabel - ); - - this.settings.labelPosition = - this.settings.labelPosition || - ABViewChartPropertyComponentDefaults.labelPosition; - - this.settings.labelWidth = parseInt( - this.settings.labelWidth ?? - ABViewChartPropertyComponentDefaults.labelWidth - ); - - this.settings.height = parseInt( - this.settings.height ?? ABViewChartPropertyComponentDefaults.height - ); - - this.settings.multipleSeries = parseInt( - this.settings.multipleSeries ?? - ABViewChartPropertyComponentDefaults.multipleSeries - ); - - this.translate(this, this, ["chartLabel"]); - } - - /** - * @method componentList - * return the list of components available on this view to display in the editor. - */ - componentList() { - const viewsToAllow = ["label", "pie", "bar", "line", "area"]; - return this.application.viewAll((c) => { - return viewsToAllow.indexOf(c.common().key) > -1; - }); - } - - labelField() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnLabel); - } - - valueField() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnValue); - } - - valueField2() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnValue2); - } -}; +export default function FNABViewChartCore({ ABViewWidgetPlugin }) { + const ABViewChartPropertyComponentDefaults = { + dataviewID: "", + columnValue: "", + columnLabel: "", + columnValue2: "", + isPercentage: 1, + showLabel: 1, + labelPosition: "left", + labelWidth: 120, + height: 200, + multipleSeries: 0, + }; + + const ABViewChartDefaults = { + key: "chart", // {string} unique key for this view + icon: "bar-chart", // {string} fa-[icon] reference for this view + labelKey: "Chart", // {string} the multilingual label key for the class label + }; + + return class ABViewChartCore extends ABViewWidgetPlugin { + constructor(values, application, parent, defaultValues) { + super( + values, + application, + parent, + defaultValues || ABViewChartDefaults + ); + } + + get datacollection() { + return this.parent.datacollection; + } + + static getPluginType() { + return "view"; + } + + static common() { + return ABViewChartDefaults; + } + + static defaultValues() { + return ABViewChartPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.dataviewID = + this.settings.dataviewID ?? + ABViewChartPropertyComponentDefaults.dataviewID; + + this.settings.columnValue = + this.settings.columnValue ?? + ABViewChartPropertyComponentDefaults.columnValue; + + this.settings.columnLabel = + this.settings.columnLabel ?? + ABViewChartPropertyComponentDefaults.columnLabel; + + this.settings.columnValue2 = + this.settings.columnValue2 ?? + ABViewChartPropertyComponentDefaults.columnValue2; + + this.settings.isPercentage = parseInt( + this.settings.isPercentage ?? + ABViewChartPropertyComponentDefaults.isPercentage + ); + + this.settings.showLabel = parseInt( + this.settings.showLabel ?? + ABViewChartPropertyComponentDefaults.showLabel + ); + + this.settings.labelPosition = + this.settings.labelPosition || + ABViewChartPropertyComponentDefaults.labelPosition; + + this.settings.labelWidth = parseInt( + this.settings.labelWidth ?? + ABViewChartPropertyComponentDefaults.labelWidth + ); + + this.settings.height = parseInt( + this.settings.height ?? ABViewChartPropertyComponentDefaults.height + ); + + this.settings.multipleSeries = parseInt( + this.settings.multipleSeries ?? + ABViewChartPropertyComponentDefaults.multipleSeries + ); + + this.translate(this, this, ["chartLabel"]); + + this.refreshData(); + } + + getDCChart() { + if (!this._dcChart) this._dcChart = new webix.DataCollection(); + + return this._dcChart; + } + + refreshData() { + const dc = this.datacollection; + if (dc == null) return this.getDCChart(); + + const labelCol = this.labelField(); + const valueCol = this.valueField(); + const valueCol2 = this.valueField2(); + + if (!labelCol || !valueCol) return this.getDCChart(); + + const numberColName = valueCol.columnName; + + let numberColName2 = ""; + + if (this.settings.multipleSeries && valueCol2) { + numberColName2 = valueCol2.columnName; + } + + const colorList = [ + "#ee4339", + "#ee9336", + "#eed236", + "#d3ee36", + "#a7ee70", + "#58dccd", + "#36abee", + "#476cee", + "#a244ea", + "#e33fc7", + ]; + + const dInfo = dc.getData(); + + let results = []; + let sumData = {}; + let sumNumber = 0; + let sumNumber2 = 0; + let countNumber = dInfo.length; + + dInfo.forEach((item) => { + const labelKey = labelCol.format(item) || item.id; + + let numberVal = parseFloat(item[numberColName] || 0); + let numberVal2 = null; + + if (this.settings.multipleSeries) + numberVal2 = parseFloat(item[numberColName2]) || 0; + + switch (valueCol.key) { + case "formula": + numberVal = valueCol.format(item); + + break; + + case "calculate": + numberVal = parseFloat( + valueCol.constructor.convertToJs( + valueCol.object, + valueCol.settings.formula, + item, + valueCol.settings.decimalPlaces + ) + ); + + break; + + default: + break; + } + + if (sumData[labelKey] == null) { + let label = labelKey; + + if (labelCol.isConnection) { + let relateValues = labelCol.pullRelationValues(item); + if (relateValues != null) { + if (Array.isArray(relateValues)) + label = relateValues + .map((val) => val.text || "") + .join(", "); + else label = relateValues.text; + } + } + + if (this.settings.multipleSeries) { + sumData[labelKey] = { + label: label || item.id, + value: 0, + value2: 0, + }; + } else { + sumData[labelKey] = { + label: label || item.id, + value: 0, + }; + } + } + + sumData[labelKey].value += numberVal; + sumNumber += numberVal; + + if (this.settings.multipleSeries) { + sumData[labelKey].value2 += numberVal2; + sumNumber2 += numberVal2; + } + }); + + let index = 0; + + for (const key in sumData) { + let val = sumData[key].value; + + if (val <= 0) continue; + + if (this.settings.isPercentage) { + val = (val / sumNumber) * 100; + val = Math.round(val * 100) / 100; + val = val + " %"; + } + + if (this.settings.multipleSeries) { + let val2 = sumData[key].value2; + + if (val2 <= 0) continue; + + if (this.settings.isPercentage) { + val2 = (val2 / sumNumber2) * 100; + val2 = Math.round(val2 * 100) / 100; + val2 = val2 + " %"; + } + + results.push({ + label: sumData[key].label, + value: val, + value2: val2, + color: colorList[index % colorList.length], + count: countNumber, + }); + } else { + results.push({ + label: sumData[key].label, + value: val, + color: colorList[index % colorList.length], + count: countNumber, + }); + } + + index += 1; + } + + const dcChart = this.getDCChart(); + + dcChart.clearAll(); + dcChart.parse(results); + } + + warningsEval() { + super.warningsEval(); + + let labelField = this.labelField(); + if (!labelField) { + this.warningsMessage( + `can't resolve label field[${this.settings.columnLabel}]` + ); + } + + let valueField = this.valueField(); + if (!valueField) { + this.warningsMessage( + `can't resolve value field[${this.settings.columnValue}]` + ); + } + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + const viewsToAllow = ["label", "pie", "bar", "line", "area"]; + return this.application.viewAll((c) => { + return viewsToAllow.indexOf(c.common().key) > -1; + }); + } + + labelField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnLabel); + } + + valueField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue); + } + + valueField2() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue2); + } + }; +} diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js index aef5eeda..a7e0b547 100644 --- a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js @@ -1,29 +1,26 @@ import FNAbviewchartareaComponent from "./FNAbviewchartareaComponent.js"; -import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; +import { FNABViewChartCore } from "../chartBindings.js"; // FNAbviewchartarea Web // A web side import for an ABView. // export default function FNAbviewchartarea({ - /*AB,*/ + AB, ABViewPlugin, ABViewComponentPlugin, ABViewContainer, ABViewWidgetPlugin, }) { - const ABViewChartContainer = FNAbviewchartcontainer({ - ABViewComponentPlugin, - ABViewWidgetPlugin, - }); - + const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); const ABAbviewchartareaComponent = FNAbviewchartareaComponent({ + AB, ABViewComponentPlugin, }); const ABViewChartAreaPropertyComponentDefaults = { areaType: "area", isLegend: 1, - // chartWidth: 600, + chartWidth: 600, chartHeight: 200, labelFontSize: 12, stepValue: 20, @@ -36,7 +33,7 @@ export default function FNAbviewchartarea({ labelKey: "Area", // {string} the multilingual label key for the class label }; - class ABViewChartAreaCore extends ABViewChartContainer { + class ABViewChartAreaCore extends ABViewChartCore { constructor(values, application, parent, defaultValues) { super(values, application, parent, defaultValues || ABViewDefaults); } @@ -117,8 +114,8 @@ export default function FNAbviewchartarea({ * return a UI component based upon this view. * @return {obj} UI component */ - component(parentId) { - return new ABAbviewchartareaComponent(this, parentId); + component() { + return new ABAbviewchartareaComponent(this); } // constructor(values, application, parent, defaultValues) { diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js index d7bc0d0a..70e354a7 100644 --- a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js @@ -1,4 +1,4 @@ -import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; +import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; export default function FNAbviewchartareaComponent({ /*AB,*/ diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js index b5b5f4bc..657814ae 100644 --- a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js @@ -1,6 +1,5 @@ import FNAbviewchartbarComponent from "./FNAbviewchartbarComponent.js"; -import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; - +import { FNABViewChartCore } from "../chartBindings.js"; // FNAbviewchartbar Web // A web side import for an ABView. @@ -10,13 +9,12 @@ export default function FNAbviewchartbar({ ABViewPlugin, ABViewComponentPlugin, ABViewContainer, - ABViewWidgetPlugin + ABViewWidgetPlugin, }) { - const ABViewChartContainer = FNAbviewchartcontainer({ + const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); + const ABAbviewchartbarComponent = FNAbviewchartbarComponent({ ABViewComponentPlugin, - ABViewWidgetPlugin, }); - const ABAbviewchartbarComponent = FNAbviewchartbarComponent({ ABViewComponentPlugin }); const ABViewChartBarPropertyComponentDefaults = { barType: "bar", @@ -35,7 +33,7 @@ export default function FNAbviewchartbar({ labelKey: "Bar", // {string} the multilingual label key for the class label }; - class ABViewChartBarCore extends ABViewChartContainer { + class ABViewChartBarCore extends ABViewChartCore { constructor(values, application, parent, defaultValues) { super(values, application, parent, defaultValues || ABViewDefaults); } @@ -76,7 +74,8 @@ export default function FNAbviewchartbar({ // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartBarPropertyComponentDefaults.chartWidth); this.settings.height = parseInt( - this.settings.height ?? ABViewChartBarPropertyComponentDefaults.height + this.settings.height ?? + ABViewChartBarPropertyComponentDefaults.height ); this.settings.labelFontSize = parseInt( @@ -102,35 +101,29 @@ export default function FNAbviewchartbar({ componentList() { return []; } - }; + } return class ABViewChartBar extends ABViewChartBarCore { - /** - * @method getPluginKey - * return the plugin key for this view. - * @return {string} plugin key - */ + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ static getPluginKey() { return this.common().key; } /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component(parentId) { - return new ABAbviewchartbarComponent(this, parentId); + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component() { + return new ABAbviewchartbarComponent(this); } - // constructor(values, application, parent, defaultValues) { // super(values, application, parent, defaultValues); // } - - }; - } - diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js index 8e8402e8..f8451d99 100644 --- a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js @@ -1,4 +1,4 @@ -import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; +import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; export default function FNAbviewchartbarComponent({ /*AB,*/ diff --git a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js index f5fcdb63..e1c23fce 100644 --- a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js +++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js @@ -1,159 +1,16 @@ +import ABViewChartCore from "../../../../../core/views/ABViewChartCore.js"; import FNAbviewchartComponent from "./FNAbviewchartComponent.js"; -import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; - // FNAbviewchart Web // A web side import for an ABView. // -export default function FNAbviewchart({ - /*AB,*/ - ABViewPlugin, - ABViewComponentPlugin, - ABViewContainer, - ABViewWidgetPlugin -}) { - const ABViewChartContainer = FNAbviewchartcontainer({ - ABViewComponentPlugin, - ABViewWidgetPlugin, +export default function FNAbviewchart({ AB, ABViewContainerComponent }) { + const ABAbviewchartComponent = FNAbviewchartComponent({ + AB, + ABViewContainerComponent, }); - const ABAbviewchartComponent = FNAbviewchartComponent({ ABViewComponentPlugin }); - - const ABViewChartPropertyComponentDefaults = { - dataviewID: "", - columnValue: "", - columnLabel: "", - columnValue2: "", - isPercentage: 1, - showLabel: 1, - labelPosition: "left", - labelWidth: 120, - height: 200, - multipleSeries: 0, - }; - - const ABViewChartDefaults = { - key: "chart", // {string} unique key for this view - icon: "bar-chart", // {string} fa-[icon] reference for this view - labelKey: "Chart", // {string} the multilingual label key for the class label - }; - - class ABViewChartCore extends ABViewChartContainer { - constructor(values, application, parent, defaultValues) { - super(values, application, parent, defaultValues ?? ABViewChartDefaults); - } - - static common() { - return ABViewChartDefaults; - } - - static defaultValues() { - return ABViewChartPropertyComponentDefaults; - } - - /// - /// Instance Methods - /// - - /** - * @method fromValues() - * - * initialze this object with the given set of values. - * @param {obj} values - */ - fromValues(values) { - super.fromValues(values); - - this.settings.dataviewID = - this.settings.dataviewID ?? - ABViewChartPropertyComponentDefaults.dataviewID; - - this.settings.columnValue = - this.settings.columnValue ?? - ABViewChartPropertyComponentDefaults.columnValue; - - this.settings.columnLabel = - this.settings.columnLabel ?? - ABViewChartPropertyComponentDefaults.columnLabel; - - this.settings.columnValue2 = - this.settings.columnValue2 ?? - ABViewChartPropertyComponentDefaults.columnValue2; - - this.settings.isPercentage = parseInt( - this.settings.isPercentage ?? - ABViewChartPropertyComponentDefaults.isPercentage - ); - - this.settings.showLabel = parseInt( - this.settings.showLabel ?? - ABViewChartPropertyComponentDefaults.showLabel - ); - - this.settings.labelPosition = - this.settings.labelPosition || - ABViewChartPropertyComponentDefaults.labelPosition; - - this.settings.labelWidth = parseInt( - this.settings.labelWidth ?? - ABViewChartPropertyComponentDefaults.labelWidth - ); - - this.settings.height = parseInt( - this.settings.height ?? ABViewChartPropertyComponentDefaults.height - ); - - this.settings.multipleSeries = parseInt( - this.settings.multipleSeries ?? - ABViewChartPropertyComponentDefaults.multipleSeries - ); - - this.translate(this, this, ["chartLabel"]); - } - - /** - * @method componentList - * return the list of components available on this view to display in the editor. - */ - componentList() { - const viewsToAllow = ["label", "pie", "bar", "line", "area"]; - return this.application.viewAll((c) => { - return viewsToAllow.indexOf(c.common().key) > -1; - }); - } - - labelField() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnLabel); - } - - valueField() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnValue); - } - - valueField2() { - const dc = this.datacollection; - if (!dc) return null; - - const obj = dc.datasource; - if (!obj) return null; - - return obj.fieldByID(this.settings.columnValue2); - } - }; return class ABViewChart extends ABViewChartCore { - /** * @method getPluginKey * return the plugin key for this view. @@ -163,25 +20,19 @@ export default function FNAbviewchart({ return this.common().key; } - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABAbviewchartComponent(this); + static getPluginType() { + return "view"; } - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - /** * @method component() * return a UI component based upon this view. - * @param {obj} App * @return {obj} UI component */ + component(parentId) { + return new ABAbviewchartComponent(this, parentId); + } + fromValues(values) { super.fromValues(values); this.refreshData(); @@ -195,15 +46,18 @@ export default function FNAbviewchart({ refreshData() { const dc = this.datacollection; - if (dc == null) return this.dcChart; + if (dc == null) { + return this.getDCChart(); + } const labelCol = this.labelField(); const valueCol = this.valueField(); const valueCol2 = this.valueField2(); - if (!labelCol || !valueCol) return this.dcChart; + if (!labelCol || !valueCol) { + return this.getDCChart(); + } - // const labelColName = labelCol.columnName; const numberColName = valueCol.columnName; let numberColName2 = ""; @@ -243,13 +97,11 @@ export default function FNAbviewchart({ numberVal2 = parseFloat(item[numberColName2]) || 0; switch (valueCol.key) { - //Formula Datatype case "formula": numberVal = valueCol.format(item); break; - //Calcualte Datatype case "calculate": numberVal = parseFloat( valueCol.constructor.convertToJs( @@ -269,7 +121,6 @@ export default function FNAbviewchart({ if (sumData[labelKey] == null) { let label = labelKey; - // Get label of the connect field if (labelCol.isConnection) { let relateValues = labelCol.pullRelationValues(item); if (relateValues != null) { @@ -311,10 +162,9 @@ export default function FNAbviewchart({ if (val <= 0) continue; - // Display to percent values if (this.settings.isPercentage) { val = (val / sumNumber) * 100; - val = Math.round(val * 100) / 100; // round decimal 2 digits + val = Math.round(val * 100) / 100; val = val + " %"; } @@ -323,10 +173,9 @@ export default function FNAbviewchart({ if (val2 <= 0) continue; - // Display to percent values if (this.settings.isPercentage) { val2 = (val2 / sumNumber2) * 100; - val2 = Math.round(val2 * 100) / 100; // round decimal 2 digits + val2 = Math.round(val2 * 100) / 100; val2 = val2 + " %"; } @@ -374,4 +223,3 @@ export default function FNAbviewchart({ } }; } - diff --git a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js index 2a2c6ecf..2ba26898 100644 --- a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js @@ -1,28 +1,38 @@ -import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; - export default function FNAbviewchartComponent({ - /*AB,*/ - ABViewComponentPlugin, + AB, + ABViewContainerComponent, }) { - const ChartContainerComponent = FNAbviewchartcontainerComponent({ - ABViewComponentPlugin, - }); - - return class FNAbviewchartComponent extends ChartContainerComponent { + return class FNAbviewchartComponent extends ABViewContainerComponent { constructor(baseView, idBase, ids) { super(baseView, idBase || `ABViewChart_${baseView.id}`, ids); } - async init(AB, accessLevel) { - await super.init(AB, accessLevel); + async init(ABParam, accessLevel) { + await super.init(ABParam, accessLevel); const $component = $$(this.ids.component); - const abWebix = this.AB.Webix; + const abWebix = AB.Webix; if ($component) abWebix.extend($component, abWebix.ProgressBar); const baseView = this.view; - const dc = this.datacollection; + const dc = baseView.datacollections || baseView.datacollection; + + const ensureDcLoaded = async (d) => { + if (!d || typeof d.init !== "function") return; + d.init(); + if (d.dataStatus === d.dataStatusFlag.notInitial) { + await d.loadData(); + } + }; + + if (Array.isArray(dc)) { + for (const d of dc) { + await ensureDcLoaded(d); + } + } else if (dc) { + await ensureDcLoaded(dc); + } if (dc) { const eventNames = [ @@ -35,8 +45,6 @@ export default function FNAbviewchartComponent({ ]; ["changeCursor", "cursorStale"].forEach((key) => { - // QUESTION: is this a problem if the check !(key in (...)) finds - // an event that some OTHER widget has added and not this one? if ( dc.datacollectionLink && !(key in (dc.datacollectionLink._events ?? [])) diff --git a/AppBuilder/platform/plugins/included/view_chart/chartBindings.js b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js new file mode 100644 index 00000000..5a730954 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js @@ -0,0 +1,3 @@ +export { default as FNABViewChartCore } from "./ABViewChartCore.js"; +export { default as FNAbviewchartcontainer } from "./container/FNAbviewchartcontainer.js"; +export { default as FNAbviewchartcontainerComponent } from "./container/FNAbviewchartcontainerComponent.js"; diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js index 1d72b9b7..ab56f180 100644 --- a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js +++ b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js @@ -1,10 +1,6 @@ import ABviewchartcontainerComponent from "./FNAbviewchartcontainerComponent.js"; -// FNAbviewchartcontainer Web -// A web side import for an ABView. -// export default function FNAbviewchartcontainer({ - /*AB,*/ ABViewComponentPlugin, ABViewWidgetPlugin, }) { @@ -25,9 +21,5 @@ export default function FNAbviewchartcontainer({ get datacollection() { return this.parent.datacollection; } - - static getPluginType() { - return "view"; - } }; } diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js index 56bdf321..acfce236 100644 --- a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js @@ -1,5 +1,13 @@ +function findAncestorWithGetDCChart(view) { + let cur = view && view.parent; + while (cur) { + if (typeof cur.getDCChart === "function") return cur; + cur = cur.parent; + } + return null; +} + export default function FNAbviewchartcontainerComponent({ - /*AB,*/ ABViewComponentPlugin, }) { return class ABviewchartcontainerComponent extends ABViewComponentPlugin { @@ -35,23 +43,33 @@ export default function FNAbviewchartcontainerComponent({ onShow() { super.onShow(); - // if (!this._isShow) { - - // Mark this widget is showing const baseView = this.view; baseView._isShow = true; - this.refreshData(baseView.settings.dataviewID); - // this.refreshData(baseView.parent.getDCChart()); - // } + const chartAncestor = findAncestorWithGetDCChart(baseView); + let dcChart = null; + if (chartAncestor) { + if (typeof chartAncestor.refreshData === "function") { + chartAncestor.refreshData(); + } + dcChart = chartAncestor.getDCChart(); + } else if (typeof baseView.getDCChart === "function") { + if (typeof baseView.refreshData === "function") { + baseView.refreshData(); + } + dcChart = baseView.getDCChart(); + } + this.refreshData(dcChart); } refreshData(dcChart) { const $chartContainer = $$(this.ids.chartContainer); const $chartComponent = $$(this.ids.component); - if ($chartContainer?.data) $chartContainer.data.sync(dcChart); + if (dcChart && $chartContainer?.data) { + $chartContainer.data.sync(dcChart); + } setTimeout(() => { $chartComponent?.adjust(); diff --git a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js index daf11c3e..da54a471 100644 --- a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js +++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js @@ -1,7 +1,6 @@ -import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; +import { FNABViewChartCore } from "../chartBindings.js"; import FNAbviewchartlineComponent from "./FNAbviewchartlineComponent.js"; - // FNAbviewchartline Web // A web side import for an ABView. // @@ -10,13 +9,13 @@ export default function FNAbviewchartline({ ABViewPlugin, ABViewComponentPlugin, ABViewContainer, - ABViewWidgetPlugin + ABViewWidgetPlugin, }) { - const ABViewChartContainer = FNAbviewchartcontainer({ + const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); + + const ABAbviewchartlineComponent = FNAbviewchartlineComponent({ ABViewComponentPlugin, - ABViewWidgetPlugin, }); - const ABAbviewchartlineComponent = FNAbviewchartlineComponent({ ABViewComponentPlugin }); const ABViewChartLinePropertyComponentDefaults = { lineType: "line", @@ -35,7 +34,7 @@ export default function FNAbviewchartline({ labelKey: "Line", // {string} the multilingual label key for the class label }; - class ABViewChartLineCore extends ABViewChartContainer { + class ABViewChartLineCore extends ABViewChartCore { constructor(values, application, parent, defaultValues) { super(values, application, parent, defaultValues || ABViewDefaults); } @@ -103,35 +102,29 @@ export default function FNAbviewchartline({ componentList() { return []; } - }; + } return class ABViewChartLine extends ABViewChartLineCore { - /** - * @method getPluginKey - * return the plugin key for this view. - * @return {string} plugin key - */ + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ static getPluginKey() { return this.common().key; } /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component(parentId) { - return new ABAbviewchartlineComponent(this, parentId); + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component() { + return new ABAbviewchartlineComponent(this); } - // constructor(values, application, parent, defaultValues) { // super(values, application, parent, defaultValues); // } - - }; - } - diff --git a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js index 7617ec17..7138072f 100644 --- a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js @@ -1,4 +1,4 @@ -import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; +import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; export default function FNAbviewchartlineComponent({ /*AB,*/ diff --git a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js index 733ee8a6..015d1e7d 100644 --- a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js +++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js @@ -1,4 +1,4 @@ -import FNAbviewchartcontainer from "../container/FNAbviewchartcontainer.js"; +import { FNABViewChartCore } from "../chartBindings.js"; import FNAbviewchartpieComponent from "./FNAbviewchartpieComponent.js"; // FNAbviewchartpie Web @@ -9,13 +9,12 @@ export default function FNAbviewchartpie({ ABViewPlugin, ABViewComponentPlugin, ABViewContainer, - ABViewWidgetPlugin + ABViewWidgetPlugin, }) { - const ABViewChartContainer = FNAbviewchartcontainer({ + const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); + const ABAbviewchartpieComponent = FNAbviewchartpieComponent({ ABViewComponentPlugin, - ABViewWidgetPlugin, }); - const ABAbviewchartpieComponent = FNAbviewchartpieComponent({ ABViewComponentPlugin }); const ABViewChartPiePropertyComponentDefaults = { pieType: "pie", @@ -32,7 +31,7 @@ export default function FNAbviewchartpie({ labelKey: "Pie", // {string} the multilingual label key for the class label }; - class ABViewChartPieCore extends ABViewChartContainer { + class ABViewChartPieCore extends ABViewChartCore { constructor(values, application, parent, defaultValues) { super(values, application, parent, defaultValues || ABViewDefaults); } @@ -69,7 +68,8 @@ export default function FNAbviewchartpie({ // this.settings.chartWidth = parseInt(this.settings.chartWidth || ABViewChartPiePropertyComponentDefaults.chartWidth); this.settings.height = parseInt( - this.settings.height ?? ABViewChartPiePropertyComponentDefaults.height + this.settings.height ?? + ABViewChartPiePropertyComponentDefaults.height ); this.settings.innerFontSize = parseInt( @@ -91,35 +91,29 @@ export default function FNAbviewchartpie({ componentList() { return []; } - }; + } return class ABViewChartPie extends ABViewChartPieCore { - /** - * @method getPluginKey - * return the plugin key for this view. - * @return {string} plugin key - */ + * @method getPluginKey + * return the plugin key for this view. + * @return {string} plugin key + */ static getPluginKey() { return this.common().key; } /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component(parentId) { - return new ABAbviewchartpieComponent(this, parentId); + * @method component() + * return a UI component based upon this view. + * @return {obj} UI component + */ + component() { + return new ABAbviewchartpieComponent(this); } - // constructor(values, application, parent, defaultValues) { // super(values, application, parent, defaultValues); // } - - }; - } - diff --git a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js index ee2d99d8..3fab2cc3 100644 --- a/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js @@ -1,4 +1,4 @@ -import FNAbviewchartcontainerComponent from "../container/FNAbviewchartcontainerComponent.js"; +import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; export default function FNAbviewchartpieComponent({ /*AB,*/ diff --git a/AppBuilder/platform/views/ABViewChart.js b/AppBuilder/platform/views/ABViewChart.js deleted file mode 100644 index 1a5df44c..00000000 --- a/AppBuilder/platform/views/ABViewChart.js +++ /dev/null @@ -1,214 +0,0 @@ -const ABViewChartCore = require("../../core/views/ABViewChartCore"); -const ABViewChartComponent = require("./viewComponent/ABViewChartComponent"); - -module.exports = class ABViewChart extends ABViewChartCore { - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - - /** - * @method component() - * return a UI component based upon this view. - * @param {obj} App - * @return {obj} UI component - */ - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartComponent(this); - } - - fromValues(values) { - super.fromValues(values); - this.refreshData(); - } - - getDCChart() { - if (!this._dcChart) this._dcChart = new webix.DataCollection(); - - return this._dcChart; - } - - refreshData() { - const dc = this.datacollection; - if (dc == null) return this.dcChart; - - const labelCol = this.labelField(); - const valueCol = this.valueField(); - const valueCol2 = this.valueField2(); - - if (!labelCol || !valueCol) return this.dcChart; - - // const labelColName = labelCol.columnName; - const numberColName = valueCol.columnName; - - let numberColName2 = ""; - - if (this.settings.multipleSeries && valueCol2) { - numberColName2 = valueCol2.columnName; - } - - const colorList = [ - "#ee4339", - "#ee9336", - "#eed236", - "#d3ee36", - "#a7ee70", - "#58dccd", - "#36abee", - "#476cee", - "#a244ea", - "#e33fc7", - ]; - - const dInfo = dc.getData(); - - let results = []; - let sumData = {}; - let sumNumber = 0; - let sumNumber2 = 0; - let countNumber = dInfo.length; - - dInfo.forEach((item) => { - const labelKey = labelCol.format(item) || item.id; - - let numberVal = parseFloat(item[numberColName] || 0); - let numberVal2 = null; - - if (this.settings.multipleSeries) - numberVal2 = parseFloat(item[numberColName2]) || 0; - - switch (valueCol.key) { - //Formula Datatype - case "formula": - numberVal = valueCol.format(item); - - break; - - //Calcualte Datatype - case "calculate": - numberVal = parseFloat( - valueCol.constructor.convertToJs( - valueCol.object, - valueCol.settings.formula, - item, - valueCol.settings.decimalPlaces - ) - ); - - break; - - default: - break; - } - - if (sumData[labelKey] == null) { - let label = labelKey; - - // Get label of the connect field - if (labelCol.isConnection) { - let relateValues = labelCol.pullRelationValues(item); - if (relateValues != null) { - if (Array.isArray(relateValues)) - label = relateValues - .map((val) => val.text || "") - .join(", "); - else label = relateValues.text; - } - } - - if (this.settings.multipleSeries) { - sumData[labelKey] = { - label: label || item.id, - value: 0, - value2: 0, - }; - } else { - sumData[labelKey] = { - label: label || item.id, - value: 0, - }; - } - } - - sumData[labelKey].value += numberVal; - sumNumber += numberVal; - - if (this.settings.multipleSeries) { - sumData[labelKey].value2 += numberVal2; - sumNumber2 += numberVal2; - } - }); - - let index = 0; - - for (const key in sumData) { - let val = sumData[key].value; - - if (val <= 0) continue; - - // Display to percent values - if (this.settings.isPercentage) { - val = (val / sumNumber) * 100; - val = Math.round(val * 100) / 100; // round decimal 2 digits - val = val + " %"; - } - - if (this.settings.multipleSeries) { - let val2 = sumData[key].value2; - - if (val2 <= 0) continue; - - // Display to percent values - if (this.settings.isPercentage) { - val2 = (val2 / sumNumber2) * 100; - val2 = Math.round(val2 * 100) / 100; // round decimal 2 digits - val2 = val2 + " %"; - } - - results.push({ - label: sumData[key].label, - value: val, - value2: val2, - color: colorList[index % colorList.length], - count: countNumber, - }); - } else { - results.push({ - label: sumData[key].label, - value: val, - color: colorList[index % colorList.length], - count: countNumber, - }); - } - - index += 1; - } - - const dcChart = this.getDCChart(); - - dcChart.clearAll(); - dcChart.parse(results); - } - - warningsEval() { - super.warningsEval(); - - let labelField = this.labelField(); - if (!labelField) { - this.warningsMessage( - `can't resolve label field[${this.settings.columnLabel}]` - ); - } - - let valueField = this.valueField(); - if (!valueField) { - this.warningsMessage( - `can't resolve value field[${this.settings.columnValue}]` - ); - } - } -}; diff --git a/AppBuilder/platform/views/ABViewChartArea.js b/AppBuilder/platform/views/ABViewChartArea.js deleted file mode 100644 index 5c6676db..00000000 --- a/AppBuilder/platform/views/ABViewChartArea.js +++ /dev/null @@ -1,17 +0,0 @@ -const ABViewChartAreaCore = require("../../core/views/ABViewChartAreaCore"); -const ABViewChartAreaComponent = require("./viewComponent/ABViewChartAreaComponent"); - -module.exports = class ABViewChartArea extends ABViewChartAreaCore { - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartAreaComponent(this); - } -}; diff --git a/AppBuilder/platform/views/ABViewChartBar.js b/AppBuilder/platform/views/ABViewChartBar.js deleted file mode 100644 index c4f57d6b..00000000 --- a/AppBuilder/platform/views/ABViewChartBar.js +++ /dev/null @@ -1,17 +0,0 @@ -const ABViewChartBarCore = require("../../core/views/ABViewChartBarCore"); -const ABViewChartBarComponent = require("./viewComponent/ABViewChartBarComponent"); - -module.exports = class ABViewChartBar extends ABViewChartBarCore { - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartBarComponent(this); - } -}; diff --git a/AppBuilder/platform/views/ABViewChartLine.js b/AppBuilder/platform/views/ABViewChartLine.js deleted file mode 100644 index 2933684a..00000000 --- a/AppBuilder/platform/views/ABViewChartLine.js +++ /dev/null @@ -1,17 +0,0 @@ -const ABViewChartLineCore = require("../../core/views/ABViewChartLineCore"); -const ABViewChartLineComponent = require("./viewComponent/ABViewChartLineComponent"); - -module.exports = class ABViewChartLine extends ABViewChartLineCore { - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartLineComponent(this); - } -}; diff --git a/AppBuilder/platform/views/ABViewChartPie.js b/AppBuilder/platform/views/ABViewChartPie.js deleted file mode 100644 index 4ac5511f..00000000 --- a/AppBuilder/platform/views/ABViewChartPie.js +++ /dev/null @@ -1,17 +0,0 @@ -const ABViewChartPieCore = require("../../core/views/ABViewChartPieCore"); -const ABViewChartPieComponent = require("./viewComponent/ABViewChartPieComponent"); - -module.exports = class ABViewChartPie extends ABViewChartPieCore { - // constructor(values, application, parent, defaultValues) { - // super(values, application, parent, defaultValues); - // } - - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartPieComponent(this); - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartAreaComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartAreaComponent.js deleted file mode 100644 index 8c79fefa..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartAreaComponent.js +++ /dev/null @@ -1,56 +0,0 @@ -const ABViewChartContainerComponent = require("./ABViewChartContainerComponent"); - -module.exports = class ABViewChartAreaComponent extends ( - ABViewChartContainerComponent -) { - constructor(baseView, idBase, ids) { - super(baseView, idBase || `ABViewChartArea_${baseView.id}`, ids); - } - - ui() { - const settings = this.settings; - - return super.ui({ - view: "chart", - type: settings.areaType, - yAxis: { - start: 0, - step: settings.stepValue, //"#stepValue#", - end: settings.maxValue, //"#maxValue#" - }, - xAxis: { - template: settings.isLegend - ? `
#label#
` - : "", - }, - legend: settings.isLegend - ? { - template: `
#label#
`, - values: [], // TODO : bug in webix 5.1.7 - } - : null, - series: [ - { - alpha: 0.7, - value: "#value#", - color: "#ee4339", - }, - { - alpha: 0.4, - value: "#value2#", - color: "#a7ee70", - }, - ], - height: settings.chartHeight, - // width: settings.chartWidth, - }); - } - - async init(AB) { - await super.init(AB); - } - - onShow() { - super.onShow(); - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartBarComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartBarComponent.js deleted file mode 100644 index 767b59ab..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartBarComponent.js +++ /dev/null @@ -1,52 +0,0 @@ -const ABViewChartContainerComponent = require("./ABViewChartContainerComponent"); - -module.exports = class ABViewChartBarComponent extends ( - ABViewChartContainerComponent -) { - constructor(baseView, idBase, ids) { - super(baseView, idBase || `ABViewChartBar_${baseView.id}`, ids); - } - - ui() { - const settings = this.settings; - - return super.ui({ - view: "chart", - type: settings.barType, - preset: settings.barPreset, - value: "#value#", - color: "#color#", - yAxis: { - start: 0, - step: settings.stepValue, //"#stepValue#", - end: settings.maxValue, //"#maxValue#" - }, - xAxis: { - template: settings.isLegend - ? `
#label#
` - : "", - }, - legend: - settings.barType === "bar" || !settings.barType - ? settings.isLegend - ? `
#label#
` - : "" - : settings.isLegend - ? { - template: `
#label#
`, - values: [], // TODO : bug in webix 5.1.7 - } - : null, - height: settings.height, - // width: settings.chartWidth, - }); - } - - async init(AB) { - await super.init(AB); - } - - onShow() { - super.onShow(); - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartComponent.js deleted file mode 100644 index ce59c0d4..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartComponent.js +++ /dev/null @@ -1,62 +0,0 @@ -const ABViewContainerComponent = require("./ABViewContainerComponent"); - -module.exports = class ABViewChartComponent extends ABViewContainerComponent { - constructor(baseView, idBase, ids) { - super(baseView, idBase || `ABViewChart_${baseView.id}`, ids); - } - - async init(AB, accessLevel) { - await super.init(AB, accessLevel); - - const $component = $$(this.ids.component); - const abWebix = this.AB.Webix; - - if ($component) abWebix.extend($component, abWebix.ProgressBar); - - const baseView = this.view; - const dc = this.datacollection; - - if (dc) { - const eventNames = [ - "changeCursor", - "cursorStale", - "create", - "update", - "delete", - "initializedData", - ]; - - ["changeCursor", "cursorStale"].forEach((key) => { - // QUESTION: is this a problem if the check !(key in (...)) finds - // an event that some OTHER widget has added and not this one? - if ( - dc.datacollectionLink && - !(key in (dc.datacollectionLink._events ?? [])) - ) - baseView.eventAdd({ - emitter: dc.datacollectionLink, - eventName: key, - listener: () => { - baseView.refreshData(); - }, - }); - }); - - eventNames.forEach((evtName) => { - baseView.eventAdd({ - emitter: dc, - eventName: evtName, - listener: () => { - baseView.refreshData(); - }, - }); - }); - } - - baseView.refreshData(); - } - - onShow() { - super.onShow(); - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartLineComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartLineComponent.js deleted file mode 100644 index f5052ea0..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartLineComponent.js +++ /dev/null @@ -1,39 +0,0 @@ -const ABViewChartContainerComponent = require("./ABViewChartContainerComponent"); - -module.exports = class ABViewChartLineComponent extends ( - ABViewChartContainerComponent -) { - constructor(baseView, idBase, ids) { - super(baseView, idBase || `ABViewChartLine_${baseView.id}`, ids); - } - - ui() { - const settings = this.settings; - - return super.ui({ - view: "chart", - type: settings.lineType, - preset: settings.linePreset, - value: "#value#", - color: "#color#", - yAxis: { - start: 0, - step: settings.stepValue, - end: settings.maxValue, //"#maxValue#" - }, - xAxis: { - template: settings.isLegend - ? `
#label#
` - : "", - }, - legend: settings.isLegend - ? { - template: `
#label#
`, - values: [], // TODO : bug in webix 5.1.7 - } - : null, - height: settings.chartHeight, - // width: settings.chartWidth, - }); - } -}; diff --git a/AppBuilder/platform/views/viewComponent/ABViewChartPieComponent.js b/AppBuilder/platform/views/viewComponent/ABViewChartPieComponent.js deleted file mode 100644 index 0060f439..00000000 --- a/AppBuilder/platform/views/viewComponent/ABViewChartPieComponent.js +++ /dev/null @@ -1,30 +0,0 @@ -const ABViewChartContainerComponent = require("./ABViewChartContainerComponent"); - -module.exports = class ABViewChartPieComponent extends ( - ABViewChartContainerComponent -) { - constructor(baseView, idBase, ids) { - super(baseView, idBase || `ABViewChartPie_${baseView.id}`, ids); - } - - ui() { - const settings = this.settings; - - return super.ui({ - view: "chart", - type: settings.pieType, - value: "#value#", - color: "#color#", - legend: settings.isLegend - ? { - width: this.view.parent.settings.labelWidth, - template: `
#label#
`, - } - : null, - pieInnerText: `
#value#
`, - shadow: 1, - height: settings.height, - // width: settings.chartWidth, - }); - } -}; diff --git a/test/_setup.js b/test/_setup.js index ed53c8e1..6ecb2168 100644 --- a/test/_setup.js +++ b/test/_setup.js @@ -9,9 +9,12 @@ global.window = dom.window; global.document = dom.window.document; global.FileReader = global.window.FileReader; global.Blob = global.window.Blob; -global.navigator = { - userAgent: "node.js", -}; +Object.defineProperty(global, "navigator", { + value: dom.window.navigator, + writable: true, + configurable: true, + enumerable: true, +}); // Set webix globally global.$$ = webixElement; From 6fe6e0979eb8e0a4aed2013242a65ba62d93c1d1 Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Fri, 10 Apr 2026 17:49:56 +0700 Subject: [PATCH 4/8] fix reference to chartCore remove other unused code --- .../view_chart/area/FNAbviewchartarea.js | 1 - .../view_chart/chart/FNAbviewchart.js | 146 +++++++++++++++++- .../included/view_chart/chartBindings.js | 5 +- .../container/FNAbviewchartcontainer.js | 25 --- .../view_chart/{ => core}/ABViewChartCore.js | 0 .../FNAbviewchartcontainerComponent.js | 0 6 files changed, 146 insertions(+), 31 deletions(-) delete mode 100644 AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js rename AppBuilder/platform/plugins/included/view_chart/{ => core}/ABViewChartCore.js (100%) rename AppBuilder/platform/plugins/included/view_chart/{container => core}/FNAbviewchartcontainerComponent.js (100%) diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js index a7e0b547..0500f88d 100644 --- a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js @@ -20,7 +20,6 @@ export default function FNAbviewchartarea({ const ABViewChartAreaPropertyComponentDefaults = { areaType: "area", isLegend: 1, - chartWidth: 600, chartHeight: 200, labelFontSize: 12, stepValue: 20, diff --git a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js index e1c23fce..76bb39ae 100644 --- a/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js +++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js @@ -1,15 +1,157 @@ -import ABViewChartCore from "../../../../../core/views/ABViewChartCore.js"; + import FNAbviewchartComponent from "./FNAbviewchartComponent.js"; // FNAbviewchart Web // A web side import for an ABView. // -export default function FNAbviewchart({ AB, ABViewContainerComponent }) { +export default function FNAbviewchart({ + AB, + ABViewContainerComponent, + ABViewContainer, +}) { const ABAbviewchartComponent = FNAbviewchartComponent({ AB, ABViewContainerComponent, }); + const ABViewChartPropertyComponentDefaults = { + dataviewID: "", + columnValue: "", + columnLabel: "", + columnValue2: "", + isPercentage: 1, + showLabel: 1, + labelPosition: "left", + labelWidth: 120, + height: 200, + multipleSeries: 0, + }; + + const ABViewChartDefaults = { + key: "chart", // {string} unique key for this view + icon: "bar-chart", // {string} fa-[icon] reference for this view + labelKey: "Chart", // {string} the multilingual label key for the class label + }; + + // this needs to be a class that extends ABViewContainer + class ABViewChartCore extends ABViewContainer { + constructor(values, application, parent, defaultValues) { + super(values, application, parent, defaultValues || ABViewChartDefaults); + } + + static getPluginType() { + return "view"; + } + static common() { + return ABViewChartDefaults; + } + + static defaultValues() { + return ABViewChartPropertyComponentDefaults; + } + + /// + /// Instance Methods + /// + + /** + * @method fromValues() + * + * initialze this object with the given set of values. + * @param {obj} values + */ + fromValues(values) { + super.fromValues(values); + + this.settings.dataviewID = + this.settings.dataviewID ?? + ABViewChartPropertyComponentDefaults.dataviewID; + + this.settings.columnValue = + this.settings.columnValue ?? + ABViewChartPropertyComponentDefaults.columnValue; + + this.settings.columnLabel = + this.settings.columnLabel ?? + ABViewChartPropertyComponentDefaults.columnLabel; + + this.settings.columnValue2 = + this.settings.columnValue2 ?? + ABViewChartPropertyComponentDefaults.columnValue2; + + this.settings.isPercentage = parseInt( + this.settings.isPercentage ?? + ABViewChartPropertyComponentDefaults.isPercentage + ); + + this.settings.showLabel = parseInt( + this.settings.showLabel ?? + ABViewChartPropertyComponentDefaults.showLabel + ); + + this.settings.labelPosition = + this.settings.labelPosition || + ABViewChartPropertyComponentDefaults.labelPosition; + + this.settings.labelWidth = parseInt( + this.settings.labelWidth ?? + ABViewChartPropertyComponentDefaults.labelWidth + ); + + this.settings.height = parseInt( + this.settings.height ?? ABViewChartPropertyComponentDefaults.height + ); + + this.settings.multipleSeries = parseInt( + this.settings.multipleSeries ?? + ABViewChartPropertyComponentDefaults.multipleSeries + ); + + this.translate(this, this, ["chartLabel"]); + } + + /** + * @method componentList + * return the list of components available on this view to display in the editor. + */ + componentList() { + const viewsToAllow = ["label", "pie", "bar", "line", "area"]; + return this.application.viewAll((c) => { + return viewsToAllow.indexOf(c.common().key) > -1; + }); + } + + labelField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnLabel); + } + + valueField() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue); + } + + valueField2() { + const dc = this.datacollection; + if (!dc) return null; + + const obj = dc.datasource; + if (!obj) return null; + + return obj.fieldByID(this.settings.columnValue2); + } + }; + return class ABViewChart extends ABViewChartCore { /** * @method getPluginKey diff --git a/AppBuilder/platform/plugins/included/view_chart/chartBindings.js b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js index 5a730954..a8923451 100644 --- a/AppBuilder/platform/plugins/included/view_chart/chartBindings.js +++ b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js @@ -1,3 +1,2 @@ -export { default as FNABViewChartCore } from "./ABViewChartCore.js"; -export { default as FNAbviewchartcontainer } from "./container/FNAbviewchartcontainer.js"; -export { default as FNAbviewchartcontainerComponent } from "./container/FNAbviewchartcontainerComponent.js"; +export { default as FNABViewChartCore } from "./core/ABViewChartCore.js"; +export { default as FNAbviewchartcontainerComponent } from "./core/FNAbviewchartcontainerComponent.js"; diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js b/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js deleted file mode 100644 index ab56f180..00000000 --- a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainer.js +++ /dev/null @@ -1,25 +0,0 @@ -import ABviewchartcontainerComponent from "./FNAbviewchartcontainerComponent.js"; - -export default function FNAbviewchartcontainer({ - ABViewComponentPlugin, - ABViewWidgetPlugin, -}) { - const ABViewChartContainerComponent = ABviewchartcontainerComponent({ - ABViewComponentPlugin, - }); - - return class ABViewChartContainer extends ABViewWidgetPlugin { - /** - * @method component() - * return a UI component based upon this view. - * @return {obj} UI component - */ - component() { - return new ABViewChartContainerComponent(this); - } - - get datacollection() { - return this.parent.datacollection; - } - }; -} diff --git a/AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js b/AppBuilder/platform/plugins/included/view_chart/core/ABViewChartCore.js similarity index 100% rename from AppBuilder/platform/plugins/included/view_chart/ABViewChartCore.js rename to AppBuilder/platform/plugins/included/view_chart/core/ABViewChartCore.js diff --git a/AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js b/AppBuilder/platform/plugins/included/view_chart/core/FNAbviewchartcontainerComponent.js similarity index 100% rename from AppBuilder/platform/plugins/included/view_chart/container/FNAbviewchartcontainerComponent.js rename to AppBuilder/platform/plugins/included/view_chart/core/FNAbviewchartcontainerComponent.js From c7c9e61020ed4ba25a843bd92b9f4bea9bc8f5cd Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Mon, 13 Apr 2026 17:10:56 +0700 Subject: [PATCH 5/8] add commands to workflow --- .github/workflows/e2e-tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 02971523..817dce6c 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -34,6 +34,10 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} ref: ${{ matrix.branch }} + - run: npm config set ignore-scripts true + - run: npm config set allow-git none + - run: npm config set min-release-age=7 + - run: npm i working-directory: ./ab_platform_web From f86462fb8a7dfdb802d2364a33f401126be11b07 Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Mon, 13 Apr 2026 17:30:09 +0700 Subject: [PATCH 6/8] action update --- .github/workflows/e2e-tests.yml | 146 +++++++++++++++---------------- .github/workflows/lighthouse.yml | 6 +- 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 817dce6c..aa6a28c9 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,92 +1,88 @@ name: E2E Tests on: - workflow_call: + workflow_call: inputs: ref: type: string default: ${{ github.ref }} jobs: - e2e-tests: - name: E2E Tests - runs-on: ubuntu-latest - env: - CYPRESS_RESPONSE_TIMEOUT: 200000 - CYPRESS_DEFAULT_COMMAND_TIMEOUT: 30000 - CYPRESS_RETRIES: 2 - strategy: - fail-fast: true - matrix: - include: - - branch: develop - webpack: dev - - branch: master - webpack: update - steps: - - uses: actions/checkout@v4 - with: - path: ab_platform_web - submodules: true - ref: ${{ inputs.ref }} - - uses: actions/checkout@v4 - with: - path: web - repository: CruGlobal/ab_service_web - token: ${{ secrets.GITHUB_TOKEN }} - ref: ${{ matrix.branch }} + e2e-tests: + name: E2E Tests + runs-on: ubuntu-latest + env: + CYPRESS_RESPONSE_TIMEOUT: 200000 + CYPRESS_DEFAULT_COMMAND_TIMEOUT: 30000 + CYPRESS_RETRIES: 2 + strategy: + fail-fast: true + matrix: + include: + - branch: develop + webpack: dev + - branch: master + webpack: update + steps: + - uses: actions/checkout@v4 + with: + path: ab_platform_web + submodules: true + ref: ${{ inputs.ref }} + - uses: actions/checkout@v4 + with: + path: web + repository: CruGlobal/ab_service_web + token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ matrix.branch }} - - run: npm config set ignore-scripts true - - run: npm config set allow-git none - - run: npm config set min-release-age=7 + - run: npm i + working-directory: ./ab_platform_web - - run: npm i - working-directory: ./ab_platform_web + - name: Webpack + run: npm run build:${{ matrix.webpack }} + working-directory: ./ab_platform_web - - name: Webpack - run: npm run build:${{ matrix.webpack }} - working-directory: ./ab_platform_web + # webpack expects the folder to be called "web" ab-install action expects "ab_service_web" + - run: mv web ab_service_web - # webpack expects the folder to be called "web" ab-install action expects "ab_service_web" - - run: mv web ab_service_web + - uses: CruGlobal/ab-install-action@main + with: + port: 8080 + folder: ab + repository: CruGlobal/ab_service_web - - uses: CruGlobal/ab-install-action@v1 - with: - port: 8080 - folder: ab - repository: CruGlobal/ab_service_web + - name: Check out kitchen-sink tests + uses: actions/checkout@v4 + with: + repository: CruGlobal/kitchensink_app + path: ab/test/e2e/cypress/e2e/kitchensink_app - - name: Check out kitchen-sink tests - uses: actions/checkout@v4 - with: - repository: CruGlobal/kitchensink_app - path: ab/test/e2e/cypress/e2e/kitchensink_app + # These next steps are to save our ablogs to file + - run: npm install pm2@latest -g + - name: Save Logs + run: pm2 start ./logs.js -- --toFile logs/ABServices.log + working-directory: ./ab - # These next steps are to save our ablogs to file - - run: npm install pm2@latest -g - - name: Save Logs - run: pm2 start ./logs.js -- --toFile logs/ABServices.log - working-directory: ./ab + #Run test + - name: Wait for AB + # Skipping the wait step. Cypress has a bit of wait time built in. It might be enough. + if: false + uses: ifaxity/wait-on-action@v1.1.0 + with: + resource: http://localhost:8080 + timeout: 300000 - #Run test - - name: Wait for AB - # Skipping the wait step. Cypress has a bit of wait time built in. It might be enough. - if: false - uses: ifaxity/wait-on-action@v1.1.0 - with: - resource: http://localhost:8080 - timeout: 300000 + - name: Run Cypress Tests + run: npm run test:e2e:app -- --browser chrome + working-directory: ./ab - - name: Run Cypress Tests - run: npm run test:e2e:app -- --browser chrome - working-directory: ./ab + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: cypress-screenshots + path: ./ab/test/e2e/cypress/screenshots - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: cypress-screenshots - path: ./ab/test/e2e/cypress/screenshots - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: ABServices.log - path: ./ab/logs/ABServices.log + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: ABServices.log + path: ./ab/logs/ABServices.log diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index 5ba4bce6..ec1668c2 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -9,13 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Platform Web - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: path: ab_platform_web submodules: true - name: Checkout Web Service - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: path: web repository: CruGlobal/ab_service_web @@ -121,7 +121,7 @@ jobs: # NejcZdovc/comment-pr@v2 needs a checkout to the base path - name: Fix for NejcZdovc/comment-pr if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Add Lighthouse Results to PR Commnet if: ${{ github.event_name == 'pull_request' }} From 7e8f3257d0ce5b8d2cc512a2bea0280ab5ea2916 Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Wed, 22 Apr 2026 10:24:40 +0700 Subject: [PATCH 7/8] lint --- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/lighthouse.yml | 238 +++++++++++++++---------------- 2 files changed, 120 insertions(+), 120 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index aa6a28c9..5c29bb81 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -44,7 +44,7 @@ jobs: # webpack expects the folder to be called "web" ab-install action expects "ab_service_web" - run: mv web ab_service_web - - uses: CruGlobal/ab-install-action@main + - uses: CruGlobal/ab-install-action@v1 with: port: 8080 folder: ab diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index ec1668c2..76074b17 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -1,133 +1,133 @@ name: Lighthouse CI on: - push: - branches: ["master"] - pull_request: - branches: ["master"] + push: + branches: ["master"] + pull_request: + branches: ["master"] jobs: - lighthouse: - runs-on: ubuntu-latest - steps: - - name: Checkout Platform Web - uses: actions/checkout@v6 - with: - path: ab_platform_web - submodules: true + lighthouse: + runs-on: ubuntu-latest + steps: + - name: Checkout Platform Web + uses: actions/checkout@v6 + with: + path: ab_platform_web + submodules: true - - name: Checkout Web Service - uses: actions/checkout@v6 - with: - path: web - repository: CruGlobal/ab_service_web - token: ${{ secrets.GITHUB_TOKEN }} - ref: master + - name: Checkout Web Service + uses: actions/checkout@v6 + with: + path: web + repository: CruGlobal/ab_service_web + token: ${{ secrets.GITHUB_TOKEN }} + ref: master - - name: Install NPM Dependencies - run: npm i - working-directory: ./ab_platform_web + - name: Install NPM Dependencies + run: npm i + working-directory: ./ab_platform_web - - name: Run Webpack - run: npm run build:update - working-directory: ./ab_platform_web + - name: Run Webpack + run: npm run build:update + working-directory: ./ab_platform_web - # webpack expects the folder to be called "web" ab-install action expects "ab_service_web" - - name: Fix Web Servive Foledr Name - run: mv web ab_service_web + # webpack expects the folder to be called "web" ab-install action expects "ab_service_web" + - name: Fix Web Servive Foledr Name + run: mv web ab_service_web - - name: Install AppBuilder - uses: CruGlobal/ab-install-action@v1 - with: - repository: CruGlobal/ab_service_web + - name: Install AppBuilder + uses: CruGlobal/ab-install-action@v1 + with: + repository: CruGlobal/ab_service_web - - name: Wait for AppBuilder - # Skipping the wait step. Cypress has a bit of wait time built in. It might be enough. - if: false - uses: ifaxity/wait-on-action@v1.1.0 - with: - resource: http://localhost - timeout: 300000 + - name: Wait for AppBuilder + # Skipping the wait step. Cypress has a bit of wait time built in. It might be enough. + if: false + uses: ifaxity/wait-on-action@v1.1.0 + with: + resource: http://localhost + timeout: 300000 - - name: Run Lighthouse CI - run: | - npm install -g @lhci/cli puppeteer - lhci autorun - working-directory: ./ab_platform_web - env: - LHCI_UPLOAD__TARGET: "lhci" - LHCI_UPLOAD__SERVER_BASE_URL: "https://lighthouse.digiserve.org/" - LHCI_UPLOAD__TOKEN: ${{ secrets.LHCI_BUILD_TOKEN }} - LHCI_COLLECT__URL: "http://127.0.0.1" - LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} - LHCI_COLLECT__PUPPETEER_SCRIPT: "ciLighthouseAuth.js" + - name: Run Lighthouse CI + run: | + npm install -g @lhci/cli puppeteer + lhci autorun + working-directory: ./ab_platform_web + env: + LHCI_UPLOAD__TARGET: "lhci" + LHCI_UPLOAD__SERVER_BASE_URL: "https://lighthouse.digiserve.org/" + LHCI_UPLOAD__TOKEN: ${{ secrets.LHCI_BUILD_TOKEN }} + LHCI_COLLECT__URL: "http://127.0.0.1" + LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} + LHCI_COLLECT__PUPPETEER_SCRIPT: "ciLighthouseAuth.js" - - name: Get the Lighouse Reports - if: ${{ github.event_name == 'pull_request' }} - id: get_report - run: | - echo "LH_REPORT_A=$(ls | grep lhr- | grep .json | sed -n 1p)" >> $GITHUB_OUTPUT - echo "LH_REPORT_B=$(ls | grep lhr- | grep .json | sed -n 2p)" >> $GITHUB_OUTPUT - echo "LH_REPORT_C=$(ls | grep lhr- | grep .json | sed -n 3p)" >> $GITHUB_OUTPUT - working-directory: ./ab_platform_web/.lighthouseci + - name: Get the Lighouse Reports + if: ${{ github.event_name == 'pull_request' }} + id: get_report + run: | + echo "LH_REPORT_A=$(ls | grep lhr- | grep .json | sed -n 1p)" >> $GITHUB_OUTPUT + echo "LH_REPORT_B=$(ls | grep lhr- | grep .json | sed -n 2p)" >> $GITHUB_OUTPUT + echo "LH_REPORT_C=$(ls | grep lhr- | grep .json | sed -n 3p)" >> $GITHUB_OUTPUT + working-directory: ./ab_platform_web/.lighthouseci - - name: Extract Report Highlights - if: ${{ github.event_name == 'pull_request' }} - uses: actions/github-script@v7 - env: - REPORT_A: ${{ steps.get_report.outputs.LH_REPORT_A }} - REPORT_B: ${{ steps.get_report.outputs.LH_REPORT_B }} - REPORT_C: ${{ steps.get_report.outputs.LH_REPORT_C }} - with: - script: | - const reports = [ - require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_A}`), - require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_B}`), - require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_C}`), - ]; - const links = require("./ab_platform_web/.lighthouseci/links.json"); - const getColor = (score) => score - 49 <= 0 ? "FF3333" : score - 89 <= 0 ? "FFAA33": "00CC66"; - const average = (vals, multiply = 1) => Math.round(vals.reduce((a,b) => a + b) / vals.length * multiply); - const extractDetails = (key) => { - const reportEntry = reports[0].audits[key]; - const details = { - title: reportEntry.title, - score: average(reports.map(r => r.audits[key].score), 100), - }; - details.color = getColor(details.score); - if (reportEntry.scoreDisplayMode === "numeric") { - details.score = average(reports.map(r => r.audits[key].numericValue)); - } - return details; - } - const performance = average(reports.map(r => r.categories.performance.score), 100); - core.exportVariable("PERFORMANCE", performance); - core.exportVariable("PERFORMANCE_COLOR", getColor(performance)); - const fcp = extractDetails("first-contentful-paint"); - core.exportVariable("FCP", `${Math.round(fcp.score/100)/10}%20s`); - core.exportVariable("FCP_COLOR", fcp.color); - const lcp = extractDetails("largest-contentful-paint"); - core.exportVariable("LCP", `${Math.round(lcp.score/100)/10}%20s`); - core.exportVariable("LCP_COLOR", lcp.color); - const tbt = extractDetails("total-blocking-time"); - core.exportVariable("TBT", `${tbt.score}%20ms`); - core.exportVariable("TBT_COLOR", tbt.color); - const cls = extractDetails("cumulative-layout-shift"); - core.exportVariable("CLS", cls.score); - core.exportVariable("CLS_COLOR", cls.color); - const speed = extractDetails("speed-index"); - core.exportVariable("SPEED", `${Math.round(speed.score/100)/10}%20s`); - core.exportVariable("SPEED_COLOR", speed.color); - core.exportVariable("LINK", links[Object.keys(links)[0]]); + - name: Extract Report Highlights + if: ${{ github.event_name == 'pull_request' }} + uses: actions/github-script@v7 + env: + REPORT_A: ${{ steps.get_report.outputs.LH_REPORT_A }} + REPORT_B: ${{ steps.get_report.outputs.LH_REPORT_B }} + REPORT_C: ${{ steps.get_report.outputs.LH_REPORT_C }} + with: + script: | + const reports = [ + require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_A}`), + require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_B}`), + require(`./ab_platform_web/.lighthouseci/${process.env.REPORT_C}`), + ]; + const links = require("./ab_platform_web/.lighthouseci/links.json"); + const getColor = (score) => score - 49 <= 0 ? "FF3333" : score - 89 <= 0 ? "FFAA33": "00CC66"; + const average = (vals, multiply = 1) => Math.round(vals.reduce((a,b) => a + b) / vals.length * multiply); + const extractDetails = (key) => { + const reportEntry = reports[0].audits[key]; + const details = { + title: reportEntry.title, + score: average(reports.map(r => r.audits[key].score), 100), + }; + details.color = getColor(details.score); + if (reportEntry.scoreDisplayMode === "numeric") { + details.score = average(reports.map(r => r.audits[key].numericValue)); + } + return details; + } + const performance = average(reports.map(r => r.categories.performance.score), 100); + core.exportVariable("PERFORMANCE", performance); + core.exportVariable("PERFORMANCE_COLOR", getColor(performance)); + const fcp = extractDetails("first-contentful-paint"); + core.exportVariable("FCP", `${Math.round(fcp.score/100)/10}%20s`); + core.exportVariable("FCP_COLOR", fcp.color); + const lcp = extractDetails("largest-contentful-paint"); + core.exportVariable("LCP", `${Math.round(lcp.score/100)/10}%20s`); + core.exportVariable("LCP_COLOR", lcp.color); + const tbt = extractDetails("total-blocking-time"); + core.exportVariable("TBT", `${tbt.score}%20ms`); + core.exportVariable("TBT_COLOR", tbt.color); + const cls = extractDetails("cumulative-layout-shift"); + core.exportVariable("CLS", cls.score); + core.exportVariable("CLS_COLOR", cls.color); + const speed = extractDetails("speed-index"); + core.exportVariable("SPEED", `${Math.round(speed.score/100)/10}%20s`); + core.exportVariable("SPEED_COLOR", speed.color); + core.exportVariable("LINK", links[Object.keys(links)[0]]); - # NejcZdovc/comment-pr@v2 needs a checkout to the base path - - name: Fix for NejcZdovc/comment-pr - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@v6 + # NejcZdovc/comment-pr@v2 needs a checkout to the base path + - name: Fix for NejcZdovc/comment-pr + if: ${{ github.event_name == 'pull_request' }} + uses: actions/checkout@v6 - - name: Add Lighthouse Results to PR Commnet - if: ${{ github.event_name == 'pull_request' }} - uses: NejcZdovc/comment-pr@v2 - with: - file: lighthouse.md - identifier: LIGHTHOUSE_REPORT - env: - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Add Lighthouse Results to PR Commnet + if: ${{ github.event_name == 'pull_request' }} + uses: NejcZdovc/comment-pr@v2 + with: + file: lighthouse.md + identifier: LIGHTHOUSE_REPORT + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} From 339f23c2f843a0b8facca2876059add3c13ac7cb Mon Sep 17 00:00:00 2001 From: roguisharcanetrickster Date: Mon, 18 May 2026 17:09:04 +0700 Subject: [PATCH 8/8] clean up imports --- AppBuilder/platform/plugins/included/index.js | 10 +--------- .../plugins/included/view_chart/FNAbviewchart.js | 15 +++++++++++++++ .../included/view_chart/area/FNAbviewchartarea.js | 2 -- .../view_chart/area/FNAbviewchartareaComponent.js | 5 +---- .../included/view_chart/bar/FNAbviewchartbar.js | 3 --- .../view_chart/bar/FNAbviewchartbarComponent.js | 1 - .../included/view_chart/line/FNAbviewchartline.js | 3 --- 7 files changed, 17 insertions(+), 22 deletions(-) create mode 100644 AppBuilder/platform/plugins/included/view_chart/FNAbviewchart.js diff --git a/AppBuilder/platform/plugins/included/index.js b/AppBuilder/platform/plugins/included/index.js index 7d5174dc..26df8041 100644 --- a/AppBuilder/platform/plugins/included/index.js +++ b/AppBuilder/platform/plugins/included/index.js @@ -1,9 +1,5 @@ import viewCarousel from "./view_carousel/FNAbviewcarousel.js"; -import viewChart from "./view_chart/chart/FNAbviewchart.js"; -import viewChartArea from "./view_chart/area/FNAbviewchartarea.js"; -import viewChartBar from "./view_chart/bar/FNAbviewchartbar.js"; -import viewChartLine from "./view_chart/line/FNAbviewchartline.js"; -import viewChartPie from "./view_chart/pie/FNAbviewchartpie.js"; +import viewChart from "./view_chart/FNAbviewchart.js"; import viewComment from "./view_comment/FNAbviewcomment.js"; import viewCsvExporter from "./view_csvExporter/FNAbviewcsvexporter.js"; import viewCsvImporter from "./view_csvImporter/FNAbviewcsvimporter.js"; @@ -23,10 +19,6 @@ import viewText from "./view_text/FNAbviewtext.js"; const AllPlugins = [ viewCarousel, viewChart, - viewChartArea, - viewChartBar, - viewChartLine, - viewChartPie, viewComment, viewCsvExporter, viewCsvImporter, diff --git a/AppBuilder/platform/plugins/included/view_chart/FNAbviewchart.js b/AppBuilder/platform/plugins/included/view_chart/FNAbviewchart.js new file mode 100644 index 00000000..3d6a0702 --- /dev/null +++ b/AppBuilder/platform/plugins/included/view_chart/FNAbviewchart.js @@ -0,0 +1,15 @@ +import viewChart from "./chart/FNAbviewchart.js"; +import viewChartArea from "./area/FNAbviewchartarea.js"; +import viewChartBar from "./bar/FNAbviewchartbar.js"; +import viewChartLine from "./line/FNAbviewchartline.js"; +import viewChartPie from "./pie/FNAbviewchartpie.js"; + +export default function ABchart(API) { + return [ + viewChart(API), + viewChartArea(API), + viewChartBar(API), + viewChartLine(API), + viewChartPie(API), + ]; +} \ No newline at end of file diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js index 0500f88d..4b585134 100644 --- a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js @@ -6,9 +6,7 @@ import { FNABViewChartCore } from "../chartBindings.js"; // export default function FNAbviewchartarea({ AB, - ABViewPlugin, ABViewComponentPlugin, - ABViewContainer, ABViewWidgetPlugin, }) { const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); diff --git a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js index 70e354a7..f550329b 100644 --- a/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js @@ -1,9 +1,6 @@ import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; -export default function FNAbviewchartareaComponent({ - /*AB,*/ - ABViewComponentPlugin, -}) { +export default function FNAbviewchartareaComponent({ ABViewComponentPlugin }) { const ChartContainerComponent = FNAbviewchartcontainerComponent({ ABViewComponentPlugin, }); diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js index 657814ae..b4ce0c6a 100644 --- a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js @@ -5,10 +5,7 @@ import { FNABViewChartCore } from "../chartBindings.js"; // A web side import for an ABView. // export default function FNAbviewchartbar({ - /*AB,*/ - ABViewPlugin, ABViewComponentPlugin, - ABViewContainer, ABViewWidgetPlugin, }) { const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin }); diff --git a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js index f8451d99..f142a190 100644 --- a/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js +++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js @@ -1,7 +1,6 @@ import { FNAbviewchartcontainerComponent } from "../chartBindings.js"; export default function FNAbviewchartbarComponent({ - /*AB,*/ ABViewComponentPlugin, }) { const ChartContainerComponent = FNAbviewchartcontainerComponent({ diff --git a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js index da54a471..40c3f5b6 100644 --- a/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js +++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js @@ -5,10 +5,7 @@ import FNAbviewchartlineComponent from "./FNAbviewchartlineComponent.js"; // A web side import for an ABView. // export default function FNAbviewchartline({ - /*AB,*/ - ABViewPlugin, ABViewComponentPlugin, - ABViewContainer, ABViewWidgetPlugin, }) { const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin });