diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d85a277c43..728fd30036 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -7,7 +7,6 @@ Use this guide to review both code and workflow. Focus on Mendix pluggable widge - **Monorepo** with packages under `packages/`: - `packages/pluggableWidgets/*-web` - `packages/modules/*` - - `packages/customWidgets/*` - `packages/shared/*` (configs, plugins) - **Stack**: TypeScript, React, SCSS, Rollup via `@mendix/pluggable-widgets-tools`, Jest/RTL, ESLint/Prettier. - **Commands** (root): `pnpm lint`, `pnpm test`, `pnpm build`, `pnpm -w changelog`, `pnpm -w version`. diff --git a/.github/renovate.json b/.github/renovate.json index 749c30396d..cb1b6b1e67 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -27,7 +27,6 @@ "allowScripts": true, "ignoreScripts": false, "ignoreDeps": ["typescript", "react", "react-dom", "@types/react", "@types/react-dom"], - "ignorePaths": ["**/customWidgets/**"], "packageRules": [ { "matchCategories": ["docker"], "enabled": false }, { "matchPackagePatterns": ["*"], "rangeStrategy": "bump" }, diff --git a/automation/scripts/update-screenshots.mjs b/automation/scripts/update-screenshots.mjs index e60ed6b829..9e75eff3ea 100755 --- a/automation/scripts/update-screenshots.mjs +++ b/automation/scripts/update-screenshots.mjs @@ -294,7 +294,7 @@ function extractZip(zipPath, destDir) { * C) Stripped: pluggableWidgets/gallery-web/test-results/... (v4 artifact strips packages/) * D) Via node_modules: .../node_modules/@mendix/gallery-web/test-results/... */ -const CATEGORY_DIRS = new Set(["pluggableWidgets", "modules", "customWidgets", "shared"]); +const CATEGORY_DIRS = new Set(["pluggableWidgets", "modules", "shared"]); function extractCandidatePackageDirs(parts, testResultsIdx, repoRoot) { const candidates = []; diff --git a/package.json b/package.json index 468798dfb4..be6172ec2d 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "mime-types@2.1.35": "patches/mime-types@2.1.35.patch", "mobx-react-lite@4.0.7": "patches/mobx-react-lite@4.0.7.patch", "mobx@6.12.3": "patches/mobx@6.12.3.patch", - "react-big-calendar@0.19.2": "patches/react-big-calendar@0.19.2.patch", "react-dropzone": "patches/react-dropzone.patch" }, "ignoredBuiltDependencies": [ diff --git a/packages/customWidgets/calendar-custom-web/.prettierrc.js b/packages/customWidgets/calendar-custom-web/.prettierrc.js deleted file mode 100644 index 0892704ab0..0000000000 --- a/packages/customWidgets/calendar-custom-web/.prettierrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("@mendix/prettier-config-web-widgets"); diff --git a/packages/customWidgets/calendar-custom-web/CHANGELOG.md b/packages/customWidgets/calendar-custom-web/CHANGELOG.md deleted file mode 100644 index a5d8b74cb0..0000000000 --- a/packages/customWidgets/calendar-custom-web/CHANGELOG.md +++ /dev/null @@ -1,33 +0,0 @@ -# Changelog - -All notable changes to this widget will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -## [1.0.15] - 2024-04-29 - -### Fixed - -- We fixed an issue with the widget not working correctly for RTL locales. - -### Changed - -- We updated the light and dark icons and tiles for the widget. - -## [1.0.14] - 2022-11-23 - -### Changed - -- Update moment.js to version 2.29.4 - -## [1.0.13] - 2021-06-24 - -### Removed - -- We removed the option 'Show truncated events' - -### Changed - -- We changed the behavior when clicking '+ more' to redirect to day view. diff --git a/packages/customWidgets/calendar-custom-web/README.md b/packages/customWidgets/calendar-custom-web/README.md deleted file mode 100644 index 7a1e662838..0000000000 --- a/packages/customWidgets/calendar-custom-web/README.md +++ /dev/null @@ -1 +0,0 @@ -Please see [Calendar](https://docs.mendix.com/appstore/widgets/calendar) in the Mendix documentation for details. diff --git a/packages/customWidgets/calendar-custom-web/cypress/.eslintrc.json b/packages/customWidgets/calendar-custom-web/cypress/.eslintrc.json deleted file mode 100644 index e98e5a04cb..0000000000 --- a/packages/customWidgets/calendar-custom-web/cypress/.eslintrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "root": true, - "extends": ["@mendix/eslint-config-web-widgets/cypress"] -} diff --git a/packages/customWidgets/calendar-custom-web/cypress/integration/calendar.spec.js b/packages/customWidgets/calendar-custom-web/cypress/integration/calendar.spec.js deleted file mode 100644 index a7151fcc79..0000000000 --- a/packages/customWidgets/calendar-custom-web/cypress/integration/calendar.spec.js +++ /dev/null @@ -1,145 +0,0 @@ -// Variables being used along multiple test cases -const calendarSelector = ".mx-name-calendar"; -const calendarMonthViewSelector = ".rbc-month-view"; -const calendarSlotSelector = ".rbc-day-bg"; -const modalHeader = ".modal-dialog"; - -describe("Calendar", () => { - const cleanMendixSession = () => { - cy.window().then(window => { - // Cypress opens a new session for every test, so it exceeds mendix license limit of 5 sessions, we need to logout after each test. - window.mx.session.logout(); - }); - }; - - describe("with Datasource", () => { - afterEach(() => cleanMendixSession()); - - it("should render with a context datasource", () => { - cy.visit("/p/datasourceContext"); - cy.get(`${calendarSelector}1 ${calendarMonthViewSelector}`).should("be.visible"); - }); - - it("should render with a xpath datasource", () => { - cy.visit("/"); - cy.get(`${calendarSelector}1 ${calendarMonthViewSelector}`).should("be.visible"); - }); - - it("should render with a microflow datasource", () => { - cy.visit("/p/datasourceMicroflow"); - cy.get(`${calendarSelector}1 ${calendarMonthViewSelector}`).should("be.visible"); - }); - - it("should render with a nanoflow datasource", () => { - cy.visit("/p/datasourceNanoflow"); - cy.get(`${calendarSelector}1 ${calendarMonthViewSelector}`).should("be.visible"); - }); - }); - - describe("with errors", () => { - const alertSelector = ".alert.alert-danger.widget-calendar-alert"; - - afterEach(() => cleanMendixSession()); - - it("should show error if no onClick microflow configured", () => { - cy.visit("/p/noMicroflow"); - cy.get(alertSelector).contains("On click event is set to 'Call a microflow' but no microflow is selected"); - }); - - it("should show error if no onClick nanoflow configured", () => { - cy.visit("/p/noNanoflow"); - cy.get(alertSelector).contains("On click event is set to 'Call a nanoflow' but no nanoflow is selected"); - }); - - it("should show error if no datasource microflow configured", () => { - cy.visit("/p/noMicroflowDatasource"); - cy.get(alertSelector).contains("Datasource is set to 'microflow' but no microflow is selected"); - }); - - it("should show error if no datasource nanoflow configured", () => { - cy.visit("/p/noNanoflowDatasource"); - cy.get(alertSelector).contains("Datasource is set to 'nanoflow' but no nanoflow is selected"); - }); - }); - - describe("with on click", () => { - const calendarEventSelector = ".rbc-event-content"; - - beforeEach(() => { - cy.visit("/p/onClick"); - }); - - afterEach(() => cleanMendixSession()); - - it("on click microflow triggered", () => { - cy.get(`${calendarSelector}1 ${calendarEventSelector}`).should("be.visible"); - cy.get(`${calendarSelector}1 ${calendarEventSelector}`).first().click(); - cy.get(modalHeader).find("#mxui_widget_Window_0_caption").contains("Microflow"); - }); - - it("on click nanoflow triggered", () => { - cy.get(".mx-name-tabPage2").click(); - cy.get(`${calendarSelector}2 ${calendarEventSelector}`).should("be.visible"); - cy.get(`${calendarSelector}2 ${calendarEventSelector}`).first().click(); - cy.get(modalHeader).find("#mxui_widget_Window_0_caption").contains("Nanoflow"); - }); - }); - - describe("with on create", () => { - beforeEach(() => { - cy.visit("/p/onCreate"); - }); - - afterEach(() => cleanMendixSession()); - - it("should open create event page with Microflow", () => { - cy.get(`${calendarSelector}1 ${calendarSlotSelector}`).should("be.visible"); - cy.get(`${calendarSelector}1 ${calendarSlotSelector}`).first().click(); - cy.get(modalHeader).find("#mxui_widget_Window_0_caption").contains("Edit Event (Microflow)"); - }); - - it("should open create event page with Nanoflow", () => { - cy.get(".mx-name-tabPage2").click(); - cy.get(`${calendarSelector}2 ${calendarSlotSelector}`).should("be.visible"); - cy.get(`${calendarSelector}2 ${calendarSlotSelector}`).first().click(); - cy.get(modalHeader).find("#mxui_widget_Window_0_caption").contains("Edit Event (Nanoflow)"); - }); - }); - - describe("with different views", () => { - const daysDisplayedSelector = ".rbc-header"; - const labelSelector = ".calendar-label"; - const weekViewButtonSelector = ".btn.btn-default.toolbar-btn-week"; - const dayViewButtonSelector = ".btn.btn-default.toolbar-btn-day"; - - it("renders month view", () => { - cy.visit("/"); - cy.get(`${calendarSelector}1 ${calendarMonthViewSelector}`).should("be.visible"); - }); - - afterEach(() => cleanMendixSession()); - - it("renders week view", () => { - cy.visit("/"); - cy.get(weekViewButtonSelector).click(); - cy.get(`${calendarSelector}1 ${calendarSlotSelector}`).should("be.visible"); - cy.get(`${calendarSelector}1 ${daysDisplayedSelector}`).should("have.length", 7); - }); - it("renders day view", () => { - cy.visit("/"); - cy.get(dayViewButtonSelector).click(); - cy.get(`${calendarSelector}1 ${calendarSlotSelector}`).should("be.visible"); - cy.get(`${calendarSelector}1 ${daysDisplayedSelector}`).should("have.length", 1); - }); - it("renders start date attribute correctly", () => { - cy.visit("/p/startPosition"); - cy.get(`${calendarSelector}2 ${labelSelector}`).contains("Tuesday 02/02/2021"); - }); - it("renders correct start date after switching the object", () => { - cy.visit("/p/startPosition"); - cy.get(".mx-name-switchObjectButton").click(); - cy.wait(1000); - cy.get(`${calendarSelector}2 ${labelSelector}`).contains("Saturday 01/05/2021"); - }); - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/cypress/support/e2e.js b/packages/customWidgets/calendar-custom-web/cypress/support/e2e.js deleted file mode 100644 index 5f49ab7003..0000000000 --- a/packages/customWidgets/calendar-custom-web/cypress/support/e2e.js +++ /dev/null @@ -1 +0,0 @@ -import "../../../../../configs/e2e/cypress/support/command"; diff --git a/packages/customWidgets/calendar-custom-web/eslint.config.mjs b/packages/customWidgets/calendar-custom-web/eslint.config.mjs deleted file mode 100644 index ed68ae9e78..0000000000 --- a/packages/customWidgets/calendar-custom-web/eslint.config.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import config from "@mendix/eslint-config-web-widgets/widget-ts.mjs"; - -export default config; diff --git a/packages/customWidgets/calendar-custom-web/package.json b/packages/customWidgets/calendar-custom-web/package.json deleted file mode 100644 index 2d0544705f..0000000000 --- a/packages/customWidgets/calendar-custom-web/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "@mendix/calendar-custom-web", - "widgetName": "Calendar", - "version": "1.0.15", - "description": "Display and manage calendar events", - "copyright": "© Mendix Technology BV 2025. All rights reserved.", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/mendix/web-widgets.git" - }, - "config": {}, - "mxpackage": { - "name": "Calendar", - "type": "widget", - "mpkName": "Calendar.mpk" - }, - "packagePath": "com.mendix.widget.custom", - "marketplace": { - "minimumMXVersion": "7.14.1", - "appNumber": 107954, - "appName": "Calendar" - }, - "testProject": { - "githubUrl": "https://github.com/mendix/testProjects", - "branchName": "calendar-custom-web" - }, - "scripts": { - "build": "echo 'TODO: Fix calendar-custom-web build script'", - "create-gh-release": "rui-create-gh-release", - "fixme_build": "ts-node --project scripts/tsconfig.json scripts/build.ts development", - "fixme_release": "ts-node --project scripts/tsconfig.json scripts/build.ts production", - "format": "prettier --write .", - "lint": "eslint src/ package.json", - "publish-marketplace": "rui-publish-marketplace", - "release": "echo 'TODO: Fix calendar-custom-web release script'", - "update-changelog": "rui-update-changelog-widget", - "verify": "rui-verify-package-format" - }, - "dependencies": { - "classnames": "^2.5.1", - "date-arithmetic": "^3.1.0", - "loader-utils": "1.4.2", - "moment": "^2.30.1", - "react-big-calendar": "0.19.2", - "react-dnd": "2.6.0", - "react-dnd-html5-backend": "^5.0.1" - }, - "patchedDependencies": { - "react-big-calendar@0.19.2": "patches/react-big-calendar@0.19.2.patch" - } -} diff --git a/packages/customWidgets/calendar-custom-web/scripts/build.ts b/packages/customWidgets/calendar-custom-web/scripts/build.ts deleted file mode 100755 index efc78fa9a3..0000000000 --- a/packages/customWidgets/calendar-custom-web/scripts/build.ts +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env ts-node-script - -import { cp, mkdir, zip, exec } from "@mendix/automation-utils/shell"; -import { logStep, removeDist, runWidgetSteps, WidgetStepParams } from "@mendix/automation-utils/steps"; -import { dirname, join } from "node:path"; - -const [, , env] = process.argv; -const isProd = env === "production"; -const copyToProject = !isProd && process.env.MX_PROJECT_PATH; - -async function createMPK({ config }: WidgetStepParams): Promise { - logStep("Create mpk"); - const { paths, output } = config; - mkdir("-p", dirname(output.files.mpk)); - await zip(join(paths.tmp, "widgets"), output.files.mpk); -} - -async function main(): Promise { - await runWidgetSteps({ - packagePath: process.cwd(), - steps: [ - removeDist, - async () => { - logStep("Bundling"); - const wpc = isProd ? "webpack.config.prod.js" : "webpack.config.dev.js"; - await exec(`webpack -c ${wpc}`); - }, - createMPK, - async ({ config }) => { - if (copyToProject) { - logStep("Copy widget to targetProject"); - const dir = join(config.paths.targetProject, "widgets"); - mkdir("-p", dir); - cp(config.output.files.mpk, dir); - } - } - ] - }); -} - -main().catch(err => { - console.error(err); - process.exit(1); -}); diff --git a/packages/customWidgets/calendar-custom-web/scripts/tsconfig.json b/packages/customWidgets/calendar-custom-web/scripts/tsconfig.json deleted file mode 100644 index eeb4a6cc48..0000000000 --- a/packages/customWidgets/calendar-custom-web/scripts/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@mendix/automation-utils/tsconfig" -} diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.icon.dark.png b/packages/customWidgets/calendar-custom-web/src/Calendar.icon.dark.png deleted file mode 100644 index 3798dd6bef..0000000000 Binary files a/packages/customWidgets/calendar-custom-web/src/Calendar.icon.dark.png and /dev/null differ diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.icon.png b/packages/customWidgets/calendar-custom-web/src/Calendar.icon.png deleted file mode 100644 index 0bf35d34a1..0000000000 Binary files a/packages/customWidgets/calendar-custom-web/src/Calendar.icon.png and /dev/null differ diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.tile.dark.png b/packages/customWidgets/calendar-custom-web/src/Calendar.tile.dark.png deleted file mode 100644 index 891a0c25c2..0000000000 Binary files a/packages/customWidgets/calendar-custom-web/src/Calendar.tile.dark.png and /dev/null differ diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.tile.png b/packages/customWidgets/calendar-custom-web/src/Calendar.tile.png deleted file mode 100644 index be48898821..0000000000 Binary files a/packages/customWidgets/calendar-custom-web/src/Calendar.tile.png and /dev/null differ diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.webmodeler.ts b/packages/customWidgets/calendar-custom-web/src/Calendar.webmodeler.ts deleted file mode 100644 index 888389c0a0..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/Calendar.webmodeler.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { Component, createElement, ReactNode } from "react"; - -import { Calendar, CalendarProps } from "./components/Calendar"; -import { Container } from "./utils/namespaces"; -import { validateProps } from "./utils/validation"; -import { parseStyle } from "./utils/style"; - -declare function require(name: string): string; - -export class preview extends Component { - render(): ReactNode { - return createElement(Calendar, this.transformProps(this.props)); - } - - private transformProps(props: Container.CalendarContainerProps): CalendarProps { - const eventData = [ - { - title: "Leave", - allDay: true, - start: new Date(new Date().setDate(new Date().getDate() - 15)), - end: new Date(new Date().setDate(new Date().getDate() - 7)), - guid: "", - color: "" - }, - { - title: "Leave", - allDay: true, - start: new Date(new Date().setDate(new Date().getDate() - 9)), - end: new Date(new Date().setDate(new Date().getDate() - 5)), - guid: "", - color: "green" - }, - { - title: "BD", - allDay: true, - start: new Date(), - end: new Date(), - guid: "", - color: "red" - }, - { - title: "Bank Holiday", - allDay: true, - start: new Date(new Date().valueOf() + 6000 * 3600 * 24), - end: new Date(new Date().valueOf() + 9000 * 3600 * 24), - guid: "", - color: "grey" - }, - { - title: "Bank Holiday", - allDay: true, - start: new Date(new Date().valueOf() + 4000 * 3600 * 24), - end: new Date(new Date().valueOf() + 8000 * 3600 * 24), - guid: "", - color: "purple" - }, - { - title: "Leave", - allDay: true, - start: new Date(new Date().valueOf() + 10000 * 3600 * 24), - end: new Date(new Date().valueOf() + 14000 * 3600 * 24), - guid: "", - color: "" - } - ]; - const alertMessage = validateProps(this.props); - - return { - alertMessage, - color: props.eventColor, - customViews: props.customViews, - defaultView: props.defaultView, - enableCreate: props.enableCreate, - events: eventData, - height: props.height, - heightUnit: props.heightUnit, - messages: [], - startPosition: new Date(), - editable: props.editable, - style: parseStyle(props.style), - viewOption: props.view, - width: props.width, - widthUnit: props.widthUnit, - direction: "ltr" - }; - } -} - -export function getVisibleProperties( - valueMap: Container.CalendarContainerProps, - visibilityMap: VisibilityMap -): VisibilityMap { - visibilityMap.dataSourceMicroflow = valueMap.dataSource === "microflow"; - visibilityMap.entityConstraint = valueMap.dataSource === "XPath"; - visibilityMap.onClickMicroflow = valueMap.onClickEvent === "callMicroflow"; - visibilityMap.onClickNanoflow = valueMap.onClickEvent === "callNanoflow"; - if (valueMap.view === "standard") { - visibilityMap.view = false; - } - if (valueMap.defaultView !== "agenda") { - valueMap.customViews.forEach((_element, index) => { - visibilityMap.customViews[index].allDayText = false; - visibilityMap.customViews[index].textHeaderDate = false; - visibilityMap.customViews[index].textHeaderTime = false; - visibilityMap.customViews[index].textHeaderEvent = false; - visibilityMap.customViews[index].gutterDateFormat = false; - }); - } - if (valueMap.defaultView === "agenda") { - valueMap.customViews.forEach((_element, index) => { - visibilityMap.customViews[index].headerFormat = false; - }); - } - if (valueMap.defaultView === "month") { - valueMap.customViews.forEach((_element, index) => { - visibilityMap.customViews[index].gutterTimeFormat = false; - }); - } - if (valueMap.defaultView !== "month") { - valueMap.customViews.forEach((_element, index) => { - visibilityMap.customViews[index].cellDateFormat = false; - }); - } - - return visibilityMap; -} - -export function getPreviewCss(): string { - return require("./ui/Calendar.scss") + require("react-big-calendar/lib/css/react-big-calendar.css"); -} diff --git a/packages/customWidgets/calendar-custom-web/src/Calendar.xml b/packages/customWidgets/calendar-custom-web/src/Calendar.xml deleted file mode 100644 index 5b0d07fb90..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/Calendar.xml +++ /dev/null @@ -1,382 +0,0 @@ - - - Calendar - Display and manage calendar events - - iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA69JREFUeAHtWs1uEzEQtjeRKBISBw5wKD9vAVc4QFcgVA4hZyRoX6OvQUHiHOVABUKBC1zpYyCCgEMOIKQGKV0zs1qn3l27tnftrUO8UhV7djw/n2fGP11C4hMRiAisMwK0qfPD4TDNsmwfxm8qZEyTJNkZjUYTxXsjsm89iZEVEiaN8zhis+CRjDYn+dbTGAB00MANEx6dGBMZJjxSPW0AkApcNWKtBhjknNTH8XicyxoMBkzK4IjYQo+0JtUiwCDnHLnSuRhpTaoBAGY1zqfOXbJXWPNNBoC92BUe0dfZznOuymea66rxVXmqfls9uvExAlTI29J1SNvKU/G71rP2EdAGgKlqlgS6CY/ALm2ayDDhkQpvDAAedEDiaYrzjYdUqwXRt56+hS0l1uKUd7VE9NDxradxBHjw9UxERgDOBPaAlGprgOt1NyDfc1NiCoQ2I13bs/YRoK0BbU9zXc9oVZ+uhq19BEQAqiGzbn1tDWgLyN4n1j/88/cOOyYDSllKGFkkfbr77sHGB5SdvpmnJGP7cJVcu6+T6Yar5y/ieBmPDc0LAKLTn3/NH4FBl9AoVlyYZwv2HLo3kGbjPLKDiOul8Uhs8TgHAGf08Pf8FTh7WWUXOsHfQdto5jl/8dur9Bt33RdBxl6c5nxjS4WBjND3QrdV03kEgPOZxKIZ0PI0qL6DnJ7yKMD2ZPt86Y4B0wnS6Ic4nvbIuCqnad95BNCE7lJKvoFB3wmhL2mP3rt1ceOK0sCE7qDj+EegXeXDAgo0EbzZzQvnPlb5mvadR8Dk4QZ+D1DKayRsHRxJbSz4S7MuMtKMPIYIER76eu82XQiEVk3nEdDKmspgDP+MsW2R7DL8UW7QAPgO/+ABwM2TOPtQU5yGP8p2XgPKBpv35DvCcvbDNuhpenC0hcWyqB3mChSc4aSA4XY4XzKBV+GPNTkcAKxNdzMgHACK/YDOLdV+QTdO9T6YGiDuB9K387vsmOWnxcLwGW6mXK7/HJBwIoBbBL9dVH+uLjgAcPMDEOARevm43vwsBUMjOAC62PyIAHirAfJ1/UQ1nA3yRZ4XNb6udxn+aI2/CGi8rrP7JzDB3s/h0VeUy9v+AOAaLH/hKL28T4D2T5dHX5kp/gBouq5T+gwM/ZrfKVD6xMfSJwLhrQaI67qoUNcuxl3T8bl67y8CXFnoWU4EwDPAwYvX1gDdf1eD91BjYEwBCUBTCe1/IdV8q0WAwZeZqwqGky9XV9X5aHdEICIgR+AfGqgwglFLPQMAAAAASUVORK5CYII= - - - - Data source - Data source - - - Context - Database - Microflow - Nanoflow - - - - Event entity - Data source - With data context, this entity should be equal to the containing data view - - - XPath - Data source - Also allows the event objects to be constrained to a relation to context by using [%CurrentObject%] - - - Microflow - Data source - - - - - Nanoflow - Data source - - - - - Title attribute - Data source - - - - - - - All day attribute - Data source - - - - - - - Start attribute - Data source - - - - - - - End attribute - Data source - - - - - - - Color attribute - Data source - Attribute containing a valid html color eg: red #FF0000 rgb(250,10,20) rgba(10,10,10, 0.5) - - - - - - - Refresh data source on view change - Data source - For data source microflow, enable to retrieve a sub set of large data set based on view start and end attribute - - - View start attribute - Data source - The date on which the calendar view starts, will be updated with `Refresh data source` before the view changes - - - - - - View end attribute - Data source - The date on which the calendar view ends, will be updated with `Refresh data source` before the view changes - - - - - - View - View - Standard has Day, Week and Month - - Standard - Custom - - - - Initial selected view - View - Work week and agenda are only available in custom views - - Day - Week - Month - (Work week) - (Agenda) - - - - Start date attribute - View - The start date that should be shown in the view - - - - - - Custom top bar views - View - - - - Item - Appearance - - - Previous button - Today button - Next button - Title date text - Month button - Week button - Work week button - Day button - Agenda button - - - - Position - Appearance - - - Left - Center - Right - - - - Caption - Appearance - The text for the button or title. For type 'Title date text' this field will be replaced by defaults according to the language and view. - - - Render mode - Appearance - - - Button - Link - - - - Button tooltip - Appearance - - - - Button style - Appearance - - - Default - Primary - Success - Info - Inverse - Warning - Danger - - - - Header day format - Custom formats - Format of date(s) in the header above the day, week, month, work week or Agenda view. Use Mendix date formats. e.g. 'EEEE dd/MM' - - - Cell date format - Custom formats - Date shown in the month cells. Use Mendix date formats. e.g. 'dd' - - dd - dd - - - - Time gutter format - Custom formats - Time shown as the first column in the week, day and agenda view. Use Mendix date formats. e.g. HH:mm - - hh:mm a - HH:mm - - - - Date gutter format - Custom formats - Date shown as the first column in the agenda view. e.g. 'EEE MMM d' - - EEE dd/MM - EEE MM-dd - - - - Default all day text - Text - Text showing in the agenda view to indicate an event will be all day - - All day - Gehele dag - - - - Header date - Text - Text showing in the agenda view to header in the column date - - Date - Datum - - - - Header time - Text - Text showing in the agenda view to header in the column time - - Time - Tijd - - - - Header event - Text - Text showing in the agenda view to header in the column event - - Event - Afspraak - - - - - - Editable - View - - - Default - Never - - - - Enable create - View - - - - On click - Events - The click event is triggered when an exiting item is clicked on the calendar - - Do nothing - Call a microflow - Call a nanoflow - - - - On click microflow - Events - - - - - On click nanoflow - Events - - - - - On create - Events - The create event is triggered when a time slot is selected, and the 'Enable create' property is set to 'true' - - Do nothing - Call a microflow - Call a nanoflow - - - - Create association - Events - Association is set on create with the context - - - On create microflow - Events - - - - - On create nanoflow - Events - - - - - On change - Events - The change event is triggered on moving/dragging an item or changing the start or end time of by resizing an item - - Do nothing - Call a microflow - Call a nanoflow - - - - On change microflow - Events - - - - - On change nanoflow - Events - - - - - Width unit - Size - - - Percentage - Pixels - - - - Width - Size - - - - Height unit - Size - 'Percentage of width' is the aspect ratio, 'Pixels' is absolute. Warning: When using 'Percentage of parent' the parent container must have an absolute height, else nothing is displayed. - - Percentage of width - Pixels - Percentage of parent - - - - Height - Size - - - - diff --git a/packages/customWidgets/calendar-custom-web/src/components/Alert.ts b/packages/customWidgets/calendar-custom-web/src/components/Alert.ts deleted file mode 100644 index eeca10ff88..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/Alert.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createElement, FunctionComponent, PropsWithChildren } from "react"; -import classNames from "classnames"; - -export interface AlertProps { - bootstrapStyle?: "default" | "primary" | "success" | "info" | "warning" | "danger"; - className?: string; -} - -export const Alert: FunctionComponent> = ({ bootstrapStyle, className, children }) => - children - ? createElement("div", { className: classNames(`alert alert-${bootstrapStyle}`, className) }, children) - : null; - -Alert.displayName = "Alert"; -Alert.defaultProps = { bootstrapStyle: "danger" }; diff --git a/packages/customWidgets/calendar-custom-web/src/components/Button.ts b/packages/customWidgets/calendar-custom-web/src/components/Button.ts deleted file mode 100644 index 8b4d0b6dd5..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/Button.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { createElement, FunctionComponent, ReactNode } from "react"; -import classNames from "classnames"; - -export interface ButtonProps { - renderMode: "button" | "link"; - title?: string; - className?: string; - buttonStyle?: ButtonStyle; - icon?: string; - iconPosition?: "left" | "right"; - active: boolean; - caption: ReactNode; - onClick: () => void; -} - -export type ButtonStyle = "default" | "primary" | "success" | "info" | "inverse" | "warning" | "danger"; - -export const addIcon = (icon?: string, iconPosition?: "left" | "right", content?: ReactNode): ReactNode => { - if (icon) { - if (iconPosition === "right") { - return [content, content ? " " : null, createElement("span", { className: icon })]; - } else { - return [createElement("span", { className: icon }), content ? " " : null, content]; - } - } else { - return content; - } -}; - -export const ToolbarButton: FunctionComponent = props => - props.renderMode === "button" ? Button(props) : Link(props); - -ToolbarButton.defaultProps = { buttonStyle: "default", renderMode: "button", iconPosition: "left" }; - -export const Button: FunctionComponent = ({ - title, - className, - caption, - onClick, - buttonStyle, - active, - icon, - iconPosition -}) => - createElement( - "button", - { - className: classNames("btn", `btn-${buttonStyle}`, className, { active }), - title, - onClick - }, - addIcon(icon, iconPosition, caption) - ); - -const Link: FunctionComponent = ({ title, className, caption, onClick, active, icon, iconPosition }) => - createElement( - "span", - { - className: classNames("mx-link", className, { active }), - tabindex: "0", - title, - onClick - }, - addIcon(icon, iconPosition, createElement("a", { tabindex: "-1" }, caption)) - ); diff --git a/packages/customWidgets/calendar-custom-web/src/components/Calendar.ts b/packages/customWidgets/calendar-custom-web/src/components/Calendar.ts deleted file mode 100644 index aec44cab89..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/Calendar.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { Component, createElement, CSSProperties, ReactNode } from "react"; - -import { Alert } from "./Alert"; -import { Container, Style } from "../utils/namespaces"; -import classNames from "classnames"; -import BigCalendar from "react-big-calendar"; -import moment from "moment"; -import withDragAndDrop from "react-big-calendar/lib/addons/dragAndDrop"; -import CustomToolbar from "./Toolbar"; -import { SizeContainer } from "./SizeContainer"; - -import { CalendarLoader } from "./CalendarLoader"; - -import "react-big-calendar/lib/addons/dragAndDrop/styles.css"; -import "react-big-calendar/lib/css/react-big-calendar.css"; -import "../ui/Calendar.scss"; -import "../ui/CalendarLoader.scss"; - -const localizer = BigCalendar.momentLocalizer(moment); -const DragAndDropCalendar = withDragAndDrop(BigCalendar); - -export interface CalendarProps { - alertMessage?: ReactNode; - className?: string; - events: CalendarEvent[]; - color?: string; - formats?: object; - enableCreate: boolean; - height: number; - heightUnit: Style.HeightUnitType; - defaultView: Style.View; - loading?: boolean; - startPosition?: Date; - messages: object; - editable: string; - titleFormat?: (date: Date) => void; - weekdayFormat?: (date: Date) => void; - timeGutterFormat?: (date: Date) => void; - monthHeaderFormat?: (date: Date) => void; - dayHeaderFormat?: (date: Date) => void; - style: CSSProperties; - viewOption: "custom" | "standard"; - width: number; - widthUnit: Style.WidthUnitType; - onRangeChangeAction?: (date: object) => void; - onSelectEventAction?: (eventInfo: object) => void; - onEventResizeAction?: (eventInfo: object) => void; - onSelectSlotAction?: (slotInfo: object) => void; - onEventDropAction?: (eventInfo: object) => void; - customViews: Container.CustomViews[]; - direction: "rtl" | "ltr"; -} - -interface HOCToolbarProps { - customViews: Container.CustomViews[] | Array>; - onClickToolbarButton: (date: object) => void; -} - -export interface CalendarEvent { - allDay: boolean; - color: string; - end: Date; - guid: string; - start: Date; - title: string; -} - -interface State { - date?: Date; -} - -class Calendar extends Component { - readonly state: State = { - date: undefined - }; - - private readonly onNavigateHandler = this.onNavigate.bind(this); - - render(): ReactNode { - return createElement( - SizeContainer, - { - className: classNames("widget-calendar", this.props.className), - style: this.props.style, - widthUnit: this.props.widthUnit, - width: this.props.width, - heightUnit: this.props.heightUnit, - height: this.props.height - }, - this.renderAlert(), - this.renderCalendar() - ); - } - - private getDefaultToolbar(): Array> { - return [ - { - customView: "previous", - position: "left", - buttonToolTip: "previous" - }, - { - customView: "today", - position: "left", - customCaption: "today" - }, - { - customView: "next", - position: "left", - buttonToolTip: "next" - }, - { - customView: "title", - position: "center" - }, - { - customView: "day", - position: "right", - customCaption: "day" - }, - { - customView: "week", - position: "right", - customCaption: "week" - }, - { - customView: "month", - position: "right", - customCaption: "month" - } - ]; - } - - private renderAlert(): ReactNode { - return createElement(Alert, { className: "widget-calendar-alert" }, this.props.alertMessage); - } - - private onNavigate(date: Date): void { - this.setState({ date }); - } - - private renderCalendar(): ReactNode { - const wrapToolbar = - (injectedProps: HOCToolbarProps): ((toolbarProps: Container.ToolbarProps) => void) => - (toolbarProps: Container.ToolbarProps) => - createElement(CustomToolbar as any, { ...injectedProps, ...toolbarProps }); - - const props = { - localizer, - rtl: this.props.direction === "rtl", - events: this.props.events, - allDayAccessor: this.allDayAccessor, - components: { - toolbar: wrapToolbar({ customViews: this.getToolbarProps(), onClickToolbarButton: this.onRangeChange }) - }, - onNavigate: this.onNavigateHandler, - eventPropGetter: this.eventColor, - date: this.state.date ?? this.props.startPosition, - defaultView: this.defaultView(), - formats: this.props.viewOption === "custom" ? this.props.formats : "", - messages: this.props.viewOption === "custom" ? this.props.messages : "", - popup: false, - selectable: this.props.enableCreate, - step: 60, - showMultiDayTimes: true, - onRangeChange: this.onRangeChange, - onSelectEvent: this.onSelectEvent, - onSelectSlot: this.onSelectSlot, - views: ["month", "day", "week", "work_week", "month", "agenda"] - }; - - if (this.props.loading) { - return createElement(CalendarLoader); - } else if (this.props.enableCreate && this.props.editable === "default") { - return createElement(DragAndDropCalendar, { - ...props, - onEventDrop: this.onEventDrop, - onEventResize: this.onEventResize - }); - } else { - return createElement(BigCalendar, props); - } - } - - private defaultView(): Style.View { - if ( - this.props.viewOption === "standard" && - (this.props.defaultView === "work_week" || this.props.defaultView === "agenda") - ) { - return "month"; - } - - return this.props.defaultView; - } - - private getToolbarProps(): Array> { - const toolbarProps = this.props.viewOption === "standard" ? this.getDefaultToolbar() : this.props.customViews; - - return toolbarProps.map(customView => ({ ...customView, onClickToolbarButton: this.onRangeChange })); - } - - private allDayAccessor = (event: Container.ViewOptions) => event.allDay; - - private eventColor = (events: CalendarEvent) => ({ style: { backgroundColor: events.color } }); - - private onRangeChange = (date: object) => { - if (this.props.onRangeChangeAction && date) { - this.props.onRangeChangeAction(date); - } - }; - - private onEventDrop = (eventInfo: Container.EventInfo) => { - if ( - eventInfo.start.getTime() !== eventInfo.event.start.getTime() && - this.props.editable === "default" && - this.props.onEventDropAction - ) { - this.props.onEventDropAction(eventInfo); - } - }; - - private onEventResize = (_resizeType: string, eventInfo: Container.EventInfo) => { - if ( - (eventInfo.start.getTime() !== eventInfo.event.start.getTime() || - eventInfo.end.getTime() !== eventInfo.event.end.getTime()) && - eventInfo.start.getTime() < eventInfo.end.getTime() && - this.props.editable && - this.props.onEventResizeAction - ) { - this.props.onEventResizeAction(eventInfo); - } - }; - - private onSelectEvent = (eventInfo: object) => { - if (this.props.onSelectEventAction) { - this.props.onSelectEventAction(eventInfo); - } - }; - - private onSelectSlot = (slotInfo: object) => { - if (this.props.onSelectSlotAction) { - this.props.onSelectSlotAction(slotInfo); - } - }; -} - -export { Calendar, Calendar as MyCalendar }; diff --git a/packages/customWidgets/calendar-custom-web/src/components/CalendarContainer.ts b/packages/customWidgets/calendar-custom-web/src/components/CalendarContainer.ts deleted file mode 100644 index 8d6d913175..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/CalendarContainer.ts +++ /dev/null @@ -1,544 +0,0 @@ -import { Component, createElement, ReactChild, ReactNode } from "react"; - -import { Calendar, CalendarEvent } from "./Calendar"; -import { fetchData } from "../utils/data"; -import { Container } from "../utils/namespaces"; -import dateMath from "date-arithmetic"; -import moment from "moment"; -import { validateCustomFormats, validateProps } from "../utils/validation"; -import { parseStyle } from "../utils/style"; - -type MxObject = Omit & { - fetch: (path: string, callback: (requested: any) => void, error: (error: Error) => void) => void; -}; - -export interface CalendarContainerState { - alertMessage: ReactChild; - events: CalendarEvent[]; - eventCache: MxObject[]; - eventColor: string; - loading: boolean; - startPosition: Date; -} - -interface ViewDate { - start: Date; - end: Date; -} - -export default class CalendarContainer extends Component { - private subscriptionContextHandles: number[] = []; - private subscriptionEventHandles: number[] = []; - private progressHandle?: number; - private destroyed = false; - - readonly state: CalendarContainerState = { - alertMessage: "", - events: [], - eventCache: [], - eventColor: "", - loading: true, - startPosition: new Date() - }; - - constructor(props: Container.CalendarContainerProps) { - super(props); - this.resetSubscriptions(props.mxObject); - } - - UNSAFE_componentWillMount(): void { - const [locale] = window.mx.session.sessionData.locale.code.split("_"); - moment.updateLocale(locale, { - week: { dow: window.mx.session.sessionData.locale.firstDayOfWeek, doy: 6 } - }); - } - - render(): ReactNode { - const readOnly = this.isReadOnly(); - const alertMessage = this.state.alertMessage || validateProps(this.props) || validateCustomFormats(this.props); - - return createElement( - "div", - { - style: this.state.loading ? { ...parseStyle(this.props.style) } : undefined - }, - createElement(Calendar, { - alertMessage, - className: this.props.class, - editable: this.props.editable, - enableCreate: this.props.enableCreate, - formats: this.setCalendarFormats(), - height: this.props.height, - heightUnit: this.props.heightUnit, - messages: this.setCustomViews(), - events: this.state.events, - defaultView: this.props.defaultView, - startPosition: this.state.startPosition, - loading: this.state.loading, - style: parseStyle(this.props.style), - viewOption: this.props.view, - width: this.props.width, - widthUnit: this.props.widthUnit, - onRangeChangeAction: this.onRangeChange, - onSelectEventAction: !readOnly ? this.handleOnClickEvent : undefined, - onEventResizeAction: !readOnly ? this.handleOnChangeEvent : undefined, - onSelectSlotAction: !readOnly ? this.onClickSlot : undefined, - onEventDropAction: !readOnly ? this.handleOnChangeEvent : undefined, - customViews: this.props.customViews, - direction: (window.mx.session.sessionData as any).uiconfig.direction - }) - ); - } - - componentWillUnmount(): void { - this.destroyed = true; - this.subscriptionContextHandles.forEach(window.mx.data.unsubscribe); - this.subscriptionEventHandles.forEach(window.mx.data.unsubscribe); - } - - // Note that React will not await this function to call the render function - async UNSAFE_componentWillReceiveProps(nextProps: Container.CalendarContainerProps): Promise { - if (nextProps.mxObject) { - if (!this.state.alertMessage) { - await this.loadEvents(nextProps.mxObject); - } - this.resetSubscriptions(nextProps.mxObject); - } else { - this.setState({ events: [], loading: false }); - } - } - - private isReadOnly(): boolean { - return !this.props.mxObject || !this.props.editable || this.props.readOnly; - } - - private extractAttributeValue = async ( - mxObject: MxObject, - attributePath: string - ): Promise => { - if (!attributePath) { - return Promise.resolve(undefined); - } - - return new Promise((resolve, reject) => { - mxObject.fetch( - attributePath, - (attributeValue: any): void => { - if (attributeValue instanceof Error) { - reject(attributeValue); - } else { - resolve(attributeValue); - } - }, - (error: Error): void => reject(error) - ); - }); - }; - - private getStartPosition = async (mxObject: MxObject): Promise => { - if (mxObject) { - let startDateAttributeValue; - try { - startDateAttributeValue = await this.extractAttributeValue( - mxObject, - this.props.startDateAttribute - ); - } catch (error) { - window.mx.ui.error(`Unable to fetch start date attribute value: ${error.message}`); - } - return startDateAttributeValue ? new Date(startDateAttributeValue) : new Date(); - } - - return new Date(); - }; - - private loadEvents = async (mxObject: MxObject): Promise => { - this.subscriptionEventHandles.forEach(window.mx.data.unsubscribe); - this.subscriptionEventHandles = []; - if (!mxObject) { - return; - } - await this.setViewDates(mxObject); - const guid = mxObject ? mxObject.getGuid() : ""; - if (this.props.dataSource === "context" && mxObject) { - this.setCalendarEvents([mxObject]); - } else { - try { - const mxEventObjects = await fetchData({ - guid, - type: this.props.dataSource, - entity: this.props.eventEntity, - constraint: this.props.entityConstraint, - microflow: this.props.dataSourceMicroflow, - mxform: this.props.mxform, - nanoflow: this.props.dataSourceNanoflow - }); - - if (this.destroyed) { - return; - } - - mxEventObjects.forEach( - mxEventObject => - (this.subscriptionEventHandles = [ - ...this.subscriptionEventHandles, - ...this.subscribeToEventAttributes(mxEventObject) - ]) - ); - - this.setCalendarEvents(mxEventObjects); - - if (this.progressHandle) { - mx.ui.hideProgress(this.progressHandle); - this.progressHandle = undefined; - } - } catch (e) { - window.mx.ui.error(e); - } - } - }; - - private async setViewDates(mxObject: MxObject): Promise { - const startPosition = await this.getStartPosition(mxObject); - if ( - this.props.executeOnViewChange && - mxObject.get(this.props.viewStartAttribute) === "" && - mxObject.get(this.props.viewEndAttribute) === "" - ) { - const viewStart = new Date(startPosition.getFullYear(), startPosition.getMonth(), 1); - const viewEnd = new Date(startPosition.getFullYear(), startPosition.getMonth() + 1, 0); - if (this.props.defaultView === "day") { - mxObject.set(this.props.viewStartAttribute, dateMath.startOf(startPosition, "day")); - mxObject.set(this.props.viewEndAttribute, dateMath.endOf(startPosition, "day")); - } else if (this.props.defaultView === "week" || this.props.defaultView === "work_week") { - mxObject.set( - this.props.viewStartAttribute, - dateMath.startOf(startPosition, "week", [window.mx.session.sessionData.locale.firstDayOfWeek]) - ); - - mxObject.set( - this.props.viewEndAttribute, - dateMath.endOf( - new Date( - startPosition.setDate(startPosition.getDate() + (this.props.defaultView === "week" ? 6 : 4)) - ), - "day" - ) - ); - } else { - mxObject.set(this.props.viewStartAttribute, dateMath.startOf(viewStart, "month")); - mxObject.set(this.props.viewEndAttribute, dateMath.endOf(viewEnd, "month")); - } - } - this.setState({ startPosition }); - } - - private setCalendarEvents = (mxObjects: MxObject[]): void => { - if (mxObjects) { - const events = mxObjects.map(mxObject => ({ - title: (mxObject.get(this.props.titleAttribute) as string) || " ", - allDay: mxObject.get(this.props.allDayAttribute) as boolean, - start: new Date(mxObject.get(this.props.startAttribute) as number), - end: new Date(mxObject.get(this.props.endAttribute) as number), - color: mxObject.get(this.props.eventColor) as string, - guid: mxObject.getGuid() - })); - this.setState({ events, eventCache: mxObjects, loading: false }); - } - }; - - private subscribeToEventAttributes(mxEventObject: MxObject): number[] { - return [ - this.props.allDayAttribute, - this.props.titleAttribute, - this.props.startAttribute, - this.props.endAttribute, - this.props.eventColor - ].map(attr => - window.mx.data.subscribe({ - attr, - callback: () => this.loadEvents(this.props.mxObject), - guid: mxEventObject.getGuid() - }) - ); - } - - private resetSubscriptions = (mxObject: MxObject): void => { - this.subscriptionContextHandles.forEach(window.mx.data.unsubscribe); - this.subscriptionContextHandles = []; - - if (mxObject) { - const attributePathValues = this.props.startDateAttribute.split("/"); - - if (attributePathValues.length > 2) { - const [referenceAttribute, , attr] = attributePathValues; - - this.subscriptionContextHandles.push( - window.mx.data.subscribe({ - guid: mxObject.get(referenceAttribute) as string, - attr, - callback: () => this.loadEvents(mxObject) - }) - ); - } - this.subscriptionContextHandles.push( - window.mx.data.subscribe({ - guid: mxObject.getGuid(), - attr: attributePathValues[0], - callback: () => { - this.loadEvents(mxObject); - - if (attributePathValues.length > 2) { - this.resetSubscriptions(mxObject); - } - } - }) - ); - - this.subscriptionContextHandles.push( - window.mx.data.subscribe({ - entity: this.props.eventEntity, - callback: () => this.loadEvents(mxObject) - }) - ); - this.subscriptionContextHandles.push( - window.mx.data.subscribe({ - guid: mxObject.getGuid(), - callback: () => this.loadEvents(mxObject) - }) - ); - if (this.props.dataSource === "context" && mxObject.getEntity() === this.props.eventEntity) { - this.subscriptionContextHandles = [ - ...this.subscriptionContextHandles, - ...this.subscribeToEventAttributes(mxObject) - ]; - } - } - }; - - private setCustomViews = (): Container.ViewOptions => { - return this.props.customViews.reduce( - (accumulator: Container.ViewOptions, customView: Container.CustomViews) => { - if (customView.customView === "agenda") { - accumulator.allDay = customView.allDayText; - accumulator.date = customView.textHeaderDate; - accumulator.time = customView.textHeaderTime; - accumulator.event = customView.textHeaderEvent; - } - - return accumulator; - }, - {} - ); - }; - - private setCalendarFormats = (): Container.ViewOptions => { - const calendarFormats: Container.ViewOptions = {}; - - this.props.customViews.forEach((customView: Container.CustomViews) => { - calendarFormats.dateFormat = - customView.customView === "month" - ? this.customFormat(customView.cellDateFormat, "date") - : calendarFormats.dateFormat; - calendarFormats.dayFormat = - customView.customView === "day" || - customView.customView === "week" || - customView.customView === "work_week" - ? this.customFormat(customView.gutterDateFormat, "day") - : calendarFormats.dayFormat; - calendarFormats.weekdayFormat = - customView.customView === "month" - ? this.customFormat(customView.headerFormat, "weekday") - : calendarFormats.weekdayFormat; - calendarFormats.timeGutterFormat = - customView.customView === "week" || - customView.customView === "day" || - customView.customView === "work_week" - ? this.customFormat(customView.gutterTimeFormat, "timeGutter") - : calendarFormats.timeGutterFormat; - - if (customView.headerFormat) { - switch (customView.customView) { - case "day": - calendarFormats.dayHeaderFormat = this.customFormat(customView.headerFormat); - break; - case "week": - case "work_week": - calendarFormats.dayRangeHeaderFormat = this.customRangeFormat(customView.headerFormat); - break; - case "month": - calendarFormats.monthHeaderFormat = this.customFormat(customView.headerFormat); - break; - case "agenda": - calendarFormats.agendaHeaderFormat = this.customRangeFormat(customView.headerFormat); - break; - } - } - }); - - return calendarFormats; - }; - - private customFormat = (dateFormat: string, dateType?: Container.DateType): ((date: Date) => string) => { - let datePattern = ""; - if (dateType === "date") { - datePattern = dateFormat || "dd"; - } else if (dateType === "day") { - datePattern = dateFormat || "EEE dd/MM"; - } else if (dateType === "weekday") { - datePattern = dateFormat || "EEEE"; - } else if (dateType === "timeGutter") { - datePattern = dateFormat || "hh:mm a"; - } else { - datePattern = dateFormat; - } - - return (date: Date) => window.mx.parser.formatValue(date, "datetime", { datePattern }); - }; - - private customRangeFormat = (dateFormat: string): ((dateRange: { start: Date; end: Date }) => string) => { - const datePattern = dateFormat; - return (dateRange: { start: Date; end: Date }) => { - return `${window.mx.parser.formatValue(dateRange.start, "datetime", { - datePattern - })} - ${window.mx.parser.formatValue(dateRange.end, "datetime", { datePattern })}`; - }; - }; - - private onRangeChange = async (date: ViewDate): Promise => { - if (!this.props.executeOnViewChange) { - return; - } - if (date.start) { - const middle = new Date((date.start.getTime() + date.end.getTime()) / 2); - - if (date && this.props.mxObject) { - this.props.mxObject.set(this.props.viewStartAttribute, dateMath.startOf(middle, "month")); - this.props.mxObject.set(this.props.viewEndAttribute, dateMath.endOf(middle, "month")); - } - } else { - if (date) { - const startDate = Array.isArray(date) ? date[0] : date.start; - const endDate = Array.isArray(date) ? date[date.length - 1] || date[0] : date.end; - this.props.mxObject.set(this.props.viewStartAttribute, dateMath.startOf(startDate, "day")); - this.props.mxObject.set(this.props.viewEndAttribute, dateMath.endOf(endDate, "day")); - } - } - if (!this.progressHandle) { - this.progressHandle = mx.ui.showProgress(); - } - await this.loadEvents(this.props.mxObject); - }; - - private handleOnClickEvent = (eventInfo: Container.EventInfo): void => { - mx.data.get({ - guid: eventInfo.guid, - callback: this.executeEventAction, - error: error => window.mx.ui.error(`Error while executing action: ${error.message}`) - }); - }; - - private executeEventAction = (mxObject: MxObject): void => { - const { onClickEvent, onClickMicroflow, mxform, onClickNanoflow } = this.props; - if (mxObject) { - this.executeAction(mxObject, onClickEvent, onClickMicroflow, mxform, onClickNanoflow); - } - }; - - private onClickSlot = (slotInfo: Container.EventInfo): void => { - const { start, end, slots } = slotInfo; - mx.data.create({ - entity: this.props.eventEntity, - callback: newEvent => { - const daysInBetween = dateMath.diff(start, end, "day", false); - if (daysInBetween === 0 && slots.length > 1) { - newEvent.set(this.props.startAttribute, start); - newEvent.set(this.props.endAttribute, end); - } else { - newEvent.set(this.props.startAttribute, dateMath.startOf(start, "day")); - newEvent.set(this.props.endAttribute, dateMath.endOf(end, "day")); - } - if ( - this.props.mxObject && - this.props.newEventContextPath && - this.props.newEventContextPath.split("/")[1] === this.props.mxObject.getEntity() - ) { - newEvent.set(this.props.newEventContextPath.split("/")[0], this.props.mxObject.getGuid()); - } else { - window.logger.warn("Event entity should not be same as context entity"); - } - this.executeSlotAction(newEvent); - }, - error: error => window.mx.ui.error(`Error while creating a new event: ${error.message}`) - }); - }; - - private executeSlotAction(mxObject: MxObject): void { - const { onCreate, onCreateMicroflow, mxform, onCreateNanoflow } = this.props; - this.executeAction(mxObject, onCreate, onCreateMicroflow, mxform, onCreateNanoflow); - } - - private handleOnChangeEvent = (eventInfo: Container.EventInfo): void => { - const { events } = this.state; - const eventPosition = events.findIndex(value => value.guid === eventInfo.event.guid); - if (eventPosition === -1) { - return; - } - const updatedEvent: CalendarEvent = { - title: eventInfo.event.title, - allDay: eventInfo.event.allDay, - start: eventInfo.start, - end: eventInfo.end, - guid: eventInfo.event.guid, - color: eventInfo.event.color - }; - const nextEvents = [...events]; - nextEvents.splice(eventPosition, 1, updatedEvent); - this.setState({ events: nextEvents }); - const mxEventObject = this.state.eventCache.filter(object => object.getGuid() === eventInfo.event.guid)[0]; - if (mxEventObject) { - setTimeout(() => { - mxEventObject.set(this.props.titleAttribute, eventInfo.event.title); - mxEventObject.set(this.props.eventColor, eventInfo.event.color); - mxEventObject.set(this.props.startAttribute, eventInfo.start); - mxEventObject.set(this.props.endAttribute, eventInfo.end); - this.executeOnDropAction(mxEventObject); - }, 50); - } - }; - - private executeOnDropAction = (mxObject: MxObject): void => { - const { onChangeEvent, onChangeMicroflow, mxform, onChangeNanoflow } = this.props; - if (mxObject && mxObject.getGuid()) { - this.executeAction(mxObject, onChangeEvent, onChangeMicroflow, mxform, onChangeNanoflow); - } - }; - - private executeAction( - mxObject: MxObject, - action: Container.OnClickEventOptions, - microflow: string, - mxform: mxui.lib.form._FormBase, - nanoflow: mx.Nanoflow - ): void { - const context = new mendix.lib.MxContext(); - context.setContext(mxObject.getEntity(), mxObject.getGuid()); - if (action === "callMicroflow" && microflow && mxObject.getGuid()) { - window.mx.data.action({ - context, - origin: mxform, - params: { - actionname: microflow - }, - error: error => window.mx.ui.error(`Error while executing microflow: ${microflow}: ${error.message}`) - }); - } else if (action === "callNanoflow" && nanoflow.nanoflow) { - window.mx.data.callNanoflow({ - nanoflow, - origin: mxform, - context, - error: error => window.mx.ui.error(`An error occurred while executing the nanoflow: ${error.message}`) - }); - } - } -} diff --git a/packages/customWidgets/calendar-custom-web/src/components/CalendarLoader.ts b/packages/customWidgets/calendar-custom-web/src/components/CalendarLoader.ts deleted file mode 100644 index 1ad5d2a87b..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/CalendarLoader.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createElement, FunctionComponent, ReactElement } from "react"; -import "../ui/CalendarLoader.scss"; - -export const CalendarLoader: FunctionComponent = () => - createElement( - "div", - { className: "widget-calendar-loading-wrapper" }, - createElement("div", { className: "widget-calendar-loading-indicator" }, ...generateDivs(12)) - ); - -export const generateDivs = (amount: number): Array> => { - const divs: Array> = []; - for (let i = 0; i < amount; i++) { - divs.push(createElement("div")); - } - - return divs; -}; - -CalendarLoader.displayName = "CalendarLoading"; diff --git a/packages/customWidgets/calendar-custom-web/src/components/SizeContainer.ts b/packages/customWidgets/calendar-custom-web/src/components/SizeContainer.ts deleted file mode 100644 index f322336ac0..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/SizeContainer.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { createElement, CSSProperties, FunctionComponent, PropsWithChildren } from "react"; -import classNames from "classnames"; - -export type HeightUnitType = "percentageOfWidth" | "percentageOfParent" | "pixels"; - -export type WidthUnitType = "percentage" | "pixels"; - -export interface Dimensions { - widthUnit: WidthUnitType; - width: number; - heightUnit: HeightUnitType; - height: number; -} - -export interface SizeProps extends Dimensions { - className: string; - style?: CSSProperties; -} - -export const SizeContainer: FunctionComponent> = ({ - className, - widthUnit, - width, - heightUnit, - height, - children, - style -}) => { - const styleWidth = widthUnit === "percentage" ? `${width}%` : `${width}px`; - - return createElement( - "div", - { - className: classNames(className, "size-box"), - style: { - position: "relative", - width: styleWidth, - ...getHeight(heightUnit, height), - ...style - }, - ref: parentHeight - }, - createElement( - "div", - { - className: "size-box-inner", - style: { - position: "absolute", - top: "0", - right: "0", - bottom: "0", - left: "0" - } - }, - children - ) - ); -}; - -const parentHeight = (node?: HTMLElement | null): void => { - // Fix for percentage height of parent. - // There no other way to control widget wrapper style - if (node && node.parentElement) { - node.parentElement.style.height = "100%"; - } -}; - -const getHeight = (heightUnit: HeightUnitType, height: number): CSSProperties => { - const style: CSSProperties = {}; - - if (heightUnit === "percentageOfWidth") { - style.height = "auto"; - style.paddingBottom = `${height}%`; - } else if (heightUnit === "pixels") { - style.height = `${height}px`; - } else if (heightUnit === "percentageOfParent") { - style.height = `${height}%`; - } - - return style; -}; diff --git a/packages/customWidgets/calendar-custom-web/src/components/Toolbar.ts b/packages/customWidgets/calendar-custom-web/src/components/Toolbar.ts deleted file mode 100644 index a8d9989e87..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/Toolbar.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { createElement, ReactNode } from "react"; -import classNames from "classnames"; -import Toolbar from "react-big-calendar/lib/Toolbar"; -import { Container, Style } from "../utils/namespaces"; -import { ToolbarButton } from "./Button"; - -export default class CustomToolbar extends Toolbar { - render(): ReactNode { - const isView = (customView: Container.ButtonConfig): boolean => - customView.customView === "day" || - customView.customView === "week" || - customView.customView === "month" || - customView.customView === "work_week" || - customView.customView === "agenda"; - let activeViews: Container.ButtonConfig[] = this.props.customViews; - const countViews = activeViews.filter(customView => isView(customView)).length; - if (countViews === 1) { - if (activeViews.length <= 1) { - return null; - } - activeViews = activeViews.filter(customView => !isView(customView)); - } - - const leftButton = this.filterPosition(activeViews, "left"); - const centerButton = this.filterPosition(activeViews, "center"); - const rightButton = this.filterPosition(activeViews, "right"); - - return createElement( - "div", - { className: classNames("calendar-toolbar") }, - this.createGroupButton(leftButton, "left"), - this.createGroupButton(centerButton, "center"), - this.createGroupButton(rightButton, "right") - ); - } - - private filterPosition(customViews: Container.ButtonConfig[], position: string): Container.ButtonConfig[] { - return customViews.filter((customView: Container.ButtonConfig) => customView.position === position); - } - - private createGroupButton(views: Container.ButtonConfig[], position: Style.Position): ReactNode { - return createElement( - "div", - { className: classNames(`align-${position}`, { "btn-group": true }) }, - views.map(view => this.createToolbarElement(view)) - ); - } - - private createToolbarElement(view: Container.ButtonConfig): ReactNode { - if (view.customView === "title") { - return createElement("span", { className: "calendar-label" }, this.props.label); - } - - return createElement(ToolbarButton, { - renderMode: view.renderMode, - className: `toolbar-btn-${view.customView}`, - active: this.props.view === view.customView, - title: view.buttonToolTip, - icon: this.getIcon(view), - iconPosition: this.getIconPosition(view), - caption: view.customCaption, - onClick: this.getOnClickFunction(view) - }); - } - - private getOnClickFunction(view: Container.ButtonConfig): () => void { - if (view.customView === "previous") { - return () => { - this.props.onNavigate("PREV"); - if (this.props.onClickToolbarButton) { - this.props.onClickToolbarButton(); - } - }; - } else if (view.customView === "next") { - return () => { - this.props.onNavigate("NEXT"); - if (this.props.onClickToolbarButton) { - this.props.onClickToolbarButton(); - } - }; - } else if (view.customView === "today") { - return () => { - this.props.onNavigate("TODAY"); - if (this.props.onClickToolbarButton) { - this.props.onClickToolbarButton(); - } - }; - } - - return () => { - if (this.props.view !== view.customView) { - this.props.onViewChange(view.customView); - } - }; - } - - private getIcon(view: Container.ButtonConfig): string | undefined { - if (view.customView === "previous") { - return "glyphicon glyphicon-backward"; - } else if (view.customView === "next") { - return "glyphicon glyphicon-forward"; - } - - return undefined; - } - - private getIconPosition(view: Container.ButtonConfig): "left" | "right" | undefined { - if (view.customView === "previous") { - return "left"; - } else if (view.customView === "next") { - return "right"; - } - - return undefined; - } -} diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Alert.spec.ts b/packages/customWidgets/calendar-custom-web/src/components/__tests__/Alert.spec.ts deleted file mode 100644 index 92f587a443..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Alert.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { shallow, ShallowWrapper } from "enzyme"; -import { createElement, ReactChild } from "react"; - -import { Alert, AlertProps } from "../Alert"; - -describe("Alert", () => { - const renderAlert = (props: AlertProps, message: ReactChild): ShallowWrapper => - shallow(createElement(Alert, props, message)); - const alertMessage = "This is an error"; - - it("renders structure correctly", () => { - const alert = renderAlert({}, alertMessage); - - expect(alert.getElement()).toEqual(createElement("div", { className: "alert alert-danger" }, alertMessage)); - }); - - it("renders no structure when the alert message is not specified", () => { - const alert = renderAlert({}, ""); - - expect(alert.getElement()).toEqual(null); - }); - - it("renders with the specified class", () => { - const alert = renderAlert({ className: "widget-calendar-alert" }, alertMessage); - - expect(alert.hasClass("widget-calendar-alert")).toBe(true); - }); - - it("with no bootstrap style specified renders with the class alert-danger", () => { - const alert = renderAlert({}, alertMessage); - - expect(alert.hasClass("alert-danger")).toBe(true); - }); - - it("renders with the matching class for the specified bootstrap style", () => { - const alert = renderAlert({ bootstrapStyle: "default" }, alertMessage); - - expect(alert.hasClass("alert-default")).toBe(true); - - alert.setProps({ bootstrapStyle: "primary" }); - expect(alert.hasClass("alert-primary")).toBe(true); - - alert.setProps({ bootstrapStyle: "info" }); - expect(alert.hasClass("alert-info")).toBe(true); - - alert.setProps({ bootstrapStyle: "success" }); - expect(alert.hasClass("alert-success")).toBe(true); - - alert.setProps({ bootstrapStyle: "warning" }); - expect(alert.hasClass("alert-warning")).toBe(true); - - alert.setProps({ bootstrapStyle: "danger" }); - expect(alert.hasClass("alert-danger")).toBe(true); - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Buttons.spec.ts b/packages/customWidgets/calendar-custom-web/src/components/__tests__/Buttons.spec.ts deleted file mode 100644 index 99e6d8ce55..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Buttons.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { shallow, ShallowWrapper } from "enzyme"; -import { createElement } from "react"; -import * as Button from "../Button"; - -describe("ToolbarButton", () => { - const renderToolbarButton = (props: Button.ButtonProps): ShallowWrapper => - shallow(createElement(Button.ToolbarButton, props)); - const buttonProps: Button.ButtonProps = { - renderMode: "button", - buttonStyle: "default", - iconPosition: "right", - active: false, - caption: "", - onClick: expect.any(Function) - }; - - it("renders a button when button is selected", () => { - const toolbarButton = renderToolbarButton(buttonProps); - - expect(toolbarButton).toMatchSnapshot(); - }); - - it("renders a link when link is selected", () => { - const toolbarButton = renderToolbarButton(buttonProps); - toolbarButton.setProps({ renderMode: "link" }); - - expect(toolbarButton).toMatchSnapshot(); - }); - - it("renders with a icon on the left if icon position === `right`", () => { - const toolbarButton = renderToolbarButton(buttonProps); - toolbarButton.setProps({ iconPosition: "right" }); - const icons = ""; - const iconPosition = "right"; - const content = ""; - const icon = Button.addIcon(icons, iconPosition, content); - - expect(icon).toEqual(""); - }); - - it("renders with a icon on the left if icon position === `left`", () => { - const toolbarButton = renderToolbarButton(buttonProps); - toolbarButton.setProps({ iconPosition: "left" }); - const icons = ""; - const iconPosition = "left"; - const content = ""; - const icon = Button.addIcon(icons, iconPosition, content); - - expect(icon).toEqual(""); - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Calendar.spec.ts b/packages/customWidgets/calendar-custom-web/src/components/__tests__/Calendar.spec.ts deleted file mode 100644 index 03e03eb619..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Calendar.spec.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { shallow, ShallowWrapper } from "enzyme"; -import { createElement } from "react"; - -import { CalendarProps, MyCalendar } from "../Calendar"; -import { SizeContainer, SizeProps } from "../SizeContainer"; - -interface Window { - mx: any; -} - -declare const window: Window; - -describe("Calendar", () => { - const renderCalendar = (props: CalendarProps): ShallowWrapper => - shallow(createElement(MyCalendar, props)); - const renderCalendarSizeComponent = (props: SizeProps): ShallowWrapper => - shallow(createElement(SizeContainer, props)); - const sizeProps: SizeProps = { - className: "widget-calendar", - widthUnit: "pixels", - width: 100, - heightUnit: "pixels", - height: 100 - }; - const calendarProps: CalendarProps = { - customViews: [], - defaultView: "month", - enableCreate: true, - events: [], - formats: {}, - height: 580, - heightUnit: "pixels", - messages: [], - editable: "default", - style: {}, - viewOption: "standard", - width: 100, - widthUnit: "percentage", - direction: "ltr" - }; - - beforeAll(() => { - (window as any).mx = { - session: { - sessionData: { - locale: { firstDayOfWeek: 1 } - } - }, - parser: { - formatValue: () => jest.fn() - } - }; - }); - - it("renders the structure correctly", () => { - const calendar = renderCalendarSizeComponent(sizeProps); - - expect(calendar).toMatchSnapshot(); - }); - - it("should render a structure correctly with pixels", () => { - const calendar = renderCalendarSizeComponent(sizeProps); - - expect(calendar).toMatchSnapshot(); - }); - - it("should render a structure correctly with percentage", () => { - const calendar = renderCalendarSizeComponent(sizeProps); - calendar.setProps({ - heightUnit: "percentageOfWidth", - widthUnit: "percentage" - }); - - expect(calendar).toMatchSnapshot(); - }); - - it("should render a structure correctly with percentage of parent", () => { - const calendar = renderCalendarSizeComponent(sizeProps); - calendar.setProps({ - heightUnit: "percentageOfParent", - widthUnit: "percentage" - }); - - expect(calendar).toMatchSnapshot(); - }); - - describe("event handler", () => { - it("#onSelectSlot() calls the parent onSelectSlot handler", () => { - calendarProps.onSelectSlotAction = jest.fn(); - const calendar = renderCalendar(calendarProps); - (calendar.instance() as any).onSelectSlot(); - - expect(calendarProps.onSelectSlotAction).toHaveBeenCalled(); - }); - - it("#onSelectEvent() calls the parent onSelectEvent handler", () => { - calendarProps.onSelectEventAction = jest.fn(); - const calendar = renderCalendar(calendarProps); - (calendar.instance() as any).onSelectEvent(); - - expect(calendarProps.onSelectEventAction).toHaveBeenCalled(); - }); - - it("#onEventDrop() calls the parent onEventDrop handler when the dates are different", () => { - const eventInfo = { - start: new Date(), - event: { - start: new Date(new Date().valueOf() + 1000 * 3600 * 24) - } - }; - calendarProps.onEventDropAction = jest.fn(); - const calendar = renderCalendar(calendarProps); - (calendar.instance() as any).onEventDrop(eventInfo); - - expect(calendarProps.onEventDropAction).toHaveBeenCalled(); - }); - - it("calls onEventDrop when moving the event within same day", () => { - const eventInfo = { - start: new Date(2021, 4, 27, 0, 0, 0), - event: { - start: new Date(2021, 4, 27, 18, 0, 0) - } - }; - calendarProps.onEventDropAction = jest.fn(); - const calendar = renderCalendar(calendarProps); - (calendar.instance() as any).onEventDrop(eventInfo); - - expect(calendarProps.onEventDropAction).toHaveBeenCalled(); - }); - - it("calls onEventResize when resizing the event within same day", () => { - const eventInfo = { - start: new Date(2021, 4, 27, 0, 0, 1), - end: new Date(2021, 4, 27, 12, 0, 0), - event: { - start: new Date(2021, 4, 27, 18, 0, 0), - end: new Date(2021, 4, 27, 23, 59, 59) - } - }; - calendarProps.onEventResizeAction = jest.fn(); - const calendar = renderCalendar(calendarProps); - (calendar.instance() as any).onEventResize(undefined, eventInfo); - - expect(calendarProps.onEventResizeAction).toHaveBeenCalled(); - }); - - // it("#onEventResize() calls the parent onEventResize handler when the start date, end date or both dates have changed", () => { - // const resizeType = "drop"; - // const startDate = new Date(); - // startDate.setDate(startDate.getDate() - 2); - // const initialEndDate = new Date(); - // initialEndDate.setDate(initialEndDate.getDate() - 1); - // const eventInfo = { - // start: startDate, - // end: new Date(), - // event: { - // start: startDate, - // end: initialEndDate - // } - // }; - // calendarProps.onEventResizeAction = jest.fn(); - // const calendar = renderCalendar(calendarProps); - // (calendar.instance() as any).onEventResize(resizeType, eventInfo); - // - // expect(calendarProps.onEventResizeAction).toHaveBeenCalled(); - // }); - }); - - afterAll(() => { - (window.mx as any) = undefined; - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/CalendarLoader.specs.ts b/packages/customWidgets/calendar-custom-web/src/components/__tests__/CalendarLoader.specs.ts deleted file mode 100644 index def9d6a0c9..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/CalendarLoader.specs.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { shallow } from "enzyme"; -import { createElement } from "react"; -import { CalendarLoader, generateDivs } from "../CalendarLoader"; - -describe("CalendarLoader", () => { - it("should render the structure correctly", () => { - const loading = shallow(createElement(CalendarLoader)); - - expect(loading.getElement()).toEqual( - createElement( - "div", - { className: "widget-calendar-loading-wrapper" }, - createElement("div", { className: "widget-calendar-loading-indicator" }, ...generateDivs(12)) - ) - ); - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Toobar.spec.ts b/packages/customWidgets/calendar-custom-web/src/components/__tests__/Toobar.spec.ts deleted file mode 100644 index 67bb69e83e..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/Toobar.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { shallow, ShallowWrapper } from "enzyme"; -import { createElement } from "react"; - -import CustomToolbar from "../Toolbar"; -import { CalendarProps } from "../Calendar"; - -describe("Toolbar", () => { - const renderToolbar = (props: CalendarProps): ShallowWrapper => - shallow(createElement(CustomToolbar as any, props)); - const toolbarProps: CalendarProps = { - customViews: [], - defaultView: "month", - enableCreate: true, - events: [], - formats: {}, - height: 580, - heightUnit: "pixels", - messages: [], - editable: "default", - style: {}, - viewOption: "standard", - width: 100, - widthUnit: "percentage", - direction: "ltr" - }; - - it("renders the standard toolbar structure correctly", () => { - const toolbar = renderToolbar(toolbarProps); - - expect(toolbar).toMatchSnapshot(); - }); -}); diff --git a/packages/customWidgets/calendar-custom-web/src/components/__tests__/__snapshots__/Buttons.spec.ts.snap b/packages/customWidgets/calendar-custom-web/src/components/__tests__/__snapshots__/Buttons.spec.ts.snap deleted file mode 100644 index 6c7383d02e..0000000000 --- a/packages/customWidgets/calendar-custom-web/src/components/__tests__/__snapshots__/Buttons.spec.ts.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ToolbarButton renders a button when button is selected 1`] = ` -