diff --git a/.gitignore b/.gitignore index a4be81395c..70104cb4d9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ mendixProject tests .turbo automation/run-e2e/ctrf/*.json +.cursor +.windsurf diff --git a/automation/utils/bin/rui-agent-rules.ts b/automation/utils/bin/rui-agent-rules.ts new file mode 100755 index 0000000000..db560e9f35 --- /dev/null +++ b/automation/utils/bin/rui-agent-rules.ts @@ -0,0 +1,50 @@ +#!/usr/bin/env ts-node-script + +import { mkdir, readdir, lstat, symlink, unlink } from "fs/promises"; +import path from "node:path"; + +async function ensureSymlink(targetRel: string, linkPath: string): Promise { + try { + const stat = await lstat(linkPath).catch(() => null); + if (stat) { + await unlink(linkPath); + } + await symlink(targetRel, linkPath); + } catch (err) { + console.error(`Failed to create symlink for ${linkPath}:`, err); + } +} + +async function main(): Promise { + const repoRoot = path.resolve(process.cwd(), "../.."); + const SRC_DIR = path.join(repoRoot, "docs", "requirements"); + const CURSOR_DIR = path.join(repoRoot, ".cursor", "rules"); + const WINDSURF_DIR = path.join(repoRoot, ".windsurf", "rules"); + + // Ensure target directories exist + await Promise.all([mkdir(CURSOR_DIR, { recursive: true }), mkdir(WINDSURF_DIR, { recursive: true })]); + + const files = (await readdir(SRC_DIR)).filter(f => f.endsWith(".md")); + + await Promise.all( + files.map(async file => { + const base = path.basename(file, ".md"); + const srcAbsolute = path.join(SRC_DIR, file); + + const cursorLink = path.join(CURSOR_DIR, `${base}.mdc`); + const windsurfLink = path.join(WINDSURF_DIR, `${base}.md`); + + const relFromCursor = path.relative(path.dirname(cursorLink), srcAbsolute); + const relFromWindsurf = path.relative(path.dirname(windsurfLink), srcAbsolute); + + await Promise.all([ensureSymlink(relFromCursor, cursorLink), ensureSymlink(relFromWindsurf, windsurfLink)]); + }) + ); + + console.log("Agent rules links updated."); +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/automation/utils/package.json b/automation/utils/package.json index 8453cbf3de..eba83a268e 100644 --- a/automation/utils/package.json +++ b/automation/utils/package.json @@ -5,6 +5,7 @@ "copyright": "© Mendix Technology BV 2025. All rights reserved.", "private": true, "bin": { + "rui-agent-rules": "bin/rui-agent-rules.ts", "rui-create-gh-release": "bin/rui-create-gh-release.ts", "rui-create-translation": "bin/rui-create-translation.ts", "rui-publish-marketplace": "bin/rui-publish-marketplace.ts", @@ -21,6 +22,7 @@ "tsconfig.json" ], "scripts": { + "agent-rules": "ts-node bin/rui-agent-rules.ts", "changelog": "ts-node bin/rui-changelog-helper.ts", "compile:parser:module": "peggy -o ./src/changelog-parser/parser/widget/widget.js ./src/changelog-parser/parser/widget/widget.pegjs", "compile:parser:widget": "peggy -o ./src/changelog-parser/parser/module/module.js ./src/changelog-parser/parser/module/module.pegjs", diff --git a/docs/requirements/app-flow.md b/docs/requirements/app-flow.md new file mode 100644 index 0000000000..5d5c7faf08 --- /dev/null +++ b/docs/requirements/app-flow.md @@ -0,0 +1,67 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Pluggable Widget Lifecycle & Application Flow + +Understanding how a pluggable widget moves from development to usage in Mendix Studio Pro is essential. This document breaks down the flow of creating, registering, configuring, building, and integrating a widget into Mendix Studio Pro. + +## 1. Scaffold / Creation of a New Widget + +Developers typically scaffold a new widget using the Mendix Pluggable Widget Generator. This generator creates: + +- A package structure (e.g., `packages/pluggableWidgets/my-widget-web/`). +- Initial files: a TypeScript/TSX file for the React component, a corresponding XML configuration file, a README, and build configuration files. + +Using the generator ensures correct conventions in folder layout, naming, and sample code. + +## 2. Widget Registration via XML + +Every widget has an XML file (e.g., `MyWidget.xml`) that: + +- Defines a unique widget ID and name (following the namespace pattern). +- Specifies metadata for categorization in Studio Pro. +- Defines properties (inputs, outputs, events) including types and defaults. +- Includes system properties (e.g., Visibility, Tab index). + +Studio Pro reads this XML to register the widget. Errors in the XML (such as duplicate IDs) prevent proper registration. + +## 3. Development: Implementing and Configuring the Widget + +After scaffolding and XML configuration: + +- **Coding:** Implement the widget's functionality in a `.tsx` file using React. The component receives props corresponding to the XML-defined properties. +- **Styling:** Use appropriate CSS classes (preferably Atlas UI classes) rather than inline styles. +- **Configuration:** Test the widget by adding it to a page in Studio Pro and verifying that properties appear and function as defined. + +Live reload is used during development to quickly reflect changes. + +## 4. Build and Bundle + +Using pnpm (or npm), developers: + +- Run `pnpm install` to install dependencies. +- Set the `MX_PROJECT_PATH` to point to a Mendix test project. +- You can ask the name of the project, and then set `MX_PROJECT_PATH` dynamically, for example: `export MX_PROJECT_PATH="$HOME/Mendix/${PROJECT_NAME}"`. This way, whether you run `pnpm start` or `pnpm build`, the output is deployed to the correct Studio Pro project and we can immediately see the latest changes. +- Run `pnpm start` to build the widget using Rollup (compiling TypeScript and SCSS). The output is placed in the Mendix project's widget folder. + +Rollup handles bundling into an optimized, single JavaScript file. + +## 5. Integration into Mendix Studio Pro + +Once built: + +- **During Development:** The widget appears in Studio Pro's toolbox after synchronization. Developers can drag it onto pages and configure its properties. +- **Packaging:** For distribution, a production build generates an MPK (a ZIP package) that can be imported into any Mendix project. +- **At Runtime:** The Mendix Client instantiates the widget, passes the configured properties (as EditableValue, DynamicValue, ActionValue, etc.), and the widget renders its UI. + +## 6. Summary of the Flow + +1. **Design/Develop:** Write widget code and define properties in XML. +2. **Register:** XML registration makes the widget available in Studio Pro. +3. **Configure in App:** Drag the widget onto a page and set its properties. +4. **Build:** Compile using pnpm/Rollup. +5. **Run/Integrate:** Mendix client loads the widget with runtime data. +6. **Iteration:** Repeat as needed with live reload and synchronization. diff --git a/docs/requirements/backend-structure.md b/docs/requirements/backend-structure.md new file mode 100644 index 0000000000..fdab08c60f --- /dev/null +++ b/docs/requirements/backend-structure.md @@ -0,0 +1,39 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Widget Data Flow & Backend Integration + +Although pluggable widgets are primarily client-side components, they operate within the Mendix ecosystem. This document explains how data flows between a widget and the Mendix runtime, and how events are handled. + +## Widget XML Configuration and Mendix Runtime + +- **Property Types and Mendix Data:** + - **attribute:** Provided as an EditableValue object. + - **textTemplate:** Passed as a DynamicValue. + - **objects/object:** Provided as a ListValue or ObjectValue. + - **Simple types:** Passed as plain JS values. + - **action:** Provided as an ActionValue with methods like `execute()`. +- **Data Context:** Widgets may require a context object if placed within a Data View. +- **Offline Capable:** XML can mark widgets as offline capable, meaning they are designed to work without a network connection. + +## Data Flow: Reading and Updating Data + +- **Initial Data Loading:** On page load, Mendix supplies data via props (e.g., EditableValue, DynamicValue). Widgets should render loading states if data is not yet available. +- **Two-Way Data Binding:** For interactive widgets, changes are pushed back using methods like `EditableValue.setValue()`. +- **Events and Actions:** User-triggered events call ActionValue's `execute()` method (after checking `canExecute`) to run Mendix microflows or nanoflows. + +## Mendix Client and Widget Lifecycle + +- **Instantiation:** Mendix creates the widget component on page load and passes the required props. +- **Re-rendering:** Changes in Mendix data trigger re-rendering via updated props. +- **Destruction:** Widgets unmount when removed; cleanup (e.g., event listeners) should occur during unmount. +- **Communication with the Server:** Widgets trigger server-side logic indirectly via microflows or nanoflows, using data source properties when needed. + +## Example: DataGrid2 Interaction + +- A DataGrid widget receives a ListValue for data. +- Sorting or row click events trigger ActionValues that may call microflows. +- Updates to the data source result in re-rendering of the widget. diff --git a/docs/requirements/frontend-guidelines.md b/docs/requirements/frontend-guidelines.md new file mode 100644 index 0000000000..d660dd58ab --- /dev/null +++ b/docs/requirements/frontend-guidelines.md @@ -0,0 +1,43 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Frontend Guidelines for Mendix Pluggable Widgets + +This guide provides best practices for front-end development in Mendix pluggable widgets, focusing on styling, component structure, naming, and Atlas design system usage. The goal is to ensure consistent, maintainable widget development. + +## CSS and SCSS Styling Guidelines + +- **Use SCSS for Styles:** Write all widget styles in SCSS files to leverage variables, mixins, and integration with the overall theme. +- **No Inline Styles for Static Design:** Avoid using inline styles. Instead, assign CSS classes defined in SCSS or use Atlas classes. +- **Leverage Atlas UI Classes:** Utilize predefined Atlas classes (e.g., `btn`, `badge`) to ensure a consistent look. +- **Scoped vs Global Styles:** Prefix custom classes with the widget name (e.g., `.widget-combobox`) to avoid conflicts. +- **Responsive Design:** Use relative units and media queries to ensure the widget adapts gracefully to different screen sizes. +- **Avoid Deep Nesting:** Write clear, maintainable CSS without over-nesting or using `!important` unless absolutely necessary. +- **Design Properties and Conditional Classes:** Implement design properties via toggling classes based on user selections in Studio Pro. + +## Naming Conventions (Files, Classes, and Components) + +- **Component and File Names:** Use PascalCase for React component files (e.g., `ProgressBar.tsx`). +- **Widget Folder Naming:** Use lowercase names with hyphens ending with "web" (e.g., `badge-button-web`). +- **XML Keys and Attribute Names:** Use lowerCamelCase for XML property keys. +- **CSS Class Naming:** Follow a BEM-like convention for custom classes to maintain structure and clarity. + +## Component Best Practices + +- **Mendix Data API Usage:** Use Mendix API objects (EditableValue, ActionValue, etc.) correctly, checking conditions such as `canExecute` before calling actions. +- **State Management:** Use React state for UI-specific state and rely on Mendix props for persistent data. There are usages of Context and State management tools(mobx) +- **Performance Considerations:** Optimize renders, avoid heavy computations, and consider memoization. +- **Clean Up:** Ensure any event listeners or timers are cleaned up appropriately. +- **No Direct DOM Manipulation:** Use React's state and props to drive UI changes rather than direct DOM queries. +- **Accessibility:** Use semantic HTML, proper ARIA attributes, and ensure keyboard navigation is supported. + +## Using Atlas UI and Theming + +- **Consistent Look and Feel:** Ensure widgets integrate with Atlas UI by using default Atlas classes for common elements. +- **Custom Themes Support:** Build widgets so that they naturally adopt custom Atlas themes without hard-coded values. +- **Layout and Sizing:** Use flexible layouts (e.g., percentage widths, flexbox) that adapt to container sizes. +- **No Overriding Atlas Core Classes:** Do not override core Atlas classes; wrap widget elements if custom styling is needed. +- **Example – Consistent Button:** Use `` instead of custom-styled divs. diff --git a/docs/requirements/implementation-plan.md b/docs/requirements/implementation-plan.md new file mode 100644 index 0000000000..03c00c6ade --- /dev/null +++ b/docs/requirements/implementation-plan.md @@ -0,0 +1,170 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Implementation Plan for a New Pluggable Widget + +This document outlines a step-by-step plan to design, build, test, and integrate a new pluggable widget in Mendix. + +## 1. Planning and Requirements + +- **Define the Widget's Purpose:** Clearly state what the widget does, its name (e.g., "ProgressCircle"), its category, target data, and required properties (e.g., value, maximum, showLabel, onClick). +- **Check Existing Patterns:** Review similar widgets for best practices and to avoid duplicating functionality. + +## 2. Environment Setup + +- **Prerequisites:** Install Node.js (using the version specified in the repository), Mendix Studio Pro. +- **Folder Structure:** Create a new package under `packages/pluggableWidgets/` in the monorepo or use a standalone directory. + +4. Define Widget Properties in XML + Edit the generated XML file (e.g., ProgressCircle.xml) to define properties and property groups. + +Ensure property keys match the TypeScript props. + +Do not change the widget's unique ID unless necessary. + +5. Implement the React Component + Modify the generated .tsx file to match the XML-defined properties. + +Use Mendix API types (e.g., EditableValue, DynamicValue, ActionValue) correctly. + +Implement basic rendering and add error/loading states. + +Import SCSS for styling and use Atlas UI classes. + +6. Build and Run in Studio Pro + Set the MX_PROJECT_PATH environment variable to your test project's directory, you can ask what the project name running in Studio Pro is so that we can se the MX_PROJECT_PATH. The path is: /Users/rahman.unver/Mendix/ProjectName, this path is always same for the macOS version of Studio Pro. For Windows version, our path is /Volumes/[C] Windows11/Users/Rahman.Unver/Documents/ProjectName. example setting: + Windows: + +- export MX_PROJECT_PATH=/Volumes/[C] Windows11/Users/Rahman.Unver/Documents/DocumentViewerWidget +- export MX_PROJECT_PATH=/Users/rahman.unver/Mendix/RichTextTest + +Run pnpm start (or npm start) to build and watch for changes. + +In Studio Pro, synchronize the app directory to load the widget. + +Place the widget on a test page and configure properties. + +7. Iterative Development + Develop and test iteratively. + +Use browser developer tools for debugging. + +Adjust XML and TS code as needed when adding new properties or handling edge cases. + +8. Testing and Validation + Write unit tests for critical logic using Jest, React Testing Library mainly. + +Perform UI/functional testing within a Mendix project. + +Test responsiveness, performance, and edge cases. + +9. Documentation and Metadata + Update the widget's README with usage instructions and limitations. + +Ensure XML descriptions and property captions are clear. + +Optionally, add an icon for the widget. + +10. Packaging and Sharing + Run npm run build to produce an MPK file. + +Test the MPK in a fresh Mendix project. + +Update version numbers and changelogs before distribution. + +Common Gotchas: + +Ensure XML and TypeScript props match exactly. + +Install all third-party dependencies. + +Maintain case sensitivity in IDs and keys. + +Clean up event listeners to avoid memory leaks. + +Ensure compatibility with the target Mendix version. + +### Github PR Template + + + + + + +### Pull request type + + + + + + + + + + + + + + + +--- + + + +### Description + + + + + + +Keep this template in mind if I ever ask you to open a PR through command console, Github CLI or similar. diff --git a/docs/requirements/project-requirements-document.md b/docs/requirements/project-requirements-document.md new file mode 100644 index 0000000000..5879777df4 --- /dev/null +++ b/docs/requirements/project-requirements-document.md @@ -0,0 +1,43 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Web Widgets Repository – Product Requirements + +## Purpose and Background + +The Mendix Web Widgets repository is the home of all Mendix platform-supported pluggable web widgets and related modules. Its primary purpose is to provide a unified collection of reusable UI components that Mendix app developers can drop into their apps, ensuring consistency and high quality across projects. These widgets are built with Mendix's Pluggable Widgets API (introduced in Mendix 8 and enhanced in Mendix 9) and use modern web technologies (React, TypeScript, SASS) under the hood. Mendix pluggable widgets are essentially custom React components that integrate seamlessly into Mendix Studio Pro as if they were native widgets. By open-sourcing this repository, Mendix enables developers to learn from real examples and even contribute enhancements. + +## Goals and Objectives + +- **Comprehensive Widget Library:** Offer a broad range of common UI elements (grids, inputs, charts, etc.) as pluggable widgets so developers rarely need to build widgets from scratch. Each widget addresses a specific need (e.g., data grid for tabular data, color picker for color selection) with Mendix best practices in mind. +- **Consistency and Quality:** Ensure all widgets follow a consistent design language (Atlas UI design system) and coding standards. This makes the AI assistant's suggestions consistent with how a Mendix team member would implement features. Widgets adhere to Mendix's style and UX conventions, leading to a uniform experience across apps. +- **Ease of Use:** Simplify the usage of custom widgets in Mendix Studio Pro. Widgets appear in Studio Pro's toolbox with proper categorization (e.g., "Buttons", "Containers") and have intuitive properties editors defined via XML. Mendix developers can drag & drop these widgets and configure properties without writing code. +- **Reusability and Extensibility:** Provide widgets that are generic yet flexible. Many widgets offer customization via properties or design "appearance" options (often powered by Atlas classes or helper classes). For example, the Badge Button widget can be styled via preset classes (primary, info, warning, etc.) rather than creating new widgets for each style. +- **Maintainability:** As part of the platform, these widgets are maintained alongside Mendix updates. The repository is structured to facilitate testing (unit tests, E2E tests) and continuous integration. This ensures widgets remain compatible with new Mendix versions and quality regressions are caught early. + +## Target Users + +- **Primary:** Mendix application developers (both citizen and professional developers) using Mendix Studio Pro. They benefit from a rich set of ready-made widgets that can be configured visually. +- **Secondary:** Mendix R&D and community contributors. Mendix's engineering team maintains official widgets, and community developers can reference the code to learn conventions or contribute improvements. In this context, the AI assistant "learns" from these docs to help developers. + +## Scope and Widget Coverage + +This repository covers pluggable web widgets for Mendix (not native mobile widgets). The scope includes: + +- **Form and Input Widgets:** E.g., Combo Box, Checkbox Set Selector, Date Picker – enhancing Mendix's default input components. +- **Display and Formatting Widgets:** E.g., Badge/Badge Button, Format String, Image Viewer – presenting data in formatted ways. +- **Containers and Layout Widgets:** E.g., Fieldset, Accordion, Tab widgets – for grouping and layout. +- **Data Display Widgets:** Most notably, Data Grid 2 for displaying records in a table with features like sorting and filtering. +- **Navigation/Actions Widgets:** E.g., Action Button and Events widget – connecting UI interactions to Mendix logic. +- **Integration & Utility Widgets:** E.g., HTML/JavaScript Snippet, Google Maps, Charts – extending Mendix with external integrations. + +## Design System Alignment + +All widgets align with Atlas UI, Mendix's design system. They use Atlas styling conventions (spacing, colors, fonts) and support design properties for easy styling changes. Widgets automatically adopt custom Atlas-based themes through standard class names and variables. + +## Conclusion + +The Web Widgets repository is critical to the Mendix ecosystem—bridging low-code ease with pro-code flexibility. It empowers developers with ready components while ensuring consistency and quality. For Cursor's AI assistant, these guidelines and conventions provide the necessary context to generate answers and code that align with Mendix widget development. diff --git a/docs/requirements/tech-stack.md b/docs/requirements/tech-stack.md new file mode 100644 index 0000000000..dcebc786c1 --- /dev/null +++ b/docs/requirements/tech-stack.md @@ -0,0 +1,40 @@ +--- +description: +globs: +alwaysApply: true +--- + +# Technology Stack and Project Structure + +The Mendix pluggable widgets ecosystem leverages a modern web development tech stack combined with Mendix-specific tools and configurations. This document outlines the key technologies and the project structure. + +## Core Technologies Used + +- **TypeScript:** All widgets are written in TypeScript (.tsx files) to enforce type safety and improve maintainability. +- **React:** Widgets are implemented as React components, enabling a declarative UI model and rich state management. +- **SASS/SCSS:** Styling is done with SCSS, allowing use of variables, nesting, and integration with Atlas UI for theming. +- **Rollup:** The bundler used to compile widget code into a single optimized file. Rollup handles TypeScript, JSX, and SCSS while performing tree-shaking. +- **NPM (pnpm):** pnpm is used for package management, ensuring efficient dependency handling and consistent build environments. +- **Jest:** Used for unit testing widget logic and components. +- **RTL(react-testing-library):** Used for unit testing widget logic and components. +- **Linting/Formatting:** ESLint and Prettier enforce code style consistency. + +## Monorepo Structure and Packaging + +- **Packages Folder:** All widget code resides under `packages/`, typically in `packages/pluggableWidgets/` with each widget in its own folder (e.g., `badge-button-web`, `datagrid-web`). +- **Shared Modules:** Common code and assets are stored in `packages/shared/`. +- **Modules and Actions:** Additional Mendix modules and JavaScript actions are organized in separate folders. +- **Atlas Integration:** Widgets reference Atlas UI classes for a consistent design without duplicating styles. +- **Configuration Files:** Root-level configuration files (e.g., lerna.json, package.json, .nvmrc) ensure consistent tooling. +- **Build Scripts:** Each widget package includes scripts for building, starting, and testing, using @mendix/pluggable-widgets-tools. +- **Testing Setup:** Unit tests reside in widget folders (e.g., `src/__tests__/`) and can be run collectively via pnpm test. + +## Configuration and Code Standards + +- **ESLint and Prettier:** Enforce code quality and style consistency. +- **Naming Conventions:** + - React component files use PascalCase. + - Widget folders use lowercase with hyphens ending with “-web”. + - XML property keys use lowerCamelCase. +- **Atlas Styling Conventions:** Prefer Atlas UI classes over custom inline styles. +- **Versioning and Backward Compatibility:** Widgets follow semantic versioning and maintain compatibility with Mendix platform changes. diff --git a/package.json b/package.json index 2e5e3f5a5c..27b696e52a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "create-translation": "turbo run create-translation", "publish-marketplace": "turbo run publish-marketplace", "version": "pnpm --filter @mendix/automation-utils run version", - "changelog": "pnpm --filter @mendix/automation-utils run changelog" + "changelog": "pnpm --filter @mendix/automation-utils run changelog", + "postinstall": "turbo run agent-rules" }, "devDependencies": { "husky": "^8.0.3", diff --git a/turbo.json b/turbo.json index 603ed293e2..9cb746b9ff 100644 --- a/turbo.json +++ b/turbo.json @@ -107,6 +107,13 @@ "!*/**/__tests__/**" ], "outputs": [] + }, + "agent-rules": { + "cache": false, + "inputs": [ + "docs/requirements/**" + ], + "outputs": [] } } -} +} \ No newline at end of file