@salesforce/templates 66.11.0 → 66.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/generators/projectGenerator.js +4 -1
- package/lib/generators/projectGenerator.js.map +1 -1
- package/lib/templates/project/angularextapp/.forceignore +15 -0
- package/lib/templates/project/angularextapp/.husky/pre-commit +4 -0
- package/lib/templates/project/angularextapp/.prettierignore +11 -0
- package/lib/templates/project/angularextapp/.prettierrc +17 -0
- package/lib/templates/project/angularextapp/CHANGELOG.md +4086 -0
- package/lib/templates/project/angularextapp/README.md +77 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_d_/_s_/angularextapp1/angularextapp1.digitalExperience-meta.xml +11 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_d_/_s_/angularextapp1/sfdc_cms__site/angularextapp1/_meta.json +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_d_/_s_/angularextapp1/sfdc_cms__site/angularextapp1/content.json +10 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_dc_/angularextapp1.digitalExperienceConfig-meta.xml +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/.forceignore +15 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/.postcssrc.json +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/.prettierignore +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/.prettierrc +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/CHANGELOG.md +4 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/README.md +85 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/angular.json +101 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/angularextapp.uibundle-meta.xml +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/e2e/app.spec.ts +15 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/esbuild/api-version.mjs +17 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/eslint.config.js +60 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/middleware/html.mjs +3 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/middleware/proxy.mjs +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package-lock.json +13600 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package.json +56 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/playwright.config.ts +25 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/public/favicon.ico +0 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/scripts/rewrite-e2e-assets.mjs +30 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/account/account-search.service.ts +196 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/account/distinctAccountIndustries.ts +26 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/account/distinctAccountTypes.ts +26 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/account/getAccountDetail.ts +128 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/account/searchAccounts.ts +58 -0
- package/lib/templates/{uiBundles/angularbasic/src/app/api/graphql-client.service.spec.ts → project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/data-client.service.spec.ts} +36 -6
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/data-client.service.ts +74 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/user-profile.service.ts +126 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/app.config.ts +22 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/app.html +1 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/app.routes.ts +77 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/app.spec.ts +18 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/app.ts +15 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.html +53 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.spec.ts +89 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.ts +81 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/_field-size.scss +42 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/alert/alert.html +31 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/alert/alert.ts +53 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.html +18 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.scss +112 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.ts +57 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/card/card.scss +34 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/card/card.ts +110 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/collapsible/collapsible.html +10 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/collapsible/collapsible.ts +26 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.html +25 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.scss +36 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.ts +41 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.html +34 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.scss +33 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.ts +66 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/dialog/dialog.html +37 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/dialog/dialog.ts +55 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/field/field.html +21 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/field/field.ts +36 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/field-size.ts +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.html +19 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.scss +35 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.ts +36 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/label/label.html +3 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/label/label.ts +17 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/paginator/paginator.html +10 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/paginator/paginator.ts +37 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/popover/popover.html +41 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/popover/popover.ts +40 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.html +24 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.scss +35 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.ts +72 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.html +1 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.scss +23 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.ts +56 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.html +1 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.scss +28 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.ts +24 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/spinner/spinner.ts +35 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth/auth.guard.ts +50 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth/auth.service.ts +126 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth-form/auth-form.html +34 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth-form/auth-form.ts +94 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth-layout/auth-layout.html +2 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/auth-layout/auth-layout.ts +30 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/card-layout/card-layout.html +16 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/card-layout/card-layout.ts +40 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/config/authentication.config.ts +75 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/footer-link/footer-link.html +9 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/footer-link/footer-link.ts +26 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/menu/auth-menu/auth-menu.html +26 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/menu/auth-menu/auth-menu.ts +46 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/reactive-form-page.base.ts +50 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/session/session.html +55 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/session/session.ts +205 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/status-alert/status-alert.html +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/status-alert/status-alert.ts +52 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/submit-button/submit-button.html +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/submit-button/submit-button.scss +17 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/submit-button/submit-button.ts +35 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/auth-helpers.ts +68 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/auth-validators.ts +72 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/helpers.ts +85 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/session-time-servlet.ts +130 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/session-timeout.config.ts +83 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/authentication/utils/session-timeout.service.ts +201 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/breadcrumb/breadcrumb.html +54 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/breadcrumb/breadcrumb.ts +40 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/active-filters.html +23 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/active-filters.ts +78 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-filter.html +18 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-filter.ts +137 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-range-filter.html +11 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-range-filter.ts +69 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/filter-field-wrapper.html +11 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/filter-field-wrapper.ts +36 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/multi-select-filter.html +10 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/multi-select-filter.ts +58 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/numeric-range-filter.html +22 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/numeric-range-filter.ts +146 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/search-filter.html +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/search-filter.ts +82 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/select-filter.html +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/select-filter.ts +65 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/text-filter.html +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/text-filter.ts +90 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/object-search-state.service.ts +232 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/pagination/pagination.html +8 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/pagination/pagination.ts +61 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/search-bar/search-bar.html +59 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/search-bar/search-bar.ts +108 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/sort-control/sort-control.html +50 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/sort-control/sort-control.ts +72 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/debounce.ts +31 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/field-utils.ts +54 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/filter-utils.ts +354 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/index.ts +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/sort-utils.ts +46 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.html +164 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.scss +7 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.ts +196 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/account-search/account-search-page.html +111 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/account-search/account-search-page.ts +217 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/change-password/change-password-page.html +68 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/change-password/change-password-page.ts +82 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/forgot-password/forgot-password-page.html +35 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/forgot-password/forgot-password-page.ts +87 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/home/home-page.html +18 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/home/home-page.ts +47 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.html +6 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.spec.ts +23 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.ts +13 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/login/login-page.html +47 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/login/login-page.ts +89 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.html +12 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.spec.ts +33 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.ts +15 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/profile/profile-page.html +116 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/profile/profile-page.ts +194 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/register/register-page.html +80 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/register/register-page.ts +93 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/reset-password/reset-password-page.html +60 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/reset-password/reset-password-page.ts +96 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/utils/async-data.ts +99 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/index.html +14 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/main.ts +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/styles.scss +170 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/theme.scss +39 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/types/sf-globals.d.ts +9 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/tsconfig.app.json +11 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/tsconfig.json +33 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/tsconfig.spec.json +10 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/ui-bundle.json +7 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleAuthUtils.cls +68 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleAuthUtils.cls-meta.xml +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleChangePassword.cls +77 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleChangePassword.cls-meta.xml +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleForgotPassword.cls +71 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleForgotPassword.cls-meta.xml +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleLogin.cls +105 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleLogin.cls-meta.xml +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleRegistration.cls +162 -0
- package/lib/templates/project/angularextapp/_p_/_m_/classes/UIBundleRegistration.cls-meta.xml +5 -0
- package/lib/templates/project/angularextapp/_p_/_m_/networks/angularextapp.network-meta.xml +60 -0
- package/lib/templates/project/angularextapp/_p_/_m_/package.xml +24 -0
- package/lib/templates/project/angularextapp/_p_/_m_/permissionsets/angularextapp_Guest_User_Api_Access.permissionset-meta.xml +9 -0
- package/lib/templates/project/angularextapp/_p_/_m_/sites/angularextapp.site-meta.xml +31 -0
- package/lib/templates/project/angularextapp/config/project-scratch-def.json +13 -0
- package/lib/templates/project/angularextapp/eslint.config.js +7 -0
- package/lib/templates/project/angularextapp/jest.config.js +6 -0
- package/lib/templates/project/angularextapp/package.json +46 -0
- package/lib/templates/project/angularextapp/scripts/apex/hello.apex +10 -0
- package/lib/templates/project/angularextapp/scripts/gitignore-templates.json +4 -0
- package/lib/templates/project/angularextapp/scripts/graphql-search.sh +191 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-config-schema.mjs +103 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-dev.mjs +87 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-utils.mjs +369 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-xml.mjs +182 -0
- package/lib/templates/project/angularextapp/scripts/org-setup.config.json +9 -0
- package/lib/templates/project/angularextapp/scripts/org-setup.mjs +1702 -0
- package/lib/templates/project/angularextapp/scripts/sf-project-setup.mjs +103 -0
- package/lib/templates/project/angularextapp/scripts/soql/account.soql +6 -0
- package/lib/templates/project/angularextapp/scripts/validate-org-setup-config.mjs +38 -0
- package/lib/templates/project/angularextapp/sfdx-project.json +12 -0
- package/lib/templates/project/angularintapp/.forceignore +15 -0
- package/lib/templates/project/angularintapp/.husky/pre-commit +4 -0
- package/lib/templates/project/angularintapp/.prettierignore +11 -0
- package/lib/templates/project/angularintapp/.prettierrc +17 -0
- package/lib/templates/project/angularintapp/CHANGELOG.md +4086 -0
- package/lib/templates/project/angularintapp/README.md +77 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/.forceignore +15 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/.postcssrc.json +5 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/.prettierignore +8 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/.prettierrc +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/CHANGELOG.md +4 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/README.md +85 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/angular.json +101 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/angularintapp.uibundle-meta.xml +8 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/e2e/app.spec.ts +15 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/esbuild/api-version.mjs +17 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/eslint.config.js +60 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/middleware/html.mjs +3 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/middleware/proxy.mjs +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package-lock.json +13619 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package.json +57 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/playwright.config.ts +25 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/public/favicon.ico +0 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/scripts/rewrite-e2e-assets.mjs +30 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/account/account-search.service.ts +196 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/account/distinctAccountIndustries.ts +26 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/account/distinctAccountTypes.ts +26 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/account/getAccountDetail.ts +128 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/account/searchAccounts.ts +58 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/data-client.service.spec.ts +184 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/api/data-client.service.ts +74 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/app.config.ts +22 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/app.html +1 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/app.routes.ts +31 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/app.spec.ts +18 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/app.ts +15 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.html +52 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.spec.ts +90 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/layout/app-layout/app-layout.ts +67 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/_field-size.scss +42 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/alert/alert.html +31 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/alert/alert.ts +53 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.html +18 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.scss +112 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/button/button.ts +57 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/card/card.scss +34 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/card/card.ts +110 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/collapsible/collapsible.html +10 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/collapsible/collapsible.ts +26 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.html +25 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.scss +36 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-picker/date-picker.ts +41 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.html +34 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.scss +33 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/date-range-picker/date-range-picker.ts +66 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/dialog/dialog.html +37 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/dialog/dialog.ts +55 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/field/field.html +21 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/field/field.ts +36 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/field-size.ts +8 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.html +19 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.scss +35 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/input/input.ts +36 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/label/label.html +3 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/label/label.ts +17 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/paginator/paginator.html +10 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/paginator/paginator.ts +37 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/popover/popover.html +41 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/popover/popover.ts +40 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.html +24 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.scss +35 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/select/select.ts +72 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.html +1 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.scss +23 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/separator/separator.ts +56 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.html +1 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.scss +28 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/skeleton/skeleton.ts +24 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/spinner/spinner.ts +35 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/agentforce/agentforce-embed.service.ts +177 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/agentforce/conversation.html +3 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/agentforce/conversation.ts +119 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/breadcrumb/breadcrumb.html +54 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/breadcrumb/breadcrumb.ts +40 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/active-filters.html +23 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/active-filters.ts +78 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-filter.html +18 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-filter.ts +137 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-range-filter.html +11 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/date-range-filter.ts +69 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/filter-field-wrapper.html +11 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/filter-field-wrapper.ts +36 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/multi-select-filter.html +10 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/multi-select-filter.ts +58 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/numeric-range-filter.html +22 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/numeric-range-filter.ts +146 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/search-filter.html +8 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/search-filter.ts +82 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/select-filter.html +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/select-filter.ts +65 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/text-filter.html +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/filters/text-filter.ts +90 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/object-search-state.service.ts +232 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/pagination/pagination.html +8 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/pagination/pagination.ts +61 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/search-bar/search-bar.html +59 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/search-bar/search-bar.ts +108 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/sort-control/sort-control.html +50 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/sort-control/sort-control.ts +72 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/debounce.ts +31 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/field-utils.ts +54 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/filter-utils.ts +354 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/index.ts +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/object-search/utils/sort-utils.ts +46 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.html +164 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.scss +7 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/account-detail/account-detail-page.ts +196 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/account-search/account-search-page.html +111 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/account-search/account-search-page.ts +217 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/home/home-page.html +18 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/home/home-page.ts +47 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.html +6 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.spec.ts +23 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/home/home.ts +13 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.html +12 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.spec.ts +33 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/pages/not-found/not-found.ts +15 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/types/conversation.ts +55 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/types/globals.d.ts +13 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/utils/async-data.ts +99 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/index.html +14 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/index.ts +15 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/main.ts +5 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/styles.scss +170 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/theme.scss +39 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/types/sf-globals.d.ts +9 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/tsconfig.app.json +11 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/tsconfig.json +33 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/tsconfig.spec.json +10 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/ui-bundle.json +7 -0
- package/lib/templates/project/angularintapp/_p_/_m_/applications/angularintapp.app-meta.xml +17 -0
- package/lib/templates/project/angularintapp/_p_/_m_/permissionsets/angularintapp_Access.permissionset-meta.xml +13 -0
- package/lib/templates/project/angularintapp/config/project-scratch-def.json +13 -0
- package/lib/templates/project/angularintapp/eslint.config.js +7 -0
- package/lib/templates/project/angularintapp/jest.config.js +6 -0
- package/lib/templates/project/angularintapp/package.json +46 -0
- package/lib/templates/project/angularintapp/scripts/apex/hello.apex +10 -0
- package/lib/templates/project/angularintapp/scripts/gitignore-templates.json +4 -0
- package/lib/templates/project/angularintapp/scripts/graphql-search.sh +191 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-config-schema.mjs +103 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-dev.mjs +87 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-utils.mjs +369 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-xml.mjs +182 -0
- package/lib/templates/project/angularintapp/scripts/org-setup.config.json +9 -0
- package/lib/templates/project/angularintapp/scripts/org-setup.mjs +1702 -0
- package/lib/templates/project/angularintapp/scripts/sf-project-setup.mjs +103 -0
- package/lib/templates/project/angularintapp/scripts/soql/account.soql +6 -0
- package/lib/templates/project/angularintapp/scripts/validate-org-setup-config.mjs +38 -0
- package/lib/templates/project/angularintapp/sfdx-project.json +12 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package-lock.json +864 -807
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +857 -800
- package/lib/templates/uiBundles/angularbasic/angular.json +11 -7
- package/lib/templates/uiBundles/angularbasic/eslint.config.js +4 -0
- package/lib/templates/uiBundles/angularbasic/package-lock.json +351 -319
- package/lib/templates/uiBundles/angularbasic/package.json +4 -0
- package/lib/templates/uiBundles/angularbasic/src/app/api/data-client.service.spec.ts +184 -0
- package/lib/templates/uiBundles/angularbasic/src/app/api/data-client.service.ts +74 -0
- package/lib/templates/uiBundles/angularbasic/src/app/app.config.ts +15 -1
- package/lib/templates/uiBundles/angularbasic/src/app/app.routes.ts +6 -1
- package/lib/templates/uiBundles/angularbasic/src/app/app.ts +7 -2
- package/lib/templates/uiBundles/angularbasic/src/app/{layout → components/layout/app-layout}/app-layout.component.html +2 -1
- package/lib/templates/uiBundles/angularbasic/src/app/{layout → components/layout/app-layout}/app-layout.component.ts +9 -3
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/_field-size.scss +42 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/alert/alert.component.html +31 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/alert/alert.component.ts +53 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/button/button.component.html +18 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/button/button.component.scss +112 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/button/button.component.ts +57 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/card/card.component.scss +34 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/card/card.component.ts +110 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/collapsible/collapsible.component.html +10 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/collapsible/collapsible.component.ts +26 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-picker/date-picker.component.html +25 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-picker/date-picker.component.scss +36 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-picker/date-picker.component.ts +41 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-range-picker/date-range-picker.component.html +34 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-range-picker/date-range-picker.component.scss +33 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/date-range-picker/date-range-picker.component.ts +66 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/dialog/dialog.component.html +37 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/dialog/dialog.component.ts +55 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/field/field.component.html +21 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/field/field.component.ts +36 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/field-size.ts +8 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/input/input.component.html +19 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/input/input.component.scss +35 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/input/input.component.ts +36 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/label/label.component.html +3 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/label/label.component.ts +17 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/paginator/paginator.component.html +10 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/paginator/paginator.component.ts +37 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/popover/popover.component.html +41 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/popover/popover.component.ts +40 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/select/select.component.html +24 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/select/select.component.scss +35 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/select/select.component.ts +72 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/separator/separator.component.html +1 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/separator/separator.component.scss +23 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/separator/separator.component.ts +56 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/skeleton/skeleton.component.html +1 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/skeleton/skeleton.component.scss +28 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/skeleton/skeleton.component.ts +24 -0
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/spinner/spinner.component.ts +35 -0
- package/lib/templates/uiBundles/angularbasic/src/app/pages/home/home.component.ts +7 -1
- package/lib/templates/uiBundles/angularbasic/src/app/pages/not-found/not-found.component.ts +7 -1
- package/lib/templates/uiBundles/angularbasic/src/app/utils/async-data.ts +99 -0
- package/lib/templates/uiBundles/angularbasic/src/index.html +1 -0
- package/lib/templates/uiBundles/angularbasic/src/styles.scss +170 -0
- package/lib/templates/uiBundles/angularbasic/src/theme.scss +39 -0
- package/lib/templates/uiBundles/reactbasic/package-lock.json +857 -800
- package/lib/utils/types.d.ts +1 -1
- package/lib/utils/uiBundleTemplateUtils.js +10 -0
- package/lib/utils/uiBundleTemplateUtils.js.map +1 -1
- package/package.json +5 -3
- package/lib/templates/uiBundles/angularbasic/src/app/api/graphql-client.service.ts +0 -48
- package/lib/templates/uiBundles/angularbasic/src/app/app.css +0 -0
- package/lib/templates/uiBundles/angularbasic/src/styles.css +0 -12
- /package/lib/templates/uiBundles/angularbasic/src/app/{layout → components/layout/app-layout}/app-layout.component.spec.ts +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { Directive } from "@angular/core";
|
|
7
|
+
import { FormGroup } from "@angular/forms";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Shared helpers for the auth form pages.
|
|
11
|
+
*
|
|
12
|
+
* The base `app-input` primitive exposes a two-way `[(value)]` model rather than
|
|
13
|
+
* a ControlValueAccessor, so neither `formControlName` nor `[formGroup]` can bind
|
|
14
|
+
* to it directly. These pages therefore keep a Reactive Forms `FormGroup` as the
|
|
15
|
+
* validation + submit source of truth (with no `[formGroup]` on the template
|
|
16
|
+
* `<form>`) and bridge each field manually with `[value]` / `(valueChange)`:
|
|
17
|
+
* <app-input [value]="form.controls.x.value" (valueChange)="setControl('x', $event)" />
|
|
18
|
+
*
|
|
19
|
+
* `setControl` pushes edits back into the control (marking it touched/dirty so
|
|
20
|
+
* validation surfaces), and `controlError` reads a specific error message for
|
|
21
|
+
* display once the control has been touched — mirroring the React forms, which
|
|
22
|
+
* showed field errors after interaction.
|
|
23
|
+
*
|
|
24
|
+
* Kept as an abstract base (not injectable) so each page owns its own typed
|
|
25
|
+
* `form`. Not an Angular component/service; no DI.
|
|
26
|
+
*/
|
|
27
|
+
@Directive()
|
|
28
|
+
export abstract class ReactiveFormPageBase {
|
|
29
|
+
protected abstract readonly form: FormGroup;
|
|
30
|
+
|
|
31
|
+
/** Push an edited value into the named control and mark it touched/dirty. */
|
|
32
|
+
protected setControl(name: string, value: string): void {
|
|
33
|
+
const control = this.form.get(name);
|
|
34
|
+
if (!control) return;
|
|
35
|
+
control.setValue(value);
|
|
36
|
+
control.markAsDirty();
|
|
37
|
+
control.markAsTouched();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the message for the named error key on the control, but only once
|
|
42
|
+
* the control has been touched (so pristine fields don't show errors).
|
|
43
|
+
*/
|
|
44
|
+
protected controlError(name: string, errorKey: string): string | null {
|
|
45
|
+
const control = this.form.get(name);
|
|
46
|
+
if (!control || !control.touched) return null;
|
|
47
|
+
const message = control.errors?.[errorKey];
|
|
48
|
+
return typeof message === "string" ? message : null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
@if (showWarningModal()) {
|
|
2
|
+
<app-dialog [open]="true" [closeOnBackdrop]="false">
|
|
3
|
+
<div
|
|
4
|
+
class="max-w-md"
|
|
5
|
+
role="alertdialog"
|
|
6
|
+
aria-labelledby="session-warning-title"
|
|
7
|
+
aria-describedby="session-warning-description"
|
|
8
|
+
>
|
|
9
|
+
<h2 id="session-warning-title" class="text-lg font-semibold">
|
|
10
|
+
{{ labels.sessionWarningTitle }}
|
|
11
|
+
</h2>
|
|
12
|
+
<p id="session-warning-description" class="text-sm text-muted-foreground mt-1">
|
|
13
|
+
{{ labels.sessionWarningMessage }}
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<div class="flex flex-col items-center gap-4 py-6">
|
|
17
|
+
<time
|
|
18
|
+
[attr.datetime]="isoTime()"
|
|
19
|
+
role="timer"
|
|
20
|
+
aria-live="off"
|
|
21
|
+
aria-atomic="true"
|
|
22
|
+
aria-describedby="session-warning-description"
|
|
23
|
+
class="text-5xl font-bold text-center tabular-nums text-destructive"
|
|
24
|
+
>
|
|
25
|
+
{{ formattedTime() }}
|
|
26
|
+
</time>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="flex gap-4 justify-end">
|
|
30
|
+
<app-button variant="outlined" (clicked)="onLogoutClick()">
|
|
31
|
+
{{ labels.logoutButton }}
|
|
32
|
+
</app-button>
|
|
33
|
+
<app-button variant="filled" (clicked)="onContinue()">
|
|
34
|
+
{{ labels.continueButton }}
|
|
35
|
+
</app-button>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</app-dialog>
|
|
39
|
+
} @if (showExpiredAlert()) {
|
|
40
|
+
<div class="fixed top-4 left-1/2 -translate-x-1/2 z-50 w-full max-w-md px-4">
|
|
41
|
+
<app-status-alert
|
|
42
|
+
variant="error"
|
|
43
|
+
[title]="labels.sessionWarningTitle"
|
|
44
|
+
[message]="labels.invalidSessionMessage"
|
|
45
|
+
/>
|
|
46
|
+
<button
|
|
47
|
+
type="button"
|
|
48
|
+
class="sr-only"
|
|
49
|
+
[attr.aria-label]="labels.closeLabel"
|
|
50
|
+
(click)="onDismissAlert()"
|
|
51
|
+
>
|
|
52
|
+
{{ labels.closeLabel }}
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
ChangeDetectionStrategy,
|
|
8
|
+
Component,
|
|
9
|
+
DestroyRef,
|
|
10
|
+
effect,
|
|
11
|
+
inject,
|
|
12
|
+
OnInit,
|
|
13
|
+
signal,
|
|
14
|
+
} from "@angular/core";
|
|
15
|
+
import { Router } from "@angular/router";
|
|
16
|
+
import { DialogComponent } from "../../../components/ui/dialog/dialog";
|
|
17
|
+
import { StatusAlertComponent } from "../status-alert/status-alert";
|
|
18
|
+
import { ButtonComponent } from "../../../components/ui/button/button";
|
|
19
|
+
import { AuthService } from "../auth/auth.service";
|
|
20
|
+
import { SessionTimeoutService } from "../utils/session-timeout.service";
|
|
21
|
+
import { LABELS, STORAGE_KEYS } from "../utils/session-timeout.config";
|
|
22
|
+
import { ROUTES } from "../config/authentication.config";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Session-timeout validator — the Angular port of the React
|
|
26
|
+
* `SessionTimeoutValidator`. Rendered app-wide by `AuthAppLayoutComponent` so
|
|
27
|
+
* the warning modal is available on every route (exactly like React).
|
|
28
|
+
*
|
|
29
|
+
* Responsibilities (all mirrored from React):
|
|
30
|
+
* - Starts polling via `SessionTimeoutService` on init, skipping guest users.
|
|
31
|
+
* - Shows a non-dismissable warning modal with a live countdown when the session
|
|
32
|
+
* nears expiry; "Continue" extends the session, "Log Out" logs out.
|
|
33
|
+
* - When the countdown reaches 0 it re-checks the server before logging out
|
|
34
|
+
* (prevents premature logout).
|
|
35
|
+
* - On expiry it sets the `showSessionMessage` sessionStorage flag then calls
|
|
36
|
+
* `AuthService.logout(window.location.pathname)` (hard nav).
|
|
37
|
+
* - On the login page, if the flag is set, shows the session-expired alert once
|
|
38
|
+
* (lazily read at init, since the expiry logout hard-navigates and this
|
|
39
|
+
* component always remounts fresh on login).
|
|
40
|
+
*
|
|
41
|
+
* `SessionTimeoutService` is provided here so its timers are scoped to this
|
|
42
|
+
* component's lifetime (mirrors the hook's unmount cleanup).
|
|
43
|
+
*/
|
|
44
|
+
@Component({
|
|
45
|
+
selector: "app-session-timeout-validator",
|
|
46
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
47
|
+
providers: [SessionTimeoutService],
|
|
48
|
+
imports: [DialogComponent, StatusAlertComponent, ButtonComponent],
|
|
49
|
+
templateUrl: "./session.html",
|
|
50
|
+
})
|
|
51
|
+
export class SessionTimeoutValidatorComponent implements OnInit {
|
|
52
|
+
private readonly authService = inject(AuthService);
|
|
53
|
+
private readonly session = inject(SessionTimeoutService);
|
|
54
|
+
private readonly destroyRef = inject(DestroyRef);
|
|
55
|
+
private readonly router = inject(Router);
|
|
56
|
+
|
|
57
|
+
protected readonly labels = LABELS;
|
|
58
|
+
|
|
59
|
+
// Community base path. React hard-codes "" here (root-relative); kept identical.
|
|
60
|
+
private readonly basePath = "";
|
|
61
|
+
|
|
62
|
+
// -- Exposed session state (from the service) ----------------------------
|
|
63
|
+
protected readonly showWarningModal = this.session.showWarningModal;
|
|
64
|
+
protected readonly timeLeftInSession = this.session.timeLeftInSession;
|
|
65
|
+
|
|
66
|
+
// -- Session-expired alert (lazy, read once at init) ---------------------
|
|
67
|
+
protected readonly showExpiredAlert = signal<boolean>(false);
|
|
68
|
+
|
|
69
|
+
// -- Countdown state (mirrors useCountdownTimer) -------------------------
|
|
70
|
+
protected readonly countdownSeconds = signal<number>(0);
|
|
71
|
+
private countdownIntervalId: ReturnType<typeof setInterval> | null = null;
|
|
72
|
+
private countdownEndTime = 0;
|
|
73
|
+
private lastModalOpen = false;
|
|
74
|
+
|
|
75
|
+
constructor() {
|
|
76
|
+
// React's SessionWarningModal resets+starts the countdown when the modal
|
|
77
|
+
// opens and stops it when it closes. This effect mirrors that: it reacts to
|
|
78
|
+
// the warning-modal signal and (re)starts the countdown from the latest
|
|
79
|
+
// remaining time whenever the modal is open.
|
|
80
|
+
effect(() => {
|
|
81
|
+
const open = this.showWarningModal();
|
|
82
|
+
const remaining = this.timeLeftInSession() ?? 0;
|
|
83
|
+
if (open) {
|
|
84
|
+
this.startCountdown(remaining);
|
|
85
|
+
} else if (this.lastModalOpen) {
|
|
86
|
+
this.stopCountdown();
|
|
87
|
+
}
|
|
88
|
+
this.lastModalOpen = open;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Auto-logout when the countdown/poll reports the session is expired and the
|
|
92
|
+
// user is not a guest (mirrors the React expiry `useEffect`).
|
|
93
|
+
effect(() => {
|
|
94
|
+
const timeLeft = this.timeLeftInSession();
|
|
95
|
+
if (timeLeft !== null && timeLeft <= 0 && !this.isGuest()) {
|
|
96
|
+
this.handleLogout();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
ngOnInit(): void {
|
|
102
|
+
// Session-expired alert: checked once at init via a lazy read. The expiry
|
|
103
|
+
// handler triggers a hard navigation, so this component always mounts fresh
|
|
104
|
+
// on the login page after expiry.
|
|
105
|
+
//
|
|
106
|
+
// Compare against the router's parsed URL (base-href/community-path stripped)
|
|
107
|
+
// rather than `window.location.pathname`: the raw browser path includes any
|
|
108
|
+
// base href (e.g. `/sfsites/c/.../login`) and would never equal `/login`,
|
|
109
|
+
// silently hiding the banner. `router.url` is router-relative, matching the
|
|
110
|
+
// React `useLocation().pathname` behavior. Strip the query/fragment before
|
|
111
|
+
// comparing.
|
|
112
|
+
const routerPath = this.router.url.split(/[?#]/)[0];
|
|
113
|
+
const isLoginPage = routerPath === ROUTES.LOGIN.PATH;
|
|
114
|
+
const shouldShow =
|
|
115
|
+
isLoginPage && sessionStorage.getItem(STORAGE_KEYS.SHOW_SESSION_MESSAGE) === "true";
|
|
116
|
+
if (shouldShow) {
|
|
117
|
+
sessionStorage.removeItem(STORAGE_KEYS.SHOW_SESSION_MESSAGE);
|
|
118
|
+
this.showExpiredAlert.set(true);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Start monitoring (service skips guests internally).
|
|
122
|
+
this.session.start(this.basePath, this.isGuest());
|
|
123
|
+
|
|
124
|
+
this.destroyRef.onDestroy(() => {
|
|
125
|
+
this.session.stop();
|
|
126
|
+
this.stopCountdown();
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private isGuest(): boolean {
|
|
131
|
+
return !this.authService.isAuthenticated();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// -- Countdown ------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
private startCountdown(seconds: number): void {
|
|
137
|
+
this.stopCountdown();
|
|
138
|
+
this.countdownSeconds.set(seconds);
|
|
139
|
+
this.countdownEndTime = Date.now() + seconds * 1000;
|
|
140
|
+
this.countdownIntervalId = setInterval(() => {
|
|
141
|
+
const remainingMs = this.countdownEndTime - Date.now();
|
|
142
|
+
const newTime = Math.max(0, Math.ceil(remainingMs / 1000));
|
|
143
|
+
this.countdownSeconds.set(newTime);
|
|
144
|
+
if (newTime <= 0) {
|
|
145
|
+
this.stopCountdown();
|
|
146
|
+
// Re-check with the server before logging out (React onCountdownExpire).
|
|
147
|
+
void this.session.checkSession();
|
|
148
|
+
}
|
|
149
|
+
}, 100);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private stopCountdown(): void {
|
|
153
|
+
if (this.countdownIntervalId) {
|
|
154
|
+
clearInterval(this.countdownIntervalId);
|
|
155
|
+
this.countdownIntervalId = null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** MM:SS formatted countdown (mirrors useCountdownTimer.formattedTime). */
|
|
160
|
+
protected formattedTime(): string {
|
|
161
|
+
const total = this.countdownSeconds();
|
|
162
|
+
const minutes = Math.floor(total / 60);
|
|
163
|
+
const secs = total % 60;
|
|
164
|
+
const pad = (n: number) => n.toString().padStart(2, "0");
|
|
165
|
+
return `${pad(minutes)}:${pad(secs)}`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** ISO 8601 duration for the <time> element (mirrors isoTime). */
|
|
169
|
+
protected isoTime(): string {
|
|
170
|
+
const total = this.countdownSeconds();
|
|
171
|
+
const minutes = Math.floor(total / 60);
|
|
172
|
+
const secs = total % 60;
|
|
173
|
+
return `PT${minutes}M${secs}S`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// -- Actions --------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
/** "Continue" — stop countdown and extend the session. */
|
|
179
|
+
protected onContinue(): void {
|
|
180
|
+
this.stopCountdown();
|
|
181
|
+
void this.session.extendSession();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** "Log Out" button in the warning modal. */
|
|
185
|
+
protected onLogoutClick(): void {
|
|
186
|
+
this.stopCountdown();
|
|
187
|
+
this.handleLogout();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Dismiss the session-expired alert. */
|
|
191
|
+
protected onDismissAlert(): void {
|
|
192
|
+
this.showExpiredAlert.set(false);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Set the session-message flag, stop monitoring, then hand off to the
|
|
197
|
+
* centralized logout (hard nav). Passes the current pathname as the return
|
|
198
|
+
* URL. Mirrors the React `handleLogout`.
|
|
199
|
+
*/
|
|
200
|
+
private handleLogout(): void {
|
|
201
|
+
sessionStorage.setItem(STORAGE_KEYS.SHOW_SESSION_MESSAGE, "true");
|
|
202
|
+
this.session.stop();
|
|
203
|
+
this.authService.logout(window.location.pathname);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, computed, input } from "@angular/core";
|
|
7
|
+
import { AlertComponent } from "../../../components/ui/alert/alert";
|
|
8
|
+
|
|
9
|
+
/** Status banner variant conveying the tone of the message. */
|
|
10
|
+
export type AppStatusAlertVariant = "error" | "success" | "info" | "warning";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Status / error banner — a feature-owned composition over the base `app-alert`
|
|
14
|
+
* ui primitive (not a base-template component). Adds a four-way `variant` with a
|
|
15
|
+
* colour treatment, mirroring the React `components/alerts/status-alert`.
|
|
16
|
+
*
|
|
17
|
+
* Supply the copy via the `message` input, or content-project richer markup
|
|
18
|
+
* (lists, links) as the default slot. Consumed by the authentication
|
|
19
|
+
* login-error / success / session-expired banners.
|
|
20
|
+
*/
|
|
21
|
+
@Component({
|
|
22
|
+
selector: "app-status-alert",
|
|
23
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
+
imports: [AlertComponent],
|
|
25
|
+
templateUrl: "./status-alert.html",
|
|
26
|
+
host: {
|
|
27
|
+
"data-slot": "status-alert",
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
export class StatusAlertComponent {
|
|
31
|
+
readonly variant = input<AppStatusAlertVariant>("info");
|
|
32
|
+
|
|
33
|
+
/** Optional title rendered above the message / projected content. */
|
|
34
|
+
readonly title = input<string>("");
|
|
35
|
+
|
|
36
|
+
/** Message copy; may be omitted in favour of projected content. */
|
|
37
|
+
readonly message = input<string>("");
|
|
38
|
+
|
|
39
|
+
/** Colour utilities applied to the banner for the current variant. */
|
|
40
|
+
protected readonly toneClass = computed(() => {
|
|
41
|
+
switch (this.variant()) {
|
|
42
|
+
case "error":
|
|
43
|
+
return "text-destructive";
|
|
44
|
+
case "success":
|
|
45
|
+
return "text-emerald-700";
|
|
46
|
+
case "warning":
|
|
47
|
+
return "text-amber-700";
|
|
48
|
+
default:
|
|
49
|
+
return "text-sky-700";
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Material lays the button's projected content out inside `.mdc-button__label`.
|
|
8
|
+
// Make it a flex row so the spinner and the loading label sit on the same line,
|
|
9
|
+
// vertically centred. Scoped under `:host` (via `::ng-deep`) so the override
|
|
10
|
+
// only reaches this submit button's inner `matButton`, never other buttons.
|
|
11
|
+
:host ::ng-deep .mdc-button__label {
|
|
12
|
+
display: flex;
|
|
13
|
+
|
|
14
|
+
> app-spinner {
|
|
15
|
+
margin: auto 1rem;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, input } from "@angular/core";
|
|
7
|
+
import { ButtonComponent } from "../../../components/ui/button/button";
|
|
8
|
+
import { SpinnerComponent } from "../../../components/ui/spinner/spinner";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Submit button that reflects form submission state — the Angular port of the
|
|
12
|
+
* React `SubmitButton`, which subscribed to `form.isSubmitting`.
|
|
13
|
+
*
|
|
14
|
+
* Reactive Forms have no equivalent subscription; instead the parent passes the
|
|
15
|
+
* form's `pending`/submitting flag via `[submitting]` and the caller-provided
|
|
16
|
+
* `[disabled]`. While submitting the button is disabled and shows a spinner with
|
|
17
|
+
* the loading label — the same UX (prevents double-submit + gives feedback).
|
|
18
|
+
*/
|
|
19
|
+
@Component({
|
|
20
|
+
selector: "app-submit-button",
|
|
21
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
22
|
+
imports: [ButtonComponent, SpinnerComponent],
|
|
23
|
+
templateUrl: "./submit-button.html",
|
|
24
|
+
styleUrl: "./submit-button.scss",
|
|
25
|
+
})
|
|
26
|
+
export class SubmitButtonComponent {
|
|
27
|
+
/** Button text when not submitting. */
|
|
28
|
+
readonly label = input.required<string>();
|
|
29
|
+
/** Button text while submitting. */
|
|
30
|
+
readonly loadingLabel = input<string>("Submitting…");
|
|
31
|
+
/** True while the form submission is in flight. */
|
|
32
|
+
readonly submitting = input<boolean>(false);
|
|
33
|
+
/** Additional disabled condition from the caller (e.g. already authenticated). */
|
|
34
|
+
readonly disabled = input<boolean>(false);
|
|
35
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { AUTH_REDIRECT_PARAM } from "../config/authentication.config";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extracts the startUrl from the current query params, defaulting to '/'.
|
|
10
|
+
*
|
|
11
|
+
* SECURITY NOTE: This function strictly validates the URL to prevent Open
|
|
12
|
+
* Redirect vulnerabilities. It allows only relative paths.
|
|
13
|
+
*
|
|
14
|
+
* Direct port of the React `getStartUrl`. The React version takes a
|
|
15
|
+
* `URLSearchParams`; Angular's `ParamMap` exposes the same `get(key)` contract,
|
|
16
|
+
* so this accepts a minimal `{ get(name): string | null }` shape and works with
|
|
17
|
+
* both an `ActivatedRoute` `ParamMap` and a `URLSearchParams`.
|
|
18
|
+
*
|
|
19
|
+
* @param params - The query-param map (e.g. ActivatedRoute.snapshot.queryParamMap).
|
|
20
|
+
* @returns The start URL for post-authentication redirect.
|
|
21
|
+
*/
|
|
22
|
+
export function getStartUrl(params: { get(name: string): string | null }): string {
|
|
23
|
+
const url = params.get(AUTH_REDIRECT_PARAM);
|
|
24
|
+
if (url && isValidRedirect(url)) {
|
|
25
|
+
return url;
|
|
26
|
+
}
|
|
27
|
+
return "/";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Security: Validates that the redirect URL is a relative path to prevent Open
|
|
32
|
+
* Redirect vulnerabilities.
|
|
33
|
+
*
|
|
34
|
+
* Security Checks:
|
|
35
|
+
* 1. Rejects protocol-relative URLs (//)
|
|
36
|
+
* 2. Rejects backslash usage which some browsers treat as slashes (/\)
|
|
37
|
+
* 3. Rejects control characters
|
|
38
|
+
*
|
|
39
|
+
* Ported from the React `isValidRedirect`, with one intentional hardening: the
|
|
40
|
+
* character-range ceiling is tightened from the React source's U+00FF to the
|
|
41
|
+
* printable-ASCII bound U+007E (~) so DEL / C1 controls / NBSP are rejected in
|
|
42
|
+
* line with check #3. Do not relax any of these checks without security review.
|
|
43
|
+
*/
|
|
44
|
+
export function isValidRedirect(url: string): boolean {
|
|
45
|
+
// Basic structure check
|
|
46
|
+
if (!url.startsWith("/") || url.startsWith("//")) return false;
|
|
47
|
+
// Security: Reject backslashes to prevent /\example.com bypasses
|
|
48
|
+
if (url.includes("\\")) return false;
|
|
49
|
+
// Robustness: Ensure it doesn't contain whitespace/control characters.
|
|
50
|
+
// Allowed range is the printable-ASCII band U+0021 (!) through U+007E (~).
|
|
51
|
+
// This deliberately tightens the React reference's U+00FF ceiling, which
|
|
52
|
+
// admitted U+007F (DEL), the C1 control block (U+0080-U+009F, incl. NEL),
|
|
53
|
+
// and U+00A0 (NBSP) - all of which contradict the "reject control
|
|
54
|
+
// characters" contract and are open-redirect / request-splitting vectors.
|
|
55
|
+
if (/[^!-~]/.test(url)) return false;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Shared response type for authentication endpoints (login/register). Success
|
|
61
|
+
* responses contain `success: true` and `redirectUrl`. Error responses contain
|
|
62
|
+
* an `errors` array.
|
|
63
|
+
*/
|
|
64
|
+
export interface AuthResponse {
|
|
65
|
+
success?: boolean;
|
|
66
|
+
redirectUrl?: string | null;
|
|
67
|
+
errors?: string[];
|
|
68
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Angular Reactive Forms validators that mirror the React feature's zod schemas
|
|
10
|
+
* (`authHelpers.ts`). The React port dropped zod in favour of native Angular
|
|
11
|
+
* validators; these reproduce the same rules and messages so the UX is
|
|
12
|
+
* identical. Each validator returns `{ <key>: message }` on failure and `null`
|
|
13
|
+
* on success; templates read the first message via `control.errors`.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Mirrors zod `emailSchema`: trimmed, valid email. */
|
|
17
|
+
export const emailValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
|
|
18
|
+
const value = (control.value ?? "").toString().trim();
|
|
19
|
+
if (value === "") {
|
|
20
|
+
return { email: "Please enter a valid email address" };
|
|
21
|
+
}
|
|
22
|
+
// Same intent as zod's email check: a single @ with non-empty local/domain
|
|
23
|
+
// parts and a dotted domain. Kept deliberately permissive, like zod.
|
|
24
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
25
|
+
return emailPattern.test(value) ? null : { email: "Please enter a valid email address" };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Mirrors zod `passwordSchema`: minimum 8 characters. */
|
|
29
|
+
export const passwordMinValidator: ValidatorFn = (
|
|
30
|
+
control: AbstractControl,
|
|
31
|
+
): ValidationErrors | null => {
|
|
32
|
+
const value = (control.value ?? "").toString();
|
|
33
|
+
return value.length >= 8 ? null : { password: "Password must be at least 8 characters" };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** A required-with-custom-message validator (mirrors zod `min(1, message)`). */
|
|
37
|
+
export function requiredWithMessage(message: string): ValidatorFn {
|
|
38
|
+
return (control: AbstractControl): ValidationErrors | null => {
|
|
39
|
+
const value = (control.value ?? "").toString().trim();
|
|
40
|
+
return value.length >= 1 ? null : { required: message };
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Cross-field validator mirroring the `newPasswordSchema` refine: the
|
|
46
|
+
* `confirmPassword` control must equal the `newPassword` control. Attach to the
|
|
47
|
+
* FormGroup; sets `{ passwordMismatch: '...' }` on the confirm control (matching
|
|
48
|
+
* the zod `path: ['confirmPassword']`) so the error renders under that field.
|
|
49
|
+
*/
|
|
50
|
+
export function passwordsMatchValidator(
|
|
51
|
+
passwordKey = "newPassword",
|
|
52
|
+
confirmKey = "confirmPassword",
|
|
53
|
+
): ValidatorFn {
|
|
54
|
+
return (group: AbstractControl): ValidationErrors | null => {
|
|
55
|
+
const password = group.get(passwordKey);
|
|
56
|
+
const confirm = group.get(confirmKey);
|
|
57
|
+
if (!password || !confirm) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if (confirm.value !== password.value) {
|
|
61
|
+
const existing = confirm.errors ?? {};
|
|
62
|
+
confirm.setErrors({ ...existing, passwordMismatch: "Passwords do not match" });
|
|
63
|
+
return { passwordMismatch: "Passwords do not match" };
|
|
64
|
+
}
|
|
65
|
+
// Clear only our own error, preserving any other errors on the control.
|
|
66
|
+
if (confirm.errors) {
|
|
67
|
+
const { passwordMismatch: _removed, ...rest } = confirm.errors;
|
|
68
|
+
confirm.setErrors(Object.keys(rest).length ? rest : null);
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when the API returns a non-OK response with structured error
|
|
9
|
+
* messages. The `errors` array contains user-facing messages that are safe to
|
|
10
|
+
* display — backend Apex classes guarantee that system exceptions are never
|
|
11
|
+
* exposed. Direct port of the React `ApiError`.
|
|
12
|
+
*/
|
|
13
|
+
export class ApiError extends Error {
|
|
14
|
+
readonly errors: string[];
|
|
15
|
+
constructor(errors: string[]) {
|
|
16
|
+
super(errors[0]);
|
|
17
|
+
this.name = "ApiError";
|
|
18
|
+
this.errors = errors;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helper to parse the fetch Response. Handles the distinction between success
|
|
24
|
+
* (JSON) and failure (throwing Error). Ported from the React `handleApiResponse`.
|
|
25
|
+
*/
|
|
26
|
+
export async function handleApiResponse<T = unknown>(response: Response): Promise<T> {
|
|
27
|
+
// Robustness: Handle 204 No Content gracefully
|
|
28
|
+
if (response.status === 204) {
|
|
29
|
+
return {} as T;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let data: { errors?: string[] } | null = null;
|
|
33
|
+
|
|
34
|
+
const contentType = response.headers.get("content-type");
|
|
35
|
+
if (contentType?.includes("application/json")) {
|
|
36
|
+
data = (await response.json()) as { errors?: string[] };
|
|
37
|
+
} else {
|
|
38
|
+
// If Salesforce returns HTML (e.g. standard error page), consume the text
|
|
39
|
+
// to avoid parsing errors.
|
|
40
|
+
await response.text();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
console.error("API request failed", data);
|
|
45
|
+
if (data?.errors?.length) {
|
|
46
|
+
throw new ApiError(data.errors);
|
|
47
|
+
}
|
|
48
|
+
throw new Error("An unexpected error occurred");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return data as T;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** UI API Record response structure. */
|
|
55
|
+
export type RecordResponse = {
|
|
56
|
+
fields: Record<string, { value: string }>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* GraphQL can return a complex nested structure. This helper flattens it to a
|
|
61
|
+
* simple object for easier form binding. Ported from the React
|
|
62
|
+
* `flattenGraphQLRecord`.
|
|
63
|
+
*
|
|
64
|
+
* @param data - Extracted payload from the GraphQL response.
|
|
65
|
+
* @param fallbackError - Fallback error message if data is null/undefined or not an object.
|
|
66
|
+
* @throws {Error} If data is not valid.
|
|
67
|
+
* @returns Flattened object with values mapped directly to the fields.
|
|
68
|
+
*/
|
|
69
|
+
export function flattenGraphQLRecord<T>(
|
|
70
|
+
data: unknown,
|
|
71
|
+
fallbackError = "An unknown error occurred",
|
|
72
|
+
): T {
|
|
73
|
+
if (!data || typeof data !== "object") {
|
|
74
|
+
throw new Error(fallbackError);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return Object.fromEntries(
|
|
78
|
+
Object.entries(data as Record<string, unknown>).map(([key, field]) => [
|
|
79
|
+
key,
|
|
80
|
+
field !== null && typeof field === "object" && "value" in field
|
|
81
|
+
? (field as { value: unknown }).value
|
|
82
|
+
: (field ?? null),
|
|
83
|
+
]),
|
|
84
|
+
) as T;
|
|
85
|
+
}
|