@salesforce/templates 66.11.1 → 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/project/angularextapp/_p_/_m_/_w_/_a_/src/app/api/data-client.service.spec.ts +184 -0
- 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 +589 -561
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +589 -561
- package/lib/templates/uiBundles/angularbasic/package-lock.json +147 -168
- package/lib/templates/uiBundles/reactbasic/package-lock.json +589 -561
- 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 +4 -2
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
* Centralized configuration for Auth routes. Each route contains both the path
|
|
9
|
+
* and page title. Using constants prevents typos in route paths across the app.
|
|
10
|
+
*
|
|
11
|
+
* Direct port of the React `authenticationConfig.ts`. NOTE: Angular route
|
|
12
|
+
* `path` values are relative (no leading slash) in `app.routes.ts`; these
|
|
13
|
+
* PATH constants keep the leading slash so `routerLink` / `navigate` calls and
|
|
14
|
+
* the open-redirect validation behave exactly as the React version.
|
|
15
|
+
*/
|
|
16
|
+
export const ROUTES = {
|
|
17
|
+
LOGIN: {
|
|
18
|
+
PATH: "/login",
|
|
19
|
+
TITLE: "Login | MyApp",
|
|
20
|
+
},
|
|
21
|
+
REGISTER: {
|
|
22
|
+
PATH: "/register",
|
|
23
|
+
TITLE: "Create Account | MyApp",
|
|
24
|
+
},
|
|
25
|
+
FORGOT_PASSWORD: {
|
|
26
|
+
PATH: "/forgot-password",
|
|
27
|
+
TITLE: "Recover Password | MyApp",
|
|
28
|
+
},
|
|
29
|
+
RESET_PASSWORD: {
|
|
30
|
+
PATH: "/reset-password",
|
|
31
|
+
TITLE: "Reset Password | MyApp",
|
|
32
|
+
},
|
|
33
|
+
PROFILE: {
|
|
34
|
+
PATH: "/profile",
|
|
35
|
+
TITLE: "My Profile | MyApp",
|
|
36
|
+
},
|
|
37
|
+
CHANGE_PASSWORD: {
|
|
38
|
+
PATH: "/change-password",
|
|
39
|
+
TITLE: "Change Password | MyApp",
|
|
40
|
+
},
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Centralized configuration for API endpoints. These are server-side endpoints,
|
|
45
|
+
* not client-side routes.
|
|
46
|
+
*/
|
|
47
|
+
export const API_ROUTES = {
|
|
48
|
+
// W-21253864: Logout URL integration is not currently supported
|
|
49
|
+
LOGOUT: "/secur/logout.jsp",
|
|
50
|
+
// Custom Apex REST resources handling the auth flows.
|
|
51
|
+
LOGIN: "/services/apexrest/auth/login",
|
|
52
|
+
REGISTER: "/services/apexrest/auth/register",
|
|
53
|
+
FORGOT_PASSWORD: "/services/apexrest/auth/forgot-password",
|
|
54
|
+
RESET_PASSWORD: "/services/apexrest/auth/reset-password",
|
|
55
|
+
CHANGE_PASSWORD: "/services/apexrest/auth/change-password",
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Query parameter key used to store the return URL.
|
|
60
|
+
* e.g. /login?startUrl=/profile
|
|
61
|
+
*/
|
|
62
|
+
export const AUTH_REDIRECT_PARAM = "startUrl";
|
|
63
|
+
|
|
64
|
+
/** Placeholder text constants for authentication form inputs. */
|
|
65
|
+
export const AUTH_PLACEHOLDERS = {
|
|
66
|
+
EMAIL: "e.g. name@example.com",
|
|
67
|
+
PASSWORD: "Enter your password",
|
|
68
|
+
PASSWORD_CREATE: "Create a password",
|
|
69
|
+
PASSWORD_CONFIRM: "Re-enter your password",
|
|
70
|
+
PASSWORD_NEW: "Enter new password",
|
|
71
|
+
PASSWORD_NEW_CONFIRM: "Re-enter new password",
|
|
72
|
+
FIRST_NAME: "e.g. Alex",
|
|
73
|
+
LAST_NAME: "e.g. Smith",
|
|
74
|
+
USERNAME: "e.g. asmith",
|
|
75
|
+
} as const;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<p class="w-full text-center text-sm text-muted-foreground">
|
|
2
|
+
@if (text()) { {{ text() }} }
|
|
3
|
+
<a
|
|
4
|
+
[routerLink]="to()"
|
|
5
|
+
class="font-medium underline hover:text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
6
|
+
>
|
|
7
|
+
{{ linkText() }}
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
@@ -0,0 +1,26 @@
|
|
|
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 { RouterLink } from "@angular/router";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Footer navigation link under an auth form — the Angular port of the React
|
|
11
|
+
* `FooterLink`. Renders an optional prefix text followed by a `routerLink`.
|
|
12
|
+
*/
|
|
13
|
+
@Component({
|
|
14
|
+
selector: "app-footer-link",
|
|
15
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16
|
+
imports: [RouterLink],
|
|
17
|
+
templateUrl: "./footer-link.html",
|
|
18
|
+
})
|
|
19
|
+
export class FooterLinkComponent {
|
|
20
|
+
/** Link text prefix (e.g., "Don't have an account?"). */
|
|
21
|
+
readonly text = input<string>("");
|
|
22
|
+
/** Router path to navigate to. */
|
|
23
|
+
readonly to = input.required<string>();
|
|
24
|
+
/** Link label (e.g., "Sign up"). */
|
|
25
|
+
readonly linkText = input.required<string>();
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@if (loading()) {
|
|
2
|
+
<app-skeleton class="size-8 rounded-full" />
|
|
3
|
+
} @else {
|
|
4
|
+
<button matIconButton [matMenuTriggerFor]="menu" aria-label="User menu">
|
|
5
|
+
<mat-icon>person</mat-icon>
|
|
6
|
+
</button>
|
|
7
|
+
|
|
8
|
+
<mat-menu #menu="matMenu" xPosition="before">
|
|
9
|
+
@if (isAuthenticated()) {
|
|
10
|
+
<div class="px-3 py-2 font-medium truncate">{{ user()?.name }}</div>
|
|
11
|
+
<hr />
|
|
12
|
+
<a mat-menu-item [routerLink]="routes.PROFILE.PATH">Edit Profile</a>
|
|
13
|
+
<ng-content select="[menuItems]" />
|
|
14
|
+
<button mat-menu-item type="button" (click)="onLogout()">Sign Out</button>
|
|
15
|
+
} @else {
|
|
16
|
+
<a mat-menu-item [routerLink]="routes.LOGIN.PATH">
|
|
17
|
+
<mat-icon>login</mat-icon>
|
|
18
|
+
<span>Log In</span>
|
|
19
|
+
</a>
|
|
20
|
+
<a mat-menu-item [routerLink]="routes.REGISTER.PATH">
|
|
21
|
+
<mat-icon>person_add</mat-icon>
|
|
22
|
+
<span>Register</span>
|
|
23
|
+
</a>
|
|
24
|
+
}
|
|
25
|
+
</mat-menu>
|
|
26
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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, inject } from "@angular/core";
|
|
7
|
+
import { RouterLink } from "@angular/router";
|
|
8
|
+
import { MatButtonModule } from "@angular/material/button";
|
|
9
|
+
import { MatIconModule } from "@angular/material/icon";
|
|
10
|
+
import { MatMenuModule } from "@angular/material/menu";
|
|
11
|
+
import { SkeletonComponent } from "../../../../components/ui/skeleton/skeleton";
|
|
12
|
+
import { AuthService } from "../../auth/auth.service";
|
|
13
|
+
import { ROUTES } from "../../config/authentication.config";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Auth menu — the Angular port of the React `AuthMenu`. A header dropdown that
|
|
17
|
+
* shows the authenticated user's name + Edit Profile / Sign Out, or Log In /
|
|
18
|
+
* Register for guests. While auth state is loading it shows a skeleton avatar.
|
|
19
|
+
*
|
|
20
|
+
* Owns its own trigger and `mat-menu` (the canonical Material menu shape): an
|
|
21
|
+
* icon-only person button carries `matMenuTriggerFor`, so the trigger — with its
|
|
22
|
+
* `aria-haspopup` / `aria-expanded` / keyboard handling — sits on a real focusable
|
|
23
|
+
* `<button>`. Extra items can be inserted before Sign Out via `[menuItems]`
|
|
24
|
+
* projection.
|
|
25
|
+
*
|
|
26
|
+
* Reads `AuthService` directly (the `providedIn: 'root'` replacement for
|
|
27
|
+
* `useAuth`), so no inputs are needed for auth state.
|
|
28
|
+
*/
|
|
29
|
+
@Component({
|
|
30
|
+
selector: "app-auth-menu",
|
|
31
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
32
|
+
imports: [RouterLink, MatButtonModule, MatIconModule, MatMenuModule, SkeletonComponent],
|
|
33
|
+
templateUrl: "./auth-menu.html",
|
|
34
|
+
})
|
|
35
|
+
export class AuthMenuComponent {
|
|
36
|
+
private readonly authService = inject(AuthService);
|
|
37
|
+
|
|
38
|
+
protected readonly routes = ROUTES;
|
|
39
|
+
protected readonly user = this.authService.user;
|
|
40
|
+
protected readonly isAuthenticated = this.authService.isAuthenticated;
|
|
41
|
+
protected readonly loading = this.authService.loading;
|
|
42
|
+
|
|
43
|
+
protected onLogout(): void {
|
|
44
|
+
this.authService.logout();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -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
|
+
}
|