Add standalone lead and opportunity forms#65
Draft
LoesV wants to merge 20 commits into
Draft
Conversation
Add "Add lead" and "Add opportunity" forms that are accessible to users without Dynamics/Dataverse access. These forms submit via new DataMiner automation scripts (DynamicsActivities_SubmitLead and DynamicsActivities_SubmitOpportunity) that email the submissions to a configured recipient. Includes: - Two new automation scripts with HTML email formatting - Form components with validation and success states - Hash-based router for standalone form pages - Form registry system for adding future forms - "Add lead" and "Add opportunity" buttons on auth-denied screens - Styling for form grids, actions, and success messages - Updated documentation
…ications/DynamicsActivities into lead-creation-flow
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add isTestEnvironment() so the bottom-left license view tester renders on localhost and the DataMiner dev deployment (/public/DynamicsActivitiesDev/) but never on production or RC. Enrich the detected label with the full systemuser.caltype option-set names (verified against the Dataverse Web API reference). Bump package to 1.11.0 and document the control in the README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reworked lead and opportunity submissions to open a prefilled email draft in the user’s mail client instead of calling DataMiner automation scripts. Added a shared `mailto` helper to build and launch drafts, updated both API clients to use it, and simplified both form components by removing async submit/loading and confirmation modal flows. The solution file was also updated to remove the now-unused submit script projects.
Lead and opportunity mailto drafts now include a 'Submitted by: Name <email>' line populated from the DMA session user. Both name and email are guarded — empty/missing values are omitted. Adds a reusable `formatSubmitter` helper in mailto.js.
Lead and opportunity forms now reuse the shared Dataverse account search via `AutocompletePicker`, suggesting existing accounts while still allowing free-text company entry through raw query updates. The picker now supports an `onQueryChange` callback and resets cleanly when submitting another item. This update also adjusts lead handling: first name, last name, and email are now optional (with email format checked only when provided), and lead email subjects use the lead topic plus optional company instead of contact name. Package version metadata was bumped to 1.12.4 with an updated version comment.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds standalone lead/opportunity submission flows to the DynamicsActivities SPA, aimed at Team Member CAL users who can browse but can’t manage leads/opportunities natively in Dynamics. It introduces hash-based routing for these standalone pages and adds a local/dev-only license “view override” widget to preview access states, alongside packaging and CI/CD updates for dev deployments.
Changes:
- Added standalone
#/forms/leadand#/forms/opportunitypages (registry + shared shell) that submit via prefilledmailto:drafts. - Added Team Member-only “Add lead/opportunity” entry points from the Leads/Opportunities browse views, plus license/CAL detection and a local/dev test override control.
- Updated DMAPP packaging + GitHub workflows to better support dev folder deployments and non-production version suffixing.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/styles/main.css | Adds styling for standalone forms, confirmation modal/footer, filter add button placement, and the license test widget. |
| src/main.jsx | Wraps app in LicenseTestProvider and conditionally renders the license test control in test environments. |
| src/hooks/useHashRoute.js | Introduces a minimal hash router + navigation helper for #/forms/... routes. |
| src/forms/registry.js | Central registry for standalone forms (lead, opportunity). |
| src/context/LicenseTestContext.jsx | Adds persisted license-view override state and helpers for Sales vs Team Member behavior. |
| src/components/NotesList.jsx | Adds per-view “Add lead/opportunity” buttons for Team Member users and persists active browse view in sessionStorage. |
| src/components/LicenseTestControl.jsx | Adds a pinned local/dev test UI to force access/license views. |
| src/components/forms/OpportunityForm.jsx | New standalone opportunity form that opens a prefilled email draft. |
| src/components/forms/LeadForm.jsx | New standalone lead form that opens a prefilled email draft. |
| src/components/forms/FormPage.jsx | Generic standalone form page shell with header/back navigation. |
| src/components/AutocompletePicker.jsx | Adds onQueryChange hook to support free-text entry alongside suggestions. |
| src/components/AuthGuard.jsx | Reports detected CAL type and supports test overrides for license/access state. |
| src/components/ActivityForm.jsx | Honors license test override when deciding whether to show lead-management links. |
| src/App.jsx | Routes forms/* outside the AuthGuard; wires currentUserId into NotesList. |
| src/api/opportunities.js | Mailto-based submission client for opportunity form. |
| src/api/mailto.js | Shared helpers to build and open mailto: drafts and format submitter info. |
| src/api/leads.js | Mailto-based submission client for lead form. |
| src/api/dataminer.js | Adds DataMinerServerError surfacing option and isTestEnvironment() helper. |
| README.md | Updates docs for standalone forms and adds documentation for license test control. |
| package.json | Bumps frontend package version. |
| DynamicsActivitiesPackage/DynamicsActivitiesPackage/PackageContent/CompanionFiles/Skyline DataMiner/.gitignore | Broadens ignore to cover production + dev web public folders. |
| DynamicsActivitiesPackage/DynamicsActivitiesPackage/DynamicsActivitiesPackage.csproj | Updates version/comment and adjusts companion file copying/cleaning logic for dev/prod folder targets. |
| .github/workflows/deploy-dmapp-reusable.yml | Adds workflow inputs for dev builds/version suffix and passes extra MSBuild properties. |
| .github/workflows/deploy-dma-on-pr-merge.yml | Improves manual deploy UX; adds dev deployment defaults and version suffixing. |
| .github/copilot-instructions.md | Updates key source file list to include new standalone-form and mailto modules. |
Comment on lines
+49
to
+56
| function readStoredOverride() { | ||
| try { | ||
| const stored = localStorage.getItem(STORAGE_KEY) | ||
| return LICENSE_OVERRIDES.some((o) => o.value === stored) ? stored : '' | ||
| } catch { | ||
| return '' | ||
| } | ||
| } |
Comment on lines
+403
to
+421
| const [activeViewId, setActiveViewId] = useState(readStoredActiveView) | ||
| const [canManageLeads, setCanManageLeads] = useState(false) | ||
|
|
||
| // Remember the active view so returning from a standalone form restores it. | ||
| useEffect(() => { | ||
| try { sessionStorage.setItem(ACTIVE_VIEW_STORAGE_KEY, activeViewId) } catch {} | ||
| }, [activeViewId]) | ||
|
|
||
| // Team Member CAL users cannot create leads/opportunities natively in Dynamics, | ||
| // so they get the email-based "Add lead" / "Add opportunity" forms instead. | ||
| // Sales/Enterprise users manage these directly in Dynamics and don't see the buttons. | ||
| const isTeamMember = !resolveCanManageLeads(override, canManageLeads) | ||
|
|
||
| useEffect(() => { | ||
| if (!currentUserId) return | ||
| getUserCanManageLeads(instance, currentUserId) | ||
| .then(setCanManageLeads) | ||
| .catch(() => setCanManageLeads(false)) | ||
| }, [instance, currentUserId]) // eslint-disable-line react-hooks/exhaustive-deps |
Comment on lines
+35
to
+45
| <!-- Public web folder the app is served from (…\Webpages\public\<folder>). | ||
| Defaults to the production folder; override for a dev deploy with | ||
| -p:WebAppPublicFolder=DynamicsActivitiesDev. --> | ||
| <WebAppPublicFolder Condition="'$(WebAppPublicFolder)' == ''">DynamicsActivities</WebAppPublicFolder> | ||
| <!-- Repository root (two levels up) where package.json and vite.config.js live. --> | ||
| <WebAppRoot>$(MSBuildProjectDirectory)\..\..</WebAppRoot> | ||
| <WebAppDistDir>$(WebAppRoot)\dist-dataminer</WebAppDistDir> | ||
| <!-- Default install folder for production; can be overridden via /p:WebAppPublicFolder=... --> | ||
| <WebAppPublicFolder Condition="'$(WebAppPublicFolder)' == ''">DynamicsActivities</WebAppPublicFolder> | ||
| <WebAppCompanionDir>$(MSBuildProjectDirectory)\PackageContent\CompanionFiles\Skyline DataMiner\Webpages\public\$(WebAppPublicFolder)</WebAppCompanionDir> | ||
| <WebAppCompanionRoot>$(MSBuildProjectDirectory)\PackageContent\CompanionFiles\Skyline DataMiner\Webpages\public</WebAppCompanionRoot> | ||
| <WebAppCompanionDir>$(WebAppCompanionRoot)\$(WebAppPublicFolder)</WebAppCompanionDir> |
Comment on lines
+11
to
+12
| <Version>1.12.5</Version> | ||
| <VersionComment>Fix: lead/opportunity forms no longer open multiple email drafts on a fast double-click or Enter+click. Added a synchronous submit guard so the mail draft opens exactly once per submission.</VersionComment> |
Comment on lines
+95
to
+103
| app_base_path: | ||
| description: > | ||
| Public base path the SPA is served from (e.g. /public/MyApp/). | ||
| Passed to the frontend build as VITE_APP_BASE_PATH so asset URLs | ||
| and MSAL redirect paths resolve correctly. Leave empty to use the | ||
| app's built-in default. | ||
| required: false | ||
| type: string | ||
| default: "" |
Comment on lines
+23
to
+24
| | Access gate | Request-license / request-access screen for users without Dynamics access | | ||
| | Standalone forms | `#/forms/lead` and `#/forms/opportunity` render the **Add lead** / **Add opportunity** forms, opened from the Leads / Opportunities browse views by Team Member CAL users | |
Comment on lines
+164
to
+166
| | `src/components/forms/FormPage.jsx` | Generic shell for standalone forms (header + back button); renders forms from the registry | | ||
| | `src/components/forms/LeadForm.jsx` | "Add lead" form shown to users without Dynamics/Dataverse access | | ||
| | `src/components/forms/OpportunityForm.jsx` | "Add opportunity" form shown to users without Dynamics/Dataverse access | |
| .mail-detail-pane { flex: 1; } | ||
| } | ||
|
|
||
| /* License test control (local testing only) */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.