From f5c5e7c42dd47c403a6327f68cbc0dd309dfcb79 Mon Sep 17 00:00:00 2001 From: gnbm Date: Tue, 3 Mar 2026 21:44:02 +0000 Subject: [PATCH 1/5] Add comprehensive project documentation --- .claude/settings.local.json | 12 +++ .github/CONTRIBUTING.md | 180 ++++++++++++++++++++++++++------ ARCHITECTURE.md | 97 +++++++++++++++++ CLAUDE.md | 203 ++++++++++++++++++++++++++++++++++++ 4 files changed, 463 insertions(+), 29 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 ARCHITECTURE.md create mode 100644 CLAUDE.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..8d9d9505 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,12 @@ +{ + "permissions": { + "allow": [ + "Bash(echo MISSING: $path:*)", + "WebFetch(domain:success.outsystems.com)", + "Bash(echo MISSING: $file:*)", + "WebFetch(domain:outsystemsui-qa.outsystemsenterprise.com)", + "WebFetch(domain:developers.google.com)", + "WebFetch(domain:leafletjs.com)" + ] + } +} diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 036ce7c7..44f549f7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,47 +1,169 @@ -# Contributing to OUTSYSTEMS-MAPS +# Contributing to OutSystems Maps -Thank you for considering contributing to our project! 🚀 +Thank you for contributing to OutSystems Maps. This guide covers the development workflow and standards for this TypeScript-based mapping component library. -We hope that the contribution of this repo is made in a way that meets the OutSystems guidelines. +## Development Setup -## Code of Conduct +**Prerequisites:** +- Node.js >= 12 +- npm +- [Visual Studio Code](https://code.visualstudio.com/) (recommended) -We must follow the code of conduct of OutSystems. +**Recommended VS Code Extensions:** +- Document This +- ESLint +- Prettier - Code formatter -## Our Development Process +**Setup:** +```bash +npm install +npm run dev # Starts development server at http://localhost:3000 +``` -We use GitHub to sync code to and from our internal repository. -We'll use JIRA to track issues and feature requests, and GitHub as well to accept pull requests. +The development server watches for TypeScript changes and recompiles automatically. -## Pull Requests +## Development Workflow -We actively welcome your pull requests. +### Branch Naming -1. Create your branch from `dev`. -1. If you've added code that should have tests and be tested. -1. Ensure the test suite passes. -1. Make sure your code lints. -1. The PR is compliant with all PR Checks. -1. Ensure the PR has the correct label on title, as below: +Create branches from `dev` following the pattern `` or `-description`: -| Labels | Change | SemVer | -| --------------------------------------------------------------------- | :----: | ------- | -| breaking
major | Major | X+1.0.0 | -| feat
feature
minor | Minor | 0.X+1.0 | -| revert
perf
test
refactor
fix
bugfix
patch
chore | Patch | 0.0.X+1 | -| ci
none
docs
style
skip | None | 0.0.0 | +```bash +git checkout dev +git pull origin dev +git checkout -b ROU-1234 +``` -## Trusted Committers +Examples: `ROU-12619`, `ROU-12504-fix-marker-clustering` -Our Trusted Committers are here to assist you with your contributions. -Feel free to reach out to them for guidance, reviews, and support. +### Commit Messages -Our Trusted Committer will always be the [UI Components team member on support rotation](mailto:rd.uicomponents.team@outsystems.com). +No strict commit format enforced. Use clear, descriptive messages that explain the change. -## Trusted Committer Availability Schedule +### Pull Request Requirements -Our Trusted Committees are available internally on Slack channel _#rd-uicomponents-contributors_ on business days from 2PM-3PM (PT time). +**PR Title Format:** +``` + +``` + +Examples: +- `ROU-12619 Fix marker clustering performance` +- `ROU-12558 Mark release as latest` + +The title must match the regex: `^([A-Z][A-Z0-9]*-\d+(:)?\s\w)` (enforced by CI). + +**Required Labels:** + +PRs must have at least one of these labels: +- `feature` +- `bug` / `bugfix` +- `dependencies` / `dependency` +- `chore` + +PRs with `do not merge` label will be blocked. + +**Before Submitting:** +1. Test locally using the dev server +2. Run `npm run build` to ensure the build succeeds +3. Fix all ESLint errors and warnings +4. Document your code using JSDoc comments (type `/**` above functions) +5. Fill out the PR template completely + +**PR Template Requirements:** +- Link to sample page demonstrating the change +- What was happening (the problem) +- What was done (the solution) +- Test steps to verify the fix +- Screenshots or animated GIFs +- Checklist confirmation + +PRs require approval from 2 team members before merge. + +## Building and Testing + +| Command | Description | +|---------|-------------| +| `npm run setup` | Install dependencies and start dev server | +| `npm run dev` | Start development server with hot reload | +| `npm run build` | Build production bundle with linting | +| `npm run lint` | Check code style (ESLint) | +| `npm run lintfix` | Auto-fix ESLint issues | +| `npm run prettier` | Format all JS/TS/CSS files | +| `npm run docs` | Generate TypeDoc documentation | + +**Note:** `npm test` is not configured. Manual testing via the dev server and sample pages is required. + +## Testing + +Automated tests are maintained in a separate repository: [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) + +The test suite uses Gherkin/BDD framework with WebDriver.io and supports: +- Multiple browsers (Chrome, Firefox, Edge, Safari) +- Multiple environments (dev, qa) +- Local and SauceLabs execution + +To run tests locally (from the tests repository): +```bash +npm run local -- --browsers=chrome --environment=dev --map=web +``` + +## Code Standards + +### TypeScript + +- **Target:** ES2017, compiled to AMD module +- **Output:** Single file at `dist/OutSystemsMaps.js` +- **Style:** Strict ESLint rules enforced (see `.eslintrc.json`) + +### Naming Conventions + +Enforced by ESLint: +- **Exported functions:** `StrictPascalCase` +- **Classes:** `StrictPascalCase` +- **Interfaces:** `IPascalCase` (must start with `I`) +- **Public/protected properties:** `strictCamelCase` (no leading underscore) +- **Private properties:** `_strictCamelCase` (leading underscore required) +- **Public/protected methods:** `strictCamelCase` (no leading underscore) +- **Private methods:** `_strictCamelCase` (leading underscore required) + +### Member Ordering + +Class members alphabetically ordered within groups: +1. Private fields +2. Protected fields +3. Public fields +4. Constructor +5. Private methods +6. Protected methods +7. Public methods + +### Formatting + +Enforced by Prettier (`.prettierrc.json`): +- Single quotes +- Semicolons required +- 120 character line width +- Tabs for indentation (width: 4) +- ES5 trailing commas + +Run `npm run prettier` to format all files. + +## Documentation + +Document all public APIs using JSDoc comments. VS Code's "Document This" extension provides templates when you type `/**`. + +Architectural decisions are documented in `docs/adr/`. Follow the template in `docs/adr/ADR-0000-Title-of-ADR.md`. + +## Support and Communication + +**External Contributors:** +Contact the UI Components team via [component support page](https://www.outsystems.com/forge/component-discussions/9909/OutSystems+Maps) + +**Internal Contributors:** +Slack channel `#rd-uicomponents-contributors` (business days, 2-3 PM PT) +Trusted Committer: [UI Components team on support rotation](mailto:rd.uicomponents.team@outsystems.com) ## License -This repos belongs to OutSystems and rights are reserved. +This repository is proprietary to OutSystems. All rights reserved. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..9a257d6e --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,97 @@ +# OutSystems Maps Architecture + +> **Repository:** outsystems-maps +> **Runtime Environment:** User Browser (JavaScript Library) +> **Last Updated:** 2026-03-03 + +## Overview + +OutSystems Maps is a TypeScript library that provides a unified API for integrating interactive maps into OutSystems Reactive Web applications. It abstracts multiple map providers (Google Maps and Leaflet/OpenStreetMap) behind a common interface, allowing developers to build map-based features without JavaScript knowledge. + +## Architecture Diagram + +```mermaid +graph TB + %% This repository + OSMaps["OutSystems Maps Library
Runs on: User Browser"] + + %% External services + GoogleMapsAPI[Google Maps JavaScript API
EXTERNAL] + GoogleRoutesAPI[Google Routes API
EXTERNAL] + OpenStreetMap[OpenStreetMap Tiles
EXTERNAL] + OSPlatform[OutSystems Platform
EXTERNAL] + + %% Communication flows + OSPlatform -->|JavaScript API calls
Synchronous| OSMaps + OSMaps -->|Load maps SDK, geocoding, places search
Synchronous| GoogleMapsAPI + OSMaps -->|Compute routes
Synchronous| GoogleRoutesAPI + OSMaps -->|Load map tiles
Synchronous| OpenStreetMap + + %% Styling + classDef thisRepo fill:#e0f2f1,stroke:#00796b,stroke-width:3px + classDef external fill:#ffe1e1,stroke:#d32f2f,stroke-width:2px,stroke-dasharray: 5 5 + + class OSMaps thisRepo + class GoogleMapsAPI,GoogleRoutesAPI,OpenStreetMap,OSPlatform external +``` + +## External Integrations + +| External Service | Communication Type | Purpose | +|------------------|-------------------|---------| +| Google Maps JavaScript API | Sync (HTTPS/JavaScript) | Render Google Maps, geocoding, places search, marker clustering, drawing tools | +| Google Routes API | Sync (HTTPS) | Calculate directions and route polylines via `routes.googleapis.com/directions/v2:computeRoutes` | +| OpenStreetMap Tiles | Sync (HTTPS) | Render Leaflet-based maps with OSM tile layers from `tile.openstreetmap.org` | +| OutSystems Platform | Sync (JavaScript API) | Host application that consumes this library via block parameters and events | + +## Architectural Tenets + +### T1. Provider Abstraction Must Isolate External Dependencies + +The library maintains strict separation between provider-agnostic framework code and provider-specific implementations. All map provider logic (Google Maps, Leaflet) is contained within the `Provider.Maps` namespace, while the `OSFramework.Maps` namespace defines interfaces and abstract classes that do not reference concrete provider types. This allows adding new map providers without modifying core framework code. + +**Evidence:** +- `src/OSFramework/Maps/OSMap/AbstractMap.ts` (in `AbstractMap` class) - defines common map behavior independent of provider using generic type parameter for provider object +- `src/Providers/Maps/Google/OSMap/OSMap.ts` (in `Map` class) - extends `AbstractMap` with Google-specific implementation for `google.maps.Map` +- `src/Providers/Maps/Leaflet/OSMap/OSMap.ts` (in `Map` class) - extends `AbstractMap` with Leaflet-specific implementation for `L.Map` +- `src/OSFramework/Maps/OSMap/Factory.ts` (in `MapFactory.MakeMap`) - routes provider selection to appropriate factory, the only place in framework layer that references provider namespaces + +### T2. Public API Must Return Framework Interfaces, Not Provider Types + +The OutSystems-facing API in `OutSystems.Maps.MapAPI` operates exclusively on framework interfaces from the `OSFramework.Maps` namespace. Public methods return interfaces like `IMap` and `IMarker`, never concrete provider classes. This ensures the external API remains stable regardless of which provider is selected at runtime or how provider implementations evolve. + +**Evidence:** +- `src/OutSystems/Maps/MapAPI/MapManager.ts` (in `CreateMap`) - returns `OSFramework.Maps.OSMap.IMap` interface, not provider-specific class +- `src/OutSystems/Maps/MapAPI/MapManager.ts` (in `GetMapById`) - all lookup methods return framework interfaces +- `src/OutSystems/Maps/MapAPI/MarkerManager.ts` - marker operations work with framework marker interfaces +- `src/OSFramework/Maps/OSMap/IMap.ts` - interface exposes provider as generic `any` type, not concrete provider class + +### T3. Framework Layer Owns Lifecycle and State Management + +The `OSFramework` layer controls all component lifecycle (creation, initialization, disposal) and maintains parent-child relationships (maps contain markers, shapes, file layers). Provider implementations are passive adapters that respond to framework commands via the `build()` and `dispose()` methods defined by shared interfaces, but do not independently manage their lifecycle or relationships. + +**Evidence:** +- `src/OSFramework/Maps/OSMap/AbstractMap.ts` (in `build`, `finishBuild`) - framework controls initialization sequence and triggers events +- `src/OSFramework/Maps/OSMap/AbstractMap.ts` (private fields `_markers`, `_shapes`, `_fileLayers`) - framework maintains collections of child components +- `src/OSFramework/Maps/Interfaces/IBuilder.ts` and `IDisposable.ts` - shared interfaces that enforce lifecycle contract +- `src/OSFramework/Maps/Marker/AbstractMarker.ts` (in `finishBuild`) - framework triggers initialization event and adds marker to clusterer after provider completes setup + +### T4. Configuration Transformation Occurs at Provider Boundaries + +User-facing configuration uses OutSystems-friendly structures (JSON strings, integer enums, string coordinates), while provider-specific configuration matches native API requirements (typed objects, native enums, coordinate objects). The `Configuration` namespace implements `getProviderConfig()` to transform between representations without exposing provider details to the framework layer. + +**Evidence:** +- `src/OSFramework/Maps/Configuration/AbstractConfiguration.ts` (in `getProviderConfig`) - defines contract for transforming framework config to provider config +- `src/Providers/Maps/Google/Configuration/OSMap/GoogleMapConfig.ts` (in `getProviderConfig`) - transforms framework config to Google Maps API options, including mapId handling for advanced markers +- `src/Providers/Maps/Leaflet/Configuration/OSMap/LeafletMapConfiguration.ts` (in `getProviderConfig`) - transforms framework config to Leaflet API options +- `src/OutSystems/Maps/MapAPI/MapManager.ts` (in `CreateMap`) - accepts JSON config string from OutSystems, parses and passes to factory + +### T5. Events Flow Through Framework Event Managers + +All events (map clicks, marker interactions, provider-specific events) are normalized and dispatched through framework event managers that inherit from `AbstractEventsManager`. Provider implementations register native provider events but trigger framework events, which handle subscription management and callback execution consistently across providers. User callbacks never receive provider-specific event objects. + +**Evidence:** +- `src/OSFramework/Maps/Event/AbstractEventsManager.ts` - provides centralized event subscription and dispatch mechanism used by all component types +- `src/OSFramework/Maps/Event/OSMap/MapEventsManager.ts` - manages all map-level events independent of provider, validates provider event types +- `src/Providers/Maps/Google/OSMap/OSMap.ts` (uses `google.maps.event.addListener`) - Google provider adds listeners via native API but triggers framework events +- `src/Providers/Maps/Leaflet/OSMap/OSMap.ts` (in `_setMapEvents`) - Leaflet provider converts native events to framework event format before triggering diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..37610d5d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,203 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +OutSystems Maps is a TypeScript library providing a unified API for Google Maps and Leaflet/OpenStreetMap integration in OutSystems Reactive Web applications. The library compiles to a single AMD module (`dist/OutSystemsMaps.js`) that abstracts provider differences behind framework interfaces. + +**Foundation Documents:** +- See [ARCHITECTURE.md](./ARCHITECTURE.md) for the provider abstraction pattern, architectural tenets (T1-T5), and external integrations table +- See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for development workflow, PR requirements, and code standards + +## Build and Development Commands + +**Setup and Development:** +```bash +npm install # Install dependencies +npm run dev # Start dev server at http://localhost:3000 with hot reload +``` + +**Build and Quality:** +```bash +npm run build # Production build: clean + transpile + lintfix + lint +npm run lint # Check ESLint errors/warnings +npm run lintfix # Auto-fix ESLint issues +npm run prettier # Format all JS/TS/CSS files +npm run docs # Generate TypeDoc documentation +``` + +**Note:** No automated tests exist in this repository (`npm test` exits with error). Automated tests are maintained in the separate [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) repository. + +**Build System:** Gulp-based. Check `gulpfile.js` and `gulp/Tasks/` for task definitions. TypeScript compiles to single file via tsconfig `outFile: "./dist/OutSystemsMaps.js"`. + +## Repository Structure + +``` +src/ +├── OSFramework/Maps/ # Framework layer (provider-agnostic) +│ ├── Configuration/ # Config transformation interfaces +│ ├── Event/ # Event management (MapEventsManager, MarkerEventsManager, etc.) +│ ├── Marker/ # Marker abstractions +│ ├── Shape/ # Shape abstractions (Polygon, Polyline, Circle) +│ ├── OSMap/ # Map abstractions +│ ├── DrawingTools/ # Drawing tools abstractions +│ ├── FileLayer/ # File layer abstractions (KML, GeoJSON) +│ ├── HeatmapLayer/ # Heatmap abstractions +│ └── SearchPlaces/ # Places search abstractions +├── Providers/Maps/ # Provider implementations +│ ├── Google/ # Google Maps adapter +│ └── Leaflet/ # Leaflet/OSM adapter +├── OutSystems/Maps/ # Public API +│ ├── MapAPI/ # Map management (MapManager, MarkerManager, ShapeManager, etc.) +│ └── PlacesAPI/ # Places search +└── Files/ # Static assets + ├── Google/ # Google Maps scripts + └── Leaflet/ # Leaflet scripts/styles +``` + +**Key Separation:** `OSFramework/` defines interfaces and abstractions. `Providers/` contains Google Maps and Leaflet implementations. `OutSystems/` exposes the public API. See [ARCHITECTURE.md T1](./ARCHITECTURE.md#t1-provider-abstraction-must-isolate-external-dependencies) for provider isolation details. + +## Testing and Verification + +Automated tests are maintained in a separate private repository: [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) + +**To run tests locally (requires gh CLI):** +```bash +# Clone the tests repository +gh repo clone OutSystems/outsystems-maps-tests ../outsystems-maps-tests + +# Run tests +cd ../outsystems-maps-tests +npm run local -- --browsers=chrome --environment=dev --map=web +``` + +**Manual testing via dev server:** +1. Start dev server: `npm run dev` +2. Test changes at `http://localhost:3000` +3. Reference sample app: https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample +4. Check component living docs: https://outsystemsui.outsystems.com/OutSystemsMapsSample/ + +## Important Context + +### Map Provider Architecture + +The library supports two map providers selected at runtime: +- **Google Maps:** Requires API key, provides full Google Maps JavaScript API capabilities (geocoding, places search, marker clustering, advanced markers) +- **Leaflet:** Open-source library for mobile-friendly interactive maps (~42 KB, no dependencies), uses OpenStreetMap tiles (no API key required) + +Provider selection happens in `OSFramework/Maps/OSMap/Factory.ts` via `MapFactory.MakeMap()`. All provider-specific code is isolated in `Providers/` directories. + +**Leaflet Characteristics:** +- Design philosophy: simplicity, performance, usability +- Supports tile layers, markers with popups, vector geometries, image overlays, GeoJSON +- Hardware acceleration on mobile, CSS-driven smooth panning/zooming +- Custom map projections (EPSG:3857/4326/3395) + +### Configuration Pattern + +User configuration flows: JSON string → framework config object → provider-specific options. + +Example flow: +1. `OutSystems.Maps.MapAPI.MapManager.CreateMap()` accepts JSON config string +2. Parsed into `OSFramework.Maps.Configuration.*` objects +3. `getProviderConfig()` transforms to `google.maps.MapOptions` or `L.MapOptions` + +See [ARCHITECTURE.md T4](./ARCHITECTURE.md#t4-configuration-transformation-occurs-at-provider-boundaries) for configuration transformation contract. + +### Event System + +All events flow through framework event managers (`OSFramework/Maps/Event/`): +- Provider implementations trigger framework events, not direct callbacks +- `AbstractEventsManager` handles subscription/dispatch consistently +- User callbacks never receive provider-specific event objects + +See [ARCHITECTURE.md T5](./ARCHITECTURE.md#t5-events-flow-through-framework-event-managers) for event flow details. + +### Component Lifecycle + +Framework layer controls all lifecycle via abstract classes: +- `build()` → initialize provider component +- `finishBuild()` → trigger event cascade +- `dispose()` → cleanup + +Provider implementations respond to framework commands but do not manage their own lifecycle. Framework maintains parent-child relationships (maps contain markers, shapes, file layers). + +See [ARCHITECTURE.md T3](./ARCHITECTURE.md#t3-framework-layer-owns-lifecycle-and-state-management) for lifecycle ownership details. + +## Code Standards + +**Member Ordering (enforced by ESLint):** +1. Private fields (`_name`) +2. Protected fields +3. Public fields +4. Constructor +5. Private methods +6. Protected methods +7. Public methods + +Within each group: alphabetical order. + +**Naming:** +- Exported functions: `StrictPascalCase` +- Interfaces: `IPascalCase` (must start with `I`) +- Private properties/methods: `_strictCamelCase` (leading underscore required) +- Public/protected: `strictCamelCase` (no underscore) + +**Formatting:** Single quotes, semicolons required, 120 char width, tabs (width 4). Prettier config in `.prettierrc.json`. + +See [CONTRIBUTING.md](./.github/CONTRIBUTING.md#code-standards) for complete standards. + +## Documentation + +Document public APIs with JSDoc comments. Type `/**` above functions for templates (VS Code "Document This" extension). + +Architectural decisions documented in `docs/adr/`. Use `docs/adr/ADR-0000-Title-of-ADR.md` as template. Existing ADRs: +- `ADR-0001-Google-Markers-Draw-Performance.md` - Addresses marker clustering draw performance by disabling draw during addition but keeping repaint after addition + +## PR Requirements + +**Critical:** PRs must include: +- Link to sample page demonstrating the change +- Problem description ("What was happening?") +- Solution description ("What was done?") +- Test steps +- Screenshots or GIFs + +**Labels Required:** At least one of `feature`, `bug`/`bugfix`, `dependencies`, `chore`. Avoid `do not merge` label. + +**Branch:** Create from `dev` with pattern `` or `-description` (e.g., `ROU-12619`) + +**PR Title:** Must match regex `^([A-Z][A-Z0-9]*-\d+(:)?\s\w)` (e.g., `ROU-12619 Fix marker clustering performance`) + +See [CONTRIBUTING.md](./.github/CONTRIBUTING.md#pull-request-requirements) for complete PR requirements. + +## Common Tasks + +**Adding a new map provider:** +1. Create provider directory: `src/Providers/Maps//` +2. Implement interfaces from `src/OSFramework/Maps/` +3. Add factory logic in `src/OSFramework/Maps/OSMap/Factory.ts` +4. Create configuration transformer in provider's `Configuration/` directory +5. Follow [ARCHITECTURE.md T1](./ARCHITECTURE.md#t1-provider-abstraction-must-isolate-external-dependencies) - no framework changes should be needed + +**Adding a new map feature:** +1. Define interface in `src/OSFramework/Maps//I.ts` +2. Create abstract class in `src/OSFramework/Maps//Abstract.ts` +3. Implement in each provider: `src/Providers/Maps/Google//` and `Leaflet//` +4. Add factory method in `src/OSFramework/Maps//Factory.ts` +5. Expose in public API: `src/OutSystems/Maps/MapAPI/Manager.ts` + +**Modifying provider-specific behavior:** +- Google Maps: `src/Providers/Maps/Google/` +- Leaflet: `src/Providers/Maps/Leaflet/` +- Never import provider types into `OSFramework/` or `OutSystems/` namespaces (see [ARCHITECTURE.md T2](./ARCHITECTURE.md#t2-public-api-must-return-framework-interfaces-not-provider-types)) + +## Links + +- **Forge component:** https://www.outsystems.com/forge/component-overview/9909/outsystems-maps +- **Sample app:** https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample +- **Living docs:** https://outsystemsui.outsystems.com/OutSystemsMapsSample/ +- **Official docs:** https://success.outsystems.com/Documentation/11/Developing_an_Application/Design_UI/Patterns/Using_Mobile_and_Reactive_Patterns/Map +- **Support:** https://www.outsystems.com/forge/component-discussions/9909/OutSystems+Maps +- **Tests repository:** https://github.com/OutSystems/outsystems-maps-tests From 7c0fe45f5107515bc2b14d2332ab29c88d065013 Mon Sep 17 00:00:00 2001 From: gnbm Date: Tue, 3 Mar 2026 22:19:31 +0000 Subject: [PATCH 2/5] Update CLAUDE.md --- CLAUDE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 37610d5d..4e7a75b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,6 +93,9 @@ Provider selection happens in `OSFramework/Maps/OSMap/Factory.ts` via `MapFactor - Supports tile layers, markers with popups, vector geometries, image overlays, GeoJSON - Hardware acceleration on mobile, CSS-driven smooth panning/zooming - Custom map projections (EPSG:3857/4326/3395) +- BSD 2-Clause License (highly permissive open-source) + +**External Context Note:** The external context provided information about the Leaflet library from its GitHub repository. This information is consistent with the codebase's use of Leaflet as one of the two supported map providers. The library size (~40 KB gzipped) and design principles match the implementation observed in `src/Providers/Maps/Leaflet/`. ### Configuration Pattern From eefc82774c17e24023c7afc3d2138a87f5835467 Mon Sep 17 00:00:00 2001 From: gnbm Date: Wed, 4 Mar 2026 14:56:46 +0000 Subject: [PATCH 3/5] Complement Forge information --- CLAUDE.md | 3 ++- README.md | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4e7a75b8..dc5c0dab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -198,7 +198,8 @@ See [CONTRIBUTING.md](./.github/CONTRIBUTING.md#pull-request-requirements) for c ## Links -- **Forge component:** https://www.outsystems.com/forge/component-overview/9909/outsystems-maps +- **Forge component - O11:** https://www.outsystems.com/forge/component-overview/9909/outsystems-maps-o11 +- **Forge component - ODC:** https://www.outsystems.com/forge/component-overview/15930/outsystems-maps-odc - **Sample app:** https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample - **Living docs:** https://outsystemsui.outsystems.com/OutSystemsMapsSample/ - **Official docs:** https://success.outsystems.com/Documentation/11/Developing_an_Application/Design_UI/Patterns/Using_Mobile_and_Reactive_Patterns/Map diff --git a/README.md b/README.md index 2f83ad17..a6f91415 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Use the OutSystems Maps to create visual rich enterprise-grade interfaces that h * **No javascript knowledge required** ### Where can you find the component? -The OutSystems component, like all components, can be found in [OutSystems forge](https://www.outsystems.com/forge/component-overview/9909/outsystems-maps). There you can also find a [sample application](https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample) that show-cases several uses of the component. +The OutSystems component, like all components, can be found in [OutSystems Forge](https://www.outsystems.com/forge/component-overview/9909/outsystems-maps) and [OutSystems Forge Component Page (ODC)](https://www.outsystems.com/forge/component-overview/15930/outsystems-maps-odc). There you can also find a [sample application](https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample) that show-cases several uses of the component. The documentation for the component can be found in the [official page](https://success.outsystems.com/Documentation/11/Developing_an_Application/Design_UI/Patterns/Using_Mobile_and_Reactive_Patterns/Map), as well as, in a more interactive way in the [Component living documentation](https://outsystemsui.outsystems.com/OutSystemsMapsSample/). ### Why use this component? @@ -78,7 +78,8 @@ To be accepted, a Pull Request needs to: * Avoid exposing sensible information of any kind (e.g. internal server link, process, etc). ## Useful Links -* Download latest version in [OutSystems forge](https://www.outsystems.com/forge/component-versions/9909) +* Download latest O11 version in [OutSystems forge](https://www.outsystems.com/forge/component-overview/9909/outsystems-maps-o11) +- Download latest ODC version in [OutSystems Forge Component Page (ODC)](https://www.outsystems.com/forge/component-overview/15930/outsystems-maps-odc) * Test the latest changes in the [sample app](https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample) * [Component living documentation](https://outsystemsui.outsystems.com/OutSystemsMapsSample/) * Component [documentation](https://success.outsystems.com/Documentation/11/Developing_an_Application/Design_UI/Patterns/Using_Mobile_and_Reactive_Patterns/Map) From a384c92cf32799f80aec3abac594889a8bd151c6 Mon Sep 17 00:00:00 2001 From: gnbm Date: Wed, 4 Mar 2026 17:49:25 +0000 Subject: [PATCH 4/5] Add context about providers --- .claude/settings.local.json | 4 +- .github/CONTRIBUTING.md | 98 ++++++++++++++++++++------------- ARCHITECTURE.md | 23 ++++---- CLAUDE.md | 105 ++++++++++++------------------------ 4 files changed, 113 insertions(+), 117 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 8d9d9505..db49d0e8 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -6,7 +6,9 @@ "Bash(echo MISSING: $file:*)", "WebFetch(domain:outsystemsui-qa.outsystemsenterprise.com)", "WebFetch(domain:developers.google.com)", - "WebFetch(domain:leafletjs.com)" + "WebFetch(domain:leafletjs.com)", + "WebFetch(domain:unpkg.com)", + "WebFetch(domain:app.unpkg.com)" ] } } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 44f549f7..c7ba7b80 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to OutSystems Maps -Thank you for contributing to OutSystems Maps. This guide covers the development workflow and standards for this TypeScript-based mapping component library. +Thank you for contributing to OutSystems Maps. This guide covers the development workflow and standards for this TypeScript mapping component library. ## Development Setup @@ -10,8 +10,8 @@ Thank you for contributing to OutSystems Maps. This guide covers the development - [Visual Studio Code](https://code.visualstudio.com/) (recommended) **Recommended VS Code Extensions:** -- Document This -- ESLint +- Document This (JSDoc comment templates) +- ESLint (code quality enforcement) - Prettier - Code formatter **Setup:** @@ -20,7 +20,7 @@ npm install npm run dev # Starts development server at http://localhost:3000 ``` -The development server watches for TypeScript changes and recompiles automatically. +The development server watches for TypeScript changes and recompiles automatically with hot reload. ## Development Workflow @@ -36,13 +36,18 @@ git checkout -b ROU-1234 Examples: `ROU-12619`, `ROU-12504-fix-marker-clustering` +Branches named `release/*` or `merge/*` are exempt from PR title validation. + ### Commit Messages -No strict commit format enforced. Use clear, descriptive messages that explain the change. +No strict commit format is enforced. Use clear, descriptive messages that explain the change. ### Pull Request Requirements **PR Title Format:** + +PR titles must match the regex `^([A-Z][A-Z0-9]*-\d+(:)?\s\w)` (enforced by CI): + ``` ``` @@ -51,42 +56,39 @@ Examples: - `ROU-12619 Fix marker clustering performance` - `ROU-12558 Mark release as latest` -The title must match the regex: `^([A-Z][A-Z0-9]*-\d+(:)?\s\w)` (enforced by CI). - **Required Labels:** -PRs must have at least one of these labels: +PRs must have at least one of these labels (enforced by CI): - `feature` -- `bug` / `bugfix` -- `dependencies` / `dependency` +- `bug` or `bugfix` +- `dependencies` or `dependency` - `chore` -PRs with `do not merge` label will be blocked. +PRs with `do not merge` label will be blocked from merging. -**Before Submitting:** -1. Test locally using the dev server -2. Run `npm run build` to ensure the build succeeds -3. Fix all ESLint errors and warnings -4. Document your code using JSDoc comments (type `/**` above functions) -5. Fill out the PR template completely +**PR Content Requirements:** -**PR Template Requirements:** +The PR template requires: - Link to sample page demonstrating the change -- What was happening (the problem) -- What was done (the solution) +- Problem description ("What was happening?") +- Solution description ("What was done?") - Test steps to verify the fix - Screenshots or animated GIFs -- Checklist confirmation +- Checklist confirmation (tested locally, documented, ESLint clean, etc.) -PRs require approval from 2 team members before merge. +**Before Submitting:** +1. Test locally: `npm run dev` +2. Build succeeds: `npm run build` +3. No ESLint errors: `npm run lint` +4. Add JSDoc comments (type `/**` above functions) ## Building and Testing | Command | Description | |---------|-------------| | `npm run setup` | Install dependencies and start dev server | -| `npm run dev` | Start development server with hot reload | -| `npm run build` | Build production bundle with linting | +| `npm run dev` | Start development server with hot reload at http://localhost:3000 | +| `npm run build` | Production build: clean + transpile + lintfix + lint | | `npm run lint` | Check code style (ESLint) | | `npm run lintfix` | Auto-fix ESLint issues | | `npm run prettier` | Format all JS/TS/CSS files | @@ -94,27 +96,29 @@ PRs require approval from 2 team members before merge. **Note:** `npm test` is not configured. Manual testing via the dev server and sample pages is required. -## Testing - -Automated tests are maintained in a separate repository: [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) +### Testing -The test suite uses Gherkin/BDD framework with WebDriver.io and supports: -- Multiple browsers (Chrome, Firefox, Edge, Safari) -- Multiple environments (dev, qa) -- Local and SauceLabs execution +Automated tests are maintained in a separate private repository: [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) -To run tests locally (from the tests repository): +To run tests locally (requires `gh` CLI): ```bash +gh repo clone OutSystems/outsystems-maps-tests ../outsystems-maps-tests +cd ../outsystems-maps-tests npm run local -- --browsers=chrome --environment=dev --map=web ``` +**Manual Testing Resources:** +- Development server: `npm run dev` → http://localhost:3000 +- Sample app: https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample +- Living documentation: https://outsystemsui.outsystems.com/OutSystemsMapsSample/ + ## Code Standards ### TypeScript - **Target:** ES2017, compiled to AMD module -- **Output:** Single file at `dist/OutSystemsMaps.js` -- **Style:** Strict ESLint rules enforced (see `.eslintrc.json`) +- **Output:** Single file at `dist/OutSystemsMaps.js` (configured in `tsconfig.json`) +- **Style:** Strict ESLint rules enforced (`.eslintrc.json`) ### Naming Conventions @@ -129,7 +133,8 @@ Enforced by ESLint: ### Member Ordering -Class members alphabetically ordered within groups: +Class members must be alphabetically ordered within groups (enforced by ESLint `@typescript-eslint/member-ordering`): + 1. Private fields 2. Protected fields 3. Public fields @@ -151,16 +156,35 @@ Run `npm run prettier` to format all files. ## Documentation -Document all public APIs using JSDoc comments. VS Code's "Document This" extension provides templates when you type `/**`. +Document all public APIs using JSDoc comments. VS Code's "Document This" extension provides templates when you type `/**` above a function. -Architectural decisions are documented in `docs/adr/`. Follow the template in `docs/adr/ADR-0000-Title-of-ADR.md`. +**Architectural Decision Records:** + +Architectural decisions are documented in `docs/adr/`. Follow the template in `docs/adr/ADR-0000-Title-of-ADR.md` when creating new ADRs. + +## Common Patterns + +**Provider Abstraction:** + +When modifying provider-specific behavior: +- Google Maps implementation: `src/Providers/Maps/Google/` +- Leaflet implementation: `src/Providers/Maps/Leaflet/` +- Never import provider types into `src/OSFramework/` or `src/OutSystems/` namespaces + +See [ARCHITECTURE.md](../ARCHITECTURE.md) for details on the provider abstraction pattern. + +**Adding New Features:** + +See [CLAUDE.md](../CLAUDE.md#common-tasks) for step-by-step guidance on adding new map features or providers. ## Support and Communication **External Contributors:** + Contact the UI Components team via [component support page](https://www.outsystems.com/forge/component-discussions/9909/OutSystems+Maps) **Internal Contributors:** + Slack channel `#rd-uicomponents-contributors` (business days, 2-3 PM PT) Trusted Committer: [UI Components team on support rotation](mailto:rd.uicomponents.team@outsystems.com) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 9a257d6e..930155d1 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -2,11 +2,11 @@ > **Repository:** outsystems-maps > **Runtime Environment:** User Browser (JavaScript Library) -> **Last Updated:** 2026-03-03 +> **Last Updated:** 2026-03-04 ## Overview -OutSystems Maps is a TypeScript library that provides a unified API for integrating interactive maps into OutSystems Reactive Web applications. It abstracts multiple map providers (Google Maps and Leaflet/OpenStreetMap) behind a common interface, allowing developers to build map-based features without JavaScript knowledge. +OutSystems Maps is a TypeScript library that compiles to a single AMD module providing a unified API for interactive maps in OutSystems Reactive Web applications. It abstracts Google Maps and Leaflet/OpenStreetMap behind framework interfaces, allowing developers to build map-based features without JavaScript knowledge. ## Architecture Diagram @@ -39,9 +39,14 @@ graph TB | External Service | Communication Type | Purpose | |------------------|-------------------|---------| -| Google Maps JavaScript API | Sync (HTTPS/JavaScript) | Render Google Maps, geocoding, places search, marker clustering, drawing tools | +| Google Maps JavaScript API | Sync (HTTPS/JavaScript) | Render Google Maps, geocoding, places search, drawing tools, visualization libraries (v3.61+) | | Google Routes API | Sync (HTTPS) | Calculate directions and route polylines via `routes.googleapis.com/directions/v2:computeRoutes` | +| @googlemaps/markerclusterer | Sync (JavaScript Library) | Create and manage per-zoom-level clusters for large marker volumes (v2.5.3) | | OpenStreetMap Tiles | Sync (HTTPS) | Render Leaflet-based maps with OSM tile layers from `tile.openstreetmap.org` | +| Leaflet.Draw | Sync (JavaScript Library) | Enable interactive geometry drawing toolbar on Leaflet maps (v1.0.4) | +| Leaflet.Editable | Sync (JavaScript Library) | Enable interactive geometry editing (polylines, polygons) on Leaflet maps (v1.3.0) | +| Leaflet.Path.Drag | Sync (JavaScript Library) | Add dragging capabilities to Leaflet vector features (v1.9.5) | +| Leaflet Routing Machine | Sync (JavaScript Library) | Calculate routes for Leaflet maps with pluggable backends (OSRM, GraphHopper, TomTom) (v3.2.12) | | OutSystems Platform | Sync (JavaScript API) | Host application that consumes this library via block parameters and events | ## Architectural Tenets @@ -68,11 +73,11 @@ The OutSystems-facing API in `OutSystems.Maps.MapAPI` operates exclusively on fr ### T3. Framework Layer Owns Lifecycle and State Management -The `OSFramework` layer controls all component lifecycle (creation, initialization, disposal) and maintains parent-child relationships (maps contain markers, shapes, file layers). Provider implementations are passive adapters that respond to framework commands via the `build()` and `dispose()` methods defined by shared interfaces, but do not independently manage their lifecycle or relationships. +The `OSFramework` layer controls all component lifecycle (creation, initialization, disposal) and maintains parent-child relationships (maps contain markers, shapes, file layers, heatmap layers, drawing tools). Provider implementations are passive adapters that respond to framework commands via the `build()` and `dispose()` methods defined by shared interfaces, but do not independently manage their lifecycle or relationships. **Evidence:** - `src/OSFramework/Maps/OSMap/AbstractMap.ts` (in `build`, `finishBuild`) - framework controls initialization sequence and triggers events -- `src/OSFramework/Maps/OSMap/AbstractMap.ts` (private fields `_markers`, `_shapes`, `_fileLayers`) - framework maintains collections of child components +- `src/OSFramework/Maps/OSMap/AbstractMap.ts` (private fields `_markers`, `_shapes`, `_fileLayers`, `_heatmapLayers`) - framework maintains collections of child components - `src/OSFramework/Maps/Interfaces/IBuilder.ts` and `IDisposable.ts` - shared interfaces that enforce lifecycle contract - `src/OSFramework/Maps/Marker/AbstractMarker.ts` (in `finishBuild`) - framework triggers initialization event and adds marker to clusterer after provider completes setup @@ -83,7 +88,7 @@ User-facing configuration uses OutSystems-friendly structures (JSON strings, int **Evidence:** - `src/OSFramework/Maps/Configuration/AbstractConfiguration.ts` (in `getProviderConfig`) - defines contract for transforming framework config to provider config - `src/Providers/Maps/Google/Configuration/OSMap/GoogleMapConfig.ts` (in `getProviderConfig`) - transforms framework config to Google Maps API options, including mapId handling for advanced markers -- `src/Providers/Maps/Leaflet/Configuration/OSMap/LeafletMapConfiguration.ts` (in `getProviderConfig`) - transforms framework config to Leaflet API options +- `src/Providers/Maps/Leaflet/Configuration/OSMap/LeafletMapConfiguration.ts` (in `getProviderConfig`) - transforms framework config to Leaflet API options, sets editable flag for drawing tools - `src/OutSystems/Maps/MapAPI/MapManager.ts` (in `CreateMap`) - accepts JSON config string from OutSystems, parses and passes to factory ### T5. Events Flow Through Framework Event Managers @@ -92,6 +97,6 @@ All events (map clicks, marker interactions, provider-specific events) are norma **Evidence:** - `src/OSFramework/Maps/Event/AbstractEventsManager.ts` - provides centralized event subscription and dispatch mechanism used by all component types -- `src/OSFramework/Maps/Event/OSMap/MapEventsManager.ts` - manages all map-level events independent of provider, validates provider event types -- `src/Providers/Maps/Google/OSMap/OSMap.ts` (uses `google.maps.event.addListener`) - Google provider adds listeners via native API but triggers framework events -- `src/Providers/Maps/Leaflet/OSMap/OSMap.ts` (in `_setMapEvents`) - Leaflet provider converts native events to framework event format before triggering +- `src/OSFramework/Maps/Event/OSMap/MapEventsManager.ts` (in `getInstanceOfEventType`) - validates provider event types before creating event instances +- `src/Providers/Maps/Google/OSMap/OSMap.ts` (private method `_setMapEvents`) - Google provider adds listeners via native API but triggers framework events +- `src/Providers/Maps/Leaflet/OSMap/OSMap.ts` (private method `_setMapEvents`) - Leaflet provider converts native events to framework event format before triggering diff --git a/CLAUDE.md b/CLAUDE.md index dc5c0dab..88d27f08 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,19 +7,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co OutSystems Maps is a TypeScript library providing a unified API for Google Maps and Leaflet/OpenStreetMap integration in OutSystems Reactive Web applications. The library compiles to a single AMD module (`dist/OutSystemsMaps.js`) that abstracts provider differences behind framework interfaces. **Foundation Documents:** -- See [ARCHITECTURE.md](./ARCHITECTURE.md) for the provider abstraction pattern, architectural tenets (T1-T5), and external integrations table -- See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for development workflow, PR requirements, and code standards +- See [ARCHITECTURE.md](./ARCHITECTURE.md) for the provider abstraction pattern, architectural tenets (T1-T5), architecture diagram, and external integrations table +- See [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for development workflow, branch naming, PR requirements, code standards, and member ordering rules ## Build and Development Commands -**Setup and Development:** ```bash npm install # Install dependencies npm run dev # Start dev server at http://localhost:3000 with hot reload -``` - -**Build and Quality:** -```bash npm run build # Production build: clean + transpile + lintfix + lint npm run lint # Check ESLint errors/warnings npm run lintfix # Auto-fix ESLint issues @@ -27,9 +22,9 @@ npm run prettier # Format all JS/TS/CSS files npm run docs # Generate TypeDoc documentation ``` -**Note:** No automated tests exist in this repository (`npm test` exits with error). Automated tests are maintained in the separate [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) repository. +**Build System:** Gulp-based. Check `gulpfile.js` and `gulp/Tasks/` for task definitions. TypeScript compiles to single file via `tsconfig.json` `outFile: "./dist/OutSystemsMaps.js"`. -**Build System:** Gulp-based. Check `gulpfile.js` and `gulp/Tasks/` for task definitions. TypeScript compiles to single file via tsconfig `outFile: "./dist/OutSystemsMaps.js"`. +**Testing:** No automated tests exist in this repository (`npm test` exits with error). Tests are maintained in separate private repository [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests). See [CONTRIBUTING.md Testing section](./.github/CONTRIBUTING.md#testing) for how to run tests locally via `gh repo clone`. ## Repository Structure @@ -38,6 +33,7 @@ src/ ├── OSFramework/Maps/ # Framework layer (provider-agnostic) │ ├── Configuration/ # Config transformation interfaces │ ├── Event/ # Event management (MapEventsManager, MarkerEventsManager, etc.) +│ ├── Feature/ # Feature abstractions (Directions) │ ├── Marker/ # Marker abstractions │ ├── Shape/ # Shape abstractions (Polygon, Polyline, Circle) │ ├── OSMap/ # Map abstractions @@ -49,53 +45,37 @@ src/ │ ├── Google/ # Google Maps adapter │ └── Leaflet/ # Leaflet/OSM adapter ├── OutSystems/Maps/ # Public API -│ ├── MapAPI/ # Map management (MapManager, MarkerManager, ShapeManager, etc.) +│ ├── MapAPI/ # Map management (MapManager, MarkerManager, ShapeManager, Directions, etc.) │ └── PlacesAPI/ # Places search -└── Files/ # Static assets +└── Files/ # Static assets (loaded at runtime) ├── Google/ # Google Maps scripts - └── Leaflet/ # Leaflet scripts/styles -``` - -**Key Separation:** `OSFramework/` defines interfaces and abstractions. `Providers/` contains Google Maps and Leaflet implementations. `OutSystems/` exposes the public API. See [ARCHITECTURE.md T1](./ARCHITECTURE.md#t1-provider-abstraction-must-isolate-external-dependencies) for provider isolation details. - -## Testing and Verification - -Automated tests are maintained in a separate private repository: [outsystems-maps-tests](https://github.com/OutSystems/outsystems-maps-tests) - -**To run tests locally (requires gh CLI):** -```bash -# Clone the tests repository -gh repo clone OutSystems/outsystems-maps-tests ../outsystems-maps-tests - -# Run tests -cd ../outsystems-maps-tests -npm run local -- --browsers=chrome --environment=dev --map=web + ├── Leaflet/ # Leaflet scripts/styles + │ └── Directions/ # Routing backend extensions (GraphHopper, TomTom) + └── Internal/ # Internal assets ``` -**Manual testing via dev server:** -1. Start dev server: `npm run dev` -2. Test changes at `http://localhost:3000` -3. Reference sample app: https://www.outsystems.com/forge/component-overview/10984/outsystems-maps-sample -4. Check component living docs: https://outsystemsui.outsystems.com/OutSystemsMapsSample/ +**Key Separation:** `OSFramework/` defines interfaces and abstractions. `Providers/` contains Google Maps and Leaflet implementations. `OutSystems/` exposes the public API. See [ARCHITECTURE.md T1](./ARCHITECTURE.md#t1-provider-abstraction-must-isolate-external-dependencies) for provider isolation enforcement. ## Important Context ### Map Provider Architecture The library supports two map providers selected at runtime: -- **Google Maps:** Requires API key, provides full Google Maps JavaScript API capabilities (geocoding, places search, marker clustering, advanced markers) -- **Leaflet:** Open-source library for mobile-friendly interactive maps (~42 KB, no dependencies), uses OpenStreetMap tiles (no API key required) +- **Google Maps:** Requires API key, provides full Google Maps JavaScript API capabilities (geocoding, places search, marker clustering via `@googlemaps/markerclusterer` v2.5.3, advanced markers, directions via Google Routes API) +- **Leaflet:** Open-source library for mobile-friendly interactive maps (~42 KB, no dependencies), uses OpenStreetMap tiles (no API key required), extensible with Leaflet plugins Provider selection happens in `OSFramework/Maps/OSMap/Factory.ts` via `MapFactory.MakeMap()`. All provider-specific code is isolated in `Providers/` directories. -**Leaflet Characteristics:** -- Design philosophy: simplicity, performance, usability -- Supports tile layers, markers with popups, vector geometries, image overlays, GeoJSON -- Hardware acceleration on mobile, CSS-driven smooth panning/zooming -- Custom map projections (EPSG:3857/4326/3395) -- BSD 2-Clause License (highly permissive open-source) +**Directions/Routing:** Both providers support calculating routes between points. Google uses Routes API (`routes.googleapis.com/directions/v2:computeRoutes`). Leaflet uses [Leaflet Routing Machine](https://github.com/perliedman/leaflet-routing-machine) v3.2.12 with pluggable backends (OSRM default, plus GraphHopper/TomTom extensions in `Files/Leaflet/Directions/`). See [ARCHITECTURE.md External Integrations table](./ARCHITECTURE.md#external-integrations) for integration details. -**External Context Note:** The external context provided information about the Leaflet library from its GitHub repository. This information is consistent with the codebase's use of Leaflet as one of the two supported map providers. The library size (~40 KB gzipped) and design principles match the implementation observed in `src/Providers/Maps/Leaflet/`. +**Drawing Tools:** Both providers support interactive drawing and editing of geometries: +- **Google:** Uses native Drawing Manager API +- **Leaflet:** Combines three libraries: + - [Leaflet.Draw](https://github.com/Leaflet/Leaflet.draw) v1.0.4 - Provides drawing toolbar UI (`L.Control.Draw`) with handlers for polylines, polygons, rectangles, circles, markers + - [Leaflet.Editable](https://github.com/Leaflet/Leaflet.Editable) v1.3.0 - Enables programmatic geometry editing on individual layers + - [Leaflet.Path.Drag](https://github.com/w8r/Leaflet.Path.Drag) v1.9.5 - Adds drag capabilities to vector features (polygons, polylines), mirroring marker drag API with dragstart/drag/dragend events + +Implementation in `src/Providers/Maps/Leaflet/DrawingTools/DrawingTools.ts` uses Leaflet.Draw for toolbar control and drawing modes. Maps initialize with `{editable: true}` option, then editing is enabled on individual layers via Leaflet.Editable. See [ARCHITECTURE.md External Integrations table](./ARCHITECTURE.md#external-integrations) for versions and external dependencies. ### Configuration Pattern @@ -124,56 +104,41 @@ Framework layer controls all lifecycle via abstract classes: - `finishBuild()` → trigger event cascade - `dispose()` → cleanup -Provider implementations respond to framework commands but do not manage their own lifecycle. Framework maintains parent-child relationships (maps contain markers, shapes, file layers). +Provider implementations respond to framework commands but do not manage their own lifecycle. Framework maintains parent-child relationships (maps contain markers, shapes, file layers, features). See [ARCHITECTURE.md T3](./ARCHITECTURE.md#t3-framework-layer-owns-lifecycle-and-state-management) for lifecycle ownership details. ## Code Standards -**Member Ordering (enforced by ESLint):** -1. Private fields (`_name`) -2. Protected fields -3. Public fields -4. Constructor -5. Private methods -6. Protected methods -7. Public methods - -Within each group: alphabetical order. +See [CONTRIBUTING.md Code Standards section](./.github/CONTRIBUTING.md#code-standards) for complete code standards. -**Naming:** -- Exported functions: `StrictPascalCase` -- Interfaces: `IPascalCase` (must start with `I`) +**Quick reference:** - Private properties/methods: `_strictCamelCase` (leading underscore required) - Public/protected: `strictCamelCase` (no underscore) - -**Formatting:** Single quotes, semicolons required, 120 char width, tabs (width 4). Prettier config in `.prettierrc.json`. - -See [CONTRIBUTING.md](./.github/CONTRIBUTING.md#code-standards) for complete standards. +- Interfaces: `IPascalCase` (must start with `I`) +- Exported functions/classes: `StrictPascalCase` +- Member ordering: private fields → protected fields → public fields → constructor → private methods → protected methods → public methods (alphabetical within each group, enforced by ESLint) ## Documentation Document public APIs with JSDoc comments. Type `/**` above functions for templates (VS Code "Document This" extension). Architectural decisions documented in `docs/adr/`. Use `docs/adr/ADR-0000-Title-of-ADR.md` as template. Existing ADRs: -- `ADR-0001-Google-Markers-Draw-Performance.md` - Addresses marker clustering draw performance by disabling draw during addition but keeping repaint after addition +- `ADR-0001-Google-Markers-Draw-Performance.md` - Disables draw during marker addition but keeps repaint after addition to optimize marker clustering performance ## PR Requirements +See [CONTRIBUTING.md Pull Request Requirements section](./.github/CONTRIBUTING.md#pull-request-requirements) for complete PR requirements. + **Critical:** PRs must include: - Link to sample page demonstrating the change - Problem description ("What was happening?") - Solution description ("What was done?") -- Test steps -- Screenshots or GIFs - -**Labels Required:** At least one of `feature`, `bug`/`bugfix`, `dependencies`, `chore`. Avoid `do not merge` label. - -**Branch:** Create from `dev` with pattern `` or `-description` (e.g., `ROU-12619`) - -**PR Title:** Must match regex `^([A-Z][A-Z0-9]*-\d+(:)?\s\w)` (e.g., `ROU-12619 Fix marker clustering performance`) +- Test steps and screenshots/GIFs +- At least one label: `feature`, `bug`/`bugfix`, `dependencies`, `chore` -See [CONTRIBUTING.md](./.github/CONTRIBUTING.md#pull-request-requirements) for complete PR requirements. +**Branch pattern:** `` or `-description` (e.g., `ROU-12619`) +**PR title format:** ` ` (e.g., `ROU-12619 Fix marker clustering performance`) ## Common Tasks From 7b018d3bc61628f11dafaadaf82fa8d3a5ff639a Mon Sep 17 00:00:00 2001 From: gnbm Date: Fri, 6 Mar 2026 18:09:31 +0000 Subject: [PATCH 5/5] Update CONTRIBUTING.md --- .github/CONTRIBUTING.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c7ba7b80..76d8b338 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,6 +2,10 @@ Thank you for contributing to OutSystems Maps. This guide covers the development workflow and standards for this TypeScript mapping component library. +## Code of Conduct + +We must follow the code of conduct of OutSystems. + ## Development Setup **Prerequisites:** @@ -82,6 +86,8 @@ The PR template requires: 3. No ESLint errors: `npm run lint` 4. Add JSDoc comments (type `/**` above functions) + + ## Building and Testing | Command | Description | @@ -188,6 +194,17 @@ Contact the UI Components team via [component support page](https://www.outsyste Slack channel `#rd-uicomponents-contributors` (business days, 2-3 PM PT) Trusted Committer: [UI Components team on support rotation](mailto:rd.uicomponents.team@outsystems.com) + +## Trusted Committers + +Our Trusted Committer will always be the [UI Components team member on support rotation](mailto:rd.uicomponents.team@outsystems.com). + + +## Trusted Committer Availability Schedule + +Our Trusted Committees are available internally on Slack channel _#rd-uicomponents-contributors_ on business days from 2PM-3PM (PT time). + + ## License This repository is proprietary to OutSystems. All rights reserved.