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/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml
index 02971523..5c29bb81 100644
--- a/.github/workflows/e2e-tests.yml
+++ b/.github/workflows/e2e-tests.yml
@@ -1,88 +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 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@v1
- 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..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@v3
- 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@v3
- 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@v3
+ # 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}}
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
diff --git a/AppBuilder/platform/plugins/included/index.js b/AppBuilder/platform/plugins/included/index.js
index cdc4f0a9..26df8041 100644
--- a/AppBuilder/platform/plugins/included/index.js
+++ b/AppBuilder/platform/plugins/included/index.js
@@ -1,4 +1,5 @@
import viewCarousel from "./view_carousel/FNAbviewcarousel.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";
@@ -17,6 +18,7 @@ import viewText from "./view_text/FNAbviewtext.js";
const AllPlugins = [
viewCarousel,
+ viewChart,
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
new file mode 100644
index 00000000..4b585134
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartarea.js
@@ -0,0 +1,122 @@
+import FNAbviewchartareaComponent from "./FNAbviewchartareaComponent.js";
+import { FNABViewChartCore } from "../chartBindings.js";
+
+// FNAbviewchartarea Web
+// A web side import for an ABView.
+//
+export default function FNAbviewchartarea({
+ AB,
+ ABViewComponentPlugin,
+ ABViewWidgetPlugin,
+}) {
+ const ABViewChartCore = FNABViewChartCore({ ABViewWidgetPlugin });
+ const ABAbviewchartareaComponent = FNAbviewchartareaComponent({
+ AB,
+ ABViewComponentPlugin,
+ });
+
+ const ABViewChartAreaPropertyComponentDefaults = {
+ areaType: "area",
+ isLegend: 1,
+ 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 ABViewChartCore {
+ 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() {
+ return new ABAbviewchartareaComponent(this);
+ }
+
+ // 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..f550329b
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/area/FNAbviewchartareaComponent.js
@@ -0,0 +1,60 @@
+import { FNAbviewchartcontainerComponent } from "../chartBindings.js";
+
+export default function FNAbviewchartareaComponent({ 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..b4ce0c6a
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbar.js
@@ -0,0 +1,126 @@
+import FNAbviewchartbarComponent from "./FNAbviewchartbarComponent.js";
+import { FNABViewChartCore } from "../chartBindings.js";
+
+// FNAbviewchartbar Web
+// A web side import for an ABView.
+//
+export default function FNAbviewchartbar({
+ ABViewComponentPlugin,
+ ABViewWidgetPlugin,
+}) {
+ const ABViewChartCore = FNABViewChartCore({ 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 ABViewChartCore {
+ 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() {
+ 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
new file mode 100644
index 00000000..f142a190
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/bar/FNAbviewchartbarComponent.js
@@ -0,0 +1,58 @@
+import { FNAbviewchartcontainerComponent } from "../chartBindings.js";
+
+export default function FNAbviewchartbarComponent({
+ 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..76bb39ae
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchart.js
@@ -0,0 +1,367 @@
+
+import FNAbviewchartComponent from "./FNAbviewchartComponent.js";
+
+// FNAbviewchart Web
+// A web side import for an ABView.
+//
+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
+ * return the plugin key for this view.
+ * @return {string} plugin key
+ */
+ static getPluginKey() {
+ return this.common().key;
+ }
+
+ static getPluginType() {
+ return "view";
+ }
+
+ /**
+ * @method component()
+ * return a UI component based upon this view.
+ * @return {obj} UI component
+ */
+ component(parentId) {
+ return new ABAbviewchartComponent(this, parentId);
+ }
+
+ 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.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}]`
+ );
+ }
+ }
+ };
+}
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..2ba26898
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/chart/FNAbviewchartComponent.js
@@ -0,0 +1,79 @@
+export default function FNAbviewchartComponent({
+ AB,
+ ABViewContainerComponent,
+}) {
+ return class FNAbviewchartComponent extends ABViewContainerComponent {
+ constructor(baseView, idBase, ids) {
+ super(baseView, idBase || `ABViewChart_${baseView.id}`, ids);
+ }
+
+ async init(ABParam, accessLevel) {
+ await super.init(ABParam, accessLevel);
+
+ const $component = $$(this.ids.component);
+ const abWebix = AB.Webix;
+
+ if ($component) abWebix.extend($component, abWebix.ProgressBar);
+
+ const baseView = this.view;
+ 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 = [
+ "changeCursor",
+ "cursorStale",
+ "create",
+ "update",
+ "delete",
+ "initializedData",
+ ];
+
+ ["changeCursor", "cursorStale"].forEach((key) => {
+ 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/chartBindings.js b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js
new file mode 100644
index 00000000..a8923451
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/chartBindings.js
@@ -0,0 +1,2 @@
+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/core/ABViewChartCore.js b/AppBuilder/platform/plugins/included/view_chart/core/ABViewChartCore.js
new file mode 100644
index 00000000..f2f9ea6e
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/core/ABViewChartCore.js
@@ -0,0 +1,330 @@
+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/core/FNAbviewchartcontainerComponent.js b/AppBuilder/platform/plugins/included/view_chart/core/FNAbviewchartcontainerComponent.js
new file mode 100644
index 00000000..acfce236
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/core/FNAbviewchartcontainerComponent.js
@@ -0,0 +1,80 @@
+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({
+ 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();
+ const baseView = this.view;
+
+ baseView._isShow = true;
+
+ 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 (dcChart && $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..40c3f5b6
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartline.js
@@ -0,0 +1,127 @@
+import { FNABViewChartCore } from "../chartBindings.js";
+import FNAbviewchartlineComponent from "./FNAbviewchartlineComponent.js";
+
+// FNAbviewchartline Web
+// A web side import for an ABView.
+//
+export default function FNAbviewchartline({
+ ABViewComponentPlugin,
+ ABViewWidgetPlugin,
+}) {
+ const ABViewChartCore = FNABViewChartCore({ 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 ABViewChartCore {
+ 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() {
+ 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
new file mode 100644
index 00000000..7138072f
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/line/FNAbviewchartlineComponent.js
@@ -0,0 +1,46 @@
+import { FNAbviewchartcontainerComponent } from "../chartBindings.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..015d1e7d
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpie.js
@@ -0,0 +1,119 @@
+import { FNABViewChartCore } from "../chartBindings.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 ABViewChartCore = FNABViewChartCore({ 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 ABViewChartCore {
+ 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() {
+ 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
new file mode 100644
index 00000000..3fab2cc3
--- /dev/null
+++ b/AppBuilder/platform/plugins/included/view_chart/pie/FNAbviewchartpieComponent.js
@@ -0,0 +1,37 @@
+import { FNAbviewchartcontainerComponent } from "../chartBindings.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/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/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/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/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);
- }
-};
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;