@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,217 @@
|
|
|
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, inject, signal } from "@angular/core";
|
|
7
|
+
import { RouterLink } from "@angular/router";
|
|
8
|
+
// Base-app UI wrappers, inherited (not recreated) by this feature. Post-compose
|
|
9
|
+
// they land at uiBundles/<target>/src/app/components/ui/..., three levels up from this
|
|
10
|
+
// page folder (app/features/account-search/ -> app/components/ui/).
|
|
11
|
+
import { AlertComponent } from "../../components/ui/alert/alert";
|
|
12
|
+
import { CollapsibleComponent } from "../../components/ui/collapsible/collapsible";
|
|
13
|
+
import { SkeletonComponent } from "../../components/ui/skeleton/skeleton";
|
|
14
|
+
// Object-search feature building blocks (Waves 1-2), two levels up.
|
|
15
|
+
import { ObjectBreadcrumbComponent } from "../../features/object-search/breadcrumb/breadcrumb";
|
|
16
|
+
import { SortControlComponent } from "../../features/object-search/sort-control/sort-control";
|
|
17
|
+
import { ActiveFiltersComponent } from "../../features/object-search/filters/active-filters";
|
|
18
|
+
import { PaginationControlsComponent } from "../../features/object-search/pagination/pagination";
|
|
19
|
+
import { SearchFilterComponent } from "../../features/object-search/filters/search-filter";
|
|
20
|
+
import { TextFilterComponent } from "../../features/object-search/filters/text-filter";
|
|
21
|
+
import { SelectFilterComponent } from "../../features/object-search/filters/select-filter";
|
|
22
|
+
import { MultiSelectFilterComponent } from "../../features/object-search/filters/multi-select-filter";
|
|
23
|
+
import { NumericRangeFilterComponent } from "../../features/object-search/filters/numeric-range-filter";
|
|
24
|
+
import { DateFilterComponent } from "../../features/object-search/filters/date-filter";
|
|
25
|
+
import { DateRangeFilterComponent } from "../../features/object-search/filters/date-range-filter";
|
|
26
|
+
import {
|
|
27
|
+
ObjectSearchStateService,
|
|
28
|
+
type PaginationConfig,
|
|
29
|
+
} from "../../features/object-search/object-search-state.service";
|
|
30
|
+
import { createAsyncData } from "../../utils/async-data";
|
|
31
|
+
import { fieldValue } from "../../features/object-search/utils/field-utils";
|
|
32
|
+
import type { FilterFieldConfig } from "../../features/object-search/utils/filter-utils";
|
|
33
|
+
import type { SortFieldConfig } from "../../features/object-search/utils/sort-utils";
|
|
34
|
+
import { AccountSearchService, type AccountNode } from "../../api/account/account-search.service";
|
|
35
|
+
|
|
36
|
+
/** Cursor-pagination config for the account search (mirrors the React reference). */
|
|
37
|
+
const PAGINATION_CONFIG: PaginationConfig = {
|
|
38
|
+
defaultPageSize: 7,
|
|
39
|
+
validPageSizes: [7, 14, 28, 42],
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Filter field configs — the single source of truth for URL (de)serialization
|
|
44
|
+
* and GraphQL `where` building. The picklist option lists for Industry / Type
|
|
45
|
+
* are filled in at runtime (see the component's computed configs) from the
|
|
46
|
+
* distinct-value aggregate queries.
|
|
47
|
+
*/
|
|
48
|
+
const FILTER_CONFIGS: FilterFieldConfig[] = [
|
|
49
|
+
{
|
|
50
|
+
field: "search",
|
|
51
|
+
label: "Search",
|
|
52
|
+
type: "search",
|
|
53
|
+
searchFields: ["Name", "Phone", "Industry"],
|
|
54
|
+
placeholder: "Search by name, phone, or industry...",
|
|
55
|
+
},
|
|
56
|
+
{ field: "Name", label: "Account Name", type: "text", placeholder: "Search by name..." },
|
|
57
|
+
{ field: "Industry", label: "Industry", type: "picklist" },
|
|
58
|
+
{ field: "Type", label: "Type", type: "multipicklist" },
|
|
59
|
+
{ field: "AnnualRevenue", label: "Annual Revenue", type: "numeric" },
|
|
60
|
+
{ field: "CreatedDate", label: "Created Date", type: "datetime", disableFuture: true },
|
|
61
|
+
{
|
|
62
|
+
field: "LastModifiedDate",
|
|
63
|
+
label: "Last Modified Date",
|
|
64
|
+
type: "datetimerange",
|
|
65
|
+
disableFuture: true,
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/** Sortable fields exposed by the sort control (mirrors the React reference). */
|
|
70
|
+
const ACCOUNT_SORT_CONFIGS: SortFieldConfig[] = [
|
|
71
|
+
{ field: "Name", label: "Name" },
|
|
72
|
+
{ field: "AnnualRevenue", label: "Annual Revenue" },
|
|
73
|
+
{ field: "Industry", label: "Industry" },
|
|
74
|
+
{ field: "CreatedDate", label: "Created Date" },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Account search / list page. The Angular analogue of the React `AccountSearch`
|
|
79
|
+
* example page: a sidebar filter panel (Card + Collapsible) plus a main results
|
|
80
|
+
* area with sort control, active-filter chips, a results list, and cursor
|
|
81
|
+
* pagination.
|
|
82
|
+
*
|
|
83
|
+
* State lives in a page-scoped {@link ObjectSearchStateService} (provided here,
|
|
84
|
+
* NOT in root) so each search page owns its own filters / sort / cursor stack.
|
|
85
|
+
* The filter components projected into the sidebar inject that same instance.
|
|
86
|
+
*
|
|
87
|
+
* Data flows through {@link createAsyncData}: whenever the derived query args
|
|
88
|
+
* (where / orderBy / pageSize / afterCursor) change, the search re-runs with
|
|
89
|
+
* latest-wins semantics.
|
|
90
|
+
*/
|
|
91
|
+
@Component({
|
|
92
|
+
selector: "app-account-search-page",
|
|
93
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
94
|
+
providers: [ObjectSearchStateService],
|
|
95
|
+
imports: [
|
|
96
|
+
RouterLink,
|
|
97
|
+
AlertComponent,
|
|
98
|
+
CollapsibleComponent,
|
|
99
|
+
SkeletonComponent,
|
|
100
|
+
ObjectBreadcrumbComponent,
|
|
101
|
+
SortControlComponent,
|
|
102
|
+
ActiveFiltersComponent,
|
|
103
|
+
PaginationControlsComponent,
|
|
104
|
+
SearchFilterComponent,
|
|
105
|
+
TextFilterComponent,
|
|
106
|
+
SelectFilterComponent,
|
|
107
|
+
MultiSelectFilterComponent,
|
|
108
|
+
NumericRangeFilterComponent,
|
|
109
|
+
DateFilterComponent,
|
|
110
|
+
DateRangeFilterComponent,
|
|
111
|
+
],
|
|
112
|
+
templateUrl: "./account-search-page.html",
|
|
113
|
+
})
|
|
114
|
+
export class AccountSearchPageComponent {
|
|
115
|
+
private readonly service = inject(AccountSearchService);
|
|
116
|
+
private readonly state = inject(ObjectSearchStateService);
|
|
117
|
+
|
|
118
|
+
/** Sortable field configs surfaced to the sort control. */
|
|
119
|
+
protected readonly sortConfigs = ACCOUNT_SORT_CONFIGS;
|
|
120
|
+
/** Allowed page sizes forwarded to the pagination controls. */
|
|
121
|
+
protected readonly pageSizeOptions = PAGINATION_CONFIG.validPageSizes;
|
|
122
|
+
|
|
123
|
+
/** Collapsible open state for the sidebar filter panel. */
|
|
124
|
+
protected readonly filtersOpen = signal<boolean>(true);
|
|
125
|
+
|
|
126
|
+
/** Derived, API-ready `where` / `orderBy` signals from the shared state. */
|
|
127
|
+
private readonly query = this.state.init<unknown, unknown>(FILTER_CONFIGS, PAGINATION_CONFIG);
|
|
128
|
+
|
|
129
|
+
/** Live page-size / cursor signals from the shared state. */
|
|
130
|
+
protected readonly pageSize = this.state.pageSize;
|
|
131
|
+
protected readonly hasPreviousPage = this.state.hasPreviousPage;
|
|
132
|
+
|
|
133
|
+
// -- Distinct-value option loads (Industry / Type filters) -----------------
|
|
134
|
+
private readonly industries = createAsyncData(signal(0), () =>
|
|
135
|
+
this.service.fetchDistinctIndustries(),
|
|
136
|
+
);
|
|
137
|
+
private readonly types = createAsyncData(signal(0), () => this.service.fetchDistinctTypes());
|
|
138
|
+
|
|
139
|
+
// -- Per-filter configs (options merged in for the picklist filters) -------
|
|
140
|
+
protected readonly searchConfig = FILTER_CONFIGS[0];
|
|
141
|
+
protected readonly nameConfig = FILTER_CONFIGS[1];
|
|
142
|
+
protected readonly revenueConfig = FILTER_CONFIGS[4];
|
|
143
|
+
protected readonly createdConfig = FILTER_CONFIGS[5];
|
|
144
|
+
protected readonly lastModifiedConfig = FILTER_CONFIGS[6];
|
|
145
|
+
protected readonly industryConfig = computed<FilterFieldConfig>(() => ({
|
|
146
|
+
...FILTER_CONFIGS[2],
|
|
147
|
+
options: this.industries.data() ?? [],
|
|
148
|
+
}));
|
|
149
|
+
protected readonly typeConfig = computed<FilterFieldConfig>(() => ({
|
|
150
|
+
...FILTER_CONFIGS[3],
|
|
151
|
+
options: this.types.data() ?? [],
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
// -- Search results --------------------------------------------------------
|
|
155
|
+
private readonly searchArgs = computed(() => ({
|
|
156
|
+
where: this.query.where(),
|
|
157
|
+
orderBy: this.query.orderBy(),
|
|
158
|
+
first: this.state.pageSize(),
|
|
159
|
+
after: this.state.afterCursor(),
|
|
160
|
+
}));
|
|
161
|
+
private readonly result = createAsyncData(this.searchArgs, (args) =>
|
|
162
|
+
this.service.searchAccounts(args),
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
protected readonly loading = this.result.loading;
|
|
166
|
+
protected readonly error = this.result.error;
|
|
167
|
+
|
|
168
|
+
private readonly pageInfo = computed(() => this.result.data()?.pageInfo);
|
|
169
|
+
protected readonly totalCount = computed(() => this.result.data()?.totalCount);
|
|
170
|
+
protected readonly hasNextPage = computed(() => this.pageInfo()?.hasNextPage ?? false);
|
|
171
|
+
protected readonly endCursor = computed(() => this.pageInfo()?.endCursor ?? undefined);
|
|
172
|
+
|
|
173
|
+
/** Non-null account nodes from the current page's edges. */
|
|
174
|
+
protected readonly nodes = computed<AccountNode[]>(() => {
|
|
175
|
+
const edges = this.result.data()?.edges ?? [];
|
|
176
|
+
const out: AccountNode[] = [];
|
|
177
|
+
for (const edge of edges) {
|
|
178
|
+
if (edge?.node) out.push(edge.node);
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/** Pagination controls (and the results list) are inert while fetching/errored. */
|
|
184
|
+
protected readonly controlsDisabled = computed(() => this.loading() || !!this.error());
|
|
185
|
+
|
|
186
|
+
/** Placeholder rows for the loading skeleton — one per requested page size. */
|
|
187
|
+
protected readonly skeletonRows = computed(() =>
|
|
188
|
+
Array.from({ length: this.pageSize() }, (_, i) => i),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
/** Result-count copy above the list, matching the React reference wording. */
|
|
192
|
+
protected readonly resultCountLabel = computed(() => {
|
|
193
|
+
const total = this.totalCount();
|
|
194
|
+
const shown = this.nodes().length;
|
|
195
|
+
if (total != null && (this.hasNextPage() || this.hasPreviousPage())) {
|
|
196
|
+
return `${total} account${total !== 1 ? "s" : ""} found`;
|
|
197
|
+
}
|
|
198
|
+
return `Showing ${shown} account${shown !== 1 ? "s" : ""}`;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
/** Display helpers for the results list (mirrors `fieldValue` in the template). */
|
|
202
|
+
protected name(node: AccountNode): string {
|
|
203
|
+
return fieldValue(node.Name) ?? "—";
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
protected secondaryLine(node: AccountNode): string {
|
|
207
|
+
return [fieldValue(node.Industry), fieldValue(node.Type)].filter(Boolean).join(" · ") || "—";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
protected phone(node: AccountNode): string {
|
|
211
|
+
return fieldValue(node.Phone) ?? "";
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
protected ownerName(node: AccountNode): string {
|
|
215
|
+
return fieldValue(node.Owner?.Name) ?? "";
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<main class="flex min-h-svh w-full justify-center p-6 md:p-10 items-start">
|
|
2
|
+
<div class="w-full max-w-md">
|
|
3
|
+
<app-auth-form
|
|
4
|
+
title="Change Password"
|
|
5
|
+
description="Enter your current and new password below"
|
|
6
|
+
[showAlreadyLoggedIn]="false"
|
|
7
|
+
[error]="submitError()"
|
|
8
|
+
[success]="
|
|
9
|
+
success()
|
|
10
|
+
? 'Password changed successfully! Use the link below to return to your profile.'
|
|
11
|
+
: null
|
|
12
|
+
"
|
|
13
|
+
submitText="Change Password"
|
|
14
|
+
submitLoadingText="Changing…"
|
|
15
|
+
[submitting]="submitting()"
|
|
16
|
+
[submitDisabled]="success()"
|
|
17
|
+
[footer]="{ link: routes.PROFILE.PATH, linkText: 'Back to Profile' }"
|
|
18
|
+
(submitted)="onSubmit()"
|
|
19
|
+
>
|
|
20
|
+
<div class="mt-4 flex flex-col gap-4">
|
|
21
|
+
<app-field
|
|
22
|
+
label="Current Password"
|
|
23
|
+
htmlFor="change-current-password"
|
|
24
|
+
[error]="controlError('currentPassword', 'required')"
|
|
25
|
+
>
|
|
26
|
+
<app-input
|
|
27
|
+
type="password"
|
|
28
|
+
[value]="form.controls.currentPassword.value ?? ''"
|
|
29
|
+
(valueChange)="setControl('currentPassword', $event)"
|
|
30
|
+
[placeholder]="placeholders.PASSWORD"
|
|
31
|
+
[disabled]="success()"
|
|
32
|
+
/>
|
|
33
|
+
</app-field>
|
|
34
|
+
|
|
35
|
+
<app-field
|
|
36
|
+
label="New Password"
|
|
37
|
+
htmlFor="change-new-password"
|
|
38
|
+
[error]="controlError('newPassword', 'password')"
|
|
39
|
+
>
|
|
40
|
+
<app-input
|
|
41
|
+
type="password"
|
|
42
|
+
[value]="form.controls.newPassword.value ?? ''"
|
|
43
|
+
(valueChange)="setControl('newPassword', $event)"
|
|
44
|
+
[placeholder]="placeholders.PASSWORD_NEW"
|
|
45
|
+
[disabled]="success()"
|
|
46
|
+
/>
|
|
47
|
+
</app-field>
|
|
48
|
+
|
|
49
|
+
<app-field
|
|
50
|
+
label="Confirm Password"
|
|
51
|
+
htmlFor="change-confirm-password"
|
|
52
|
+
[error]="
|
|
53
|
+
controlError('confirmPassword', 'passwordMismatch') ??
|
|
54
|
+
controlError('confirmPassword', 'required')
|
|
55
|
+
"
|
|
56
|
+
>
|
|
57
|
+
<app-input
|
|
58
|
+
type="password"
|
|
59
|
+
[value]="form.controls.confirmPassword.value ?? ''"
|
|
60
|
+
(valueChange)="setControl('confirmPassword', $event)"
|
|
61
|
+
[placeholder]="placeholders.PASSWORD_NEW_CONFIRM"
|
|
62
|
+
[disabled]="success()"
|
|
63
|
+
/>
|
|
64
|
+
</app-field>
|
|
65
|
+
</div>
|
|
66
|
+
</app-auth-form>
|
|
67
|
+
</div>
|
|
68
|
+
</main>
|
|
@@ -0,0 +1,82 @@
|
|
|
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, signal } from "@angular/core";
|
|
7
|
+
import { FormBuilder } from "@angular/forms";
|
|
8
|
+
import { DataClient } from "../../api/data-client.service";
|
|
9
|
+
import { AuthFormComponent } from "../../features/authentication/auth-form/auth-form";
|
|
10
|
+
import { ReactiveFormPageBase } from "../../features/authentication/reactive-form-page.base";
|
|
11
|
+
import { FieldComponent } from "../../components/ui/field/field";
|
|
12
|
+
import { InputComponent } from "../../components/ui/input/input";
|
|
13
|
+
import {
|
|
14
|
+
API_ROUTES,
|
|
15
|
+
AUTH_PLACEHOLDERS,
|
|
16
|
+
ROUTES,
|
|
17
|
+
} from "../../features/authentication/config/authentication.config";
|
|
18
|
+
import { ApiError, handleApiResponse } from "../../features/authentication/utils/helpers";
|
|
19
|
+
import {
|
|
20
|
+
passwordMinValidator,
|
|
21
|
+
passwordsMatchValidator,
|
|
22
|
+
requiredWithMessage,
|
|
23
|
+
} from "../../features/authentication/utils/auth-validators";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Change-password page — Angular port of the React `ChangePassword`. Protected
|
|
27
|
+
* route (guarded in `app.routes.ts`). Sends `{ currentPassword, newPassword }`;
|
|
28
|
+
* on success it resets the form and shows a success alert with a Back-to-Profile
|
|
29
|
+
* link. `showAlreadyLoggedIn` is false (the user is expected to be logged in).
|
|
30
|
+
*/
|
|
31
|
+
@Component({
|
|
32
|
+
selector: "app-change-password-page",
|
|
33
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
34
|
+
imports: [AuthFormComponent, FieldComponent, InputComponent],
|
|
35
|
+
templateUrl: "./change-password-page.html",
|
|
36
|
+
})
|
|
37
|
+
export class ChangePasswordPageComponent extends ReactiveFormPageBase {
|
|
38
|
+
private readonly fb = inject(FormBuilder);
|
|
39
|
+
private readonly dataClient = inject(DataClient);
|
|
40
|
+
|
|
41
|
+
protected readonly placeholders = AUTH_PLACEHOLDERS;
|
|
42
|
+
protected readonly routes = ROUTES;
|
|
43
|
+
|
|
44
|
+
protected override readonly form = this.fb.group(
|
|
45
|
+
{
|
|
46
|
+
currentPassword: ["", [requiredWithMessage("Current password is required")]],
|
|
47
|
+
newPassword: ["", [passwordMinValidator]],
|
|
48
|
+
confirmPassword: ["", [requiredWithMessage("Please confirm your password")]],
|
|
49
|
+
},
|
|
50
|
+
{ validators: [passwordsMatchValidator("newPassword", "confirmPassword")] },
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
protected readonly submitError = signal<string | string[] | null>(null);
|
|
54
|
+
protected readonly submitting = signal<boolean>(false);
|
|
55
|
+
protected readonly success = signal<boolean>(false);
|
|
56
|
+
|
|
57
|
+
protected async onSubmit(): Promise<void> {
|
|
58
|
+
this.form.markAllAsTouched();
|
|
59
|
+
if (this.form.invalid) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.submitError.set(null);
|
|
63
|
+
this.success.set(false);
|
|
64
|
+
this.submitting.set(true);
|
|
65
|
+
try {
|
|
66
|
+
const { currentPassword, newPassword } = this.form.getRawValue();
|
|
67
|
+
const response = await this.dataClient.fetch(API_ROUTES.CHANGE_PASSWORD, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
body: JSON.stringify({ currentPassword, newPassword }),
|
|
70
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
71
|
+
});
|
|
72
|
+
await handleApiResponse(response);
|
|
73
|
+
this.success.set(true);
|
|
74
|
+
this.form.reset({ currentPassword: "", newPassword: "", confirmPassword: "" });
|
|
75
|
+
} catch (err) {
|
|
76
|
+
console.error("Password change failed", err);
|
|
77
|
+
this.submitError.set(err instanceof ApiError ? err.errors : "Password change failed");
|
|
78
|
+
} finally {
|
|
79
|
+
this.submitting.set(false);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<main class="flex min-h-svh w-full justify-center p-6 md:p-10 items-start">
|
|
2
|
+
<div class="w-full max-w-md">
|
|
3
|
+
<app-auth-form
|
|
4
|
+
title="Forgot Password"
|
|
5
|
+
description="Enter your username and we'll send you a reset link"
|
|
6
|
+
[error]="submitError()"
|
|
7
|
+
[success]="
|
|
8
|
+
success()
|
|
9
|
+
? 'If that username exists in our system, you will receive a reset link shortly.'
|
|
10
|
+
: null
|
|
11
|
+
"
|
|
12
|
+
submitText="Send Reset Link"
|
|
13
|
+
submitLoadingText="Sending…"
|
|
14
|
+
[submitting]="submitting()"
|
|
15
|
+
[submitDisabled]="success()"
|
|
16
|
+
[footer]="{ text: 'Remember your password?', link: routes.LOGIN.PATH, linkText: 'Sign in' }"
|
|
17
|
+
(submitted)="onSubmit()"
|
|
18
|
+
>
|
|
19
|
+
<div class="mt-4 flex flex-col gap-4">
|
|
20
|
+
<app-field
|
|
21
|
+
label="Username"
|
|
22
|
+
htmlFor="forgot-username"
|
|
23
|
+
[error]="controlError('username', 'email')"
|
|
24
|
+
>
|
|
25
|
+
<app-input
|
|
26
|
+
[value]="form.controls.username.value ?? ''"
|
|
27
|
+
(valueChange)="setControl('username', $event)"
|
|
28
|
+
[placeholder]="placeholders.USERNAME"
|
|
29
|
+
[disabled]="success()"
|
|
30
|
+
/>
|
|
31
|
+
</app-field>
|
|
32
|
+
</div>
|
|
33
|
+
</app-auth-form>
|
|
34
|
+
</div>
|
|
35
|
+
</main>
|
|
@@ -0,0 +1,87 @@
|
|
|
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, signal } from "@angular/core";
|
|
7
|
+
import { FormBuilder } from "@angular/forms";
|
|
8
|
+
import { DataClient } from "../../api/data-client.service";
|
|
9
|
+
import { AuthFormComponent } from "../../features/authentication/auth-form/auth-form";
|
|
10
|
+
import { ReactiveFormPageBase } from "../../features/authentication/reactive-form-page.base";
|
|
11
|
+
import { FieldComponent } from "../../components/ui/field/field";
|
|
12
|
+
import { InputComponent } from "../../components/ui/input/input";
|
|
13
|
+
import {
|
|
14
|
+
API_ROUTES,
|
|
15
|
+
AUTH_PLACEHOLDERS,
|
|
16
|
+
ROUTES,
|
|
17
|
+
} from "../../features/authentication/config/authentication.config";
|
|
18
|
+
import { ApiError, handleApiResponse } from "../../features/authentication/utils/helpers";
|
|
19
|
+
import type { AbstractControl, ValidationErrors } from "@angular/forms";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Username validator — mirrors the React forgot-password zod schema which
|
|
23
|
+
* validates the username as an email but with the message "Please enter a
|
|
24
|
+
* valid username". Kept local since this message is unique to this page.
|
|
25
|
+
*/
|
|
26
|
+
function usernameValidator(control: AbstractControl): ValidationErrors | null {
|
|
27
|
+
const value = (control.value ?? "").toString().trim();
|
|
28
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
29
|
+
return value !== "" && emailPattern.test(value)
|
|
30
|
+
? null
|
|
31
|
+
: { email: "Please enter a valid username" };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Forgot-password page — Angular port of the React `ForgotPassword`.
|
|
36
|
+
*
|
|
37
|
+
* Anti-enumeration: the success message is intentionally generic ("If that
|
|
38
|
+
* username exists…") regardless of whether the account exists, and after a
|
|
39
|
+
* successful submit the username field and the submit button are disabled — an
|
|
40
|
+
* exact mirror of the React behavior.
|
|
41
|
+
*/
|
|
42
|
+
@Component({
|
|
43
|
+
selector: "app-forgot-password-page",
|
|
44
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
45
|
+
imports: [AuthFormComponent, FieldComponent, InputComponent],
|
|
46
|
+
templateUrl: "./forgot-password-page.html",
|
|
47
|
+
})
|
|
48
|
+
export class ForgotPasswordPageComponent extends ReactiveFormPageBase {
|
|
49
|
+
private readonly fb = inject(FormBuilder);
|
|
50
|
+
private readonly dataClient = inject(DataClient);
|
|
51
|
+
|
|
52
|
+
protected readonly placeholders = AUTH_PLACEHOLDERS;
|
|
53
|
+
protected readonly routes = ROUTES;
|
|
54
|
+
|
|
55
|
+
protected override readonly form = this.fb.group({
|
|
56
|
+
username: ["", [usernameValidator]],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
protected readonly submitError = signal<string | string[] | null>(null);
|
|
60
|
+
protected readonly submitting = signal<boolean>(false);
|
|
61
|
+
protected readonly success = signal<boolean>(false);
|
|
62
|
+
|
|
63
|
+
protected async onSubmit(): Promise<void> {
|
|
64
|
+
this.form.markAllAsTouched();
|
|
65
|
+
if (this.form.invalid) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.submitError.set(null);
|
|
69
|
+
this.success.set(false);
|
|
70
|
+
this.submitting.set(true);
|
|
71
|
+
try {
|
|
72
|
+
const username = (this.form.controls.username.value ?? "").trim();
|
|
73
|
+
const response = await this.dataClient.fetch(API_ROUTES.FORGOT_PASSWORD, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
body: JSON.stringify({ username }),
|
|
76
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
77
|
+
});
|
|
78
|
+
await handleApiResponse(response);
|
|
79
|
+
this.success.set(true);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error("Failed to send reset link", err);
|
|
82
|
+
this.submitError.set(err instanceof ApiError ? err.errors : "Failed to send reset link");
|
|
83
|
+
} finally {
|
|
84
|
+
this.submitting.set(false);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<div class="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
|
2
|
+
<div class="flex items-center gap-6 mb-6">
|
|
3
|
+
<h1 class="text-2xl font-bold">Account Search</h1>
|
|
4
|
+
<app-button appearance="outlined" size="sm" (clicked)="browseAll()"
|
|
5
|
+
>Browse All Accounts</app-button
|
|
6
|
+
>
|
|
7
|
+
</div>
|
|
8
|
+
<form class="flex gap-2 items-center" (submit)="onSubmit($event)">
|
|
9
|
+
<app-input
|
|
10
|
+
class="flex-1"
|
|
11
|
+
type="text"
|
|
12
|
+
placeholder="Search by name, phone, or industry..."
|
|
13
|
+
label="Search"
|
|
14
|
+
[(value)]="term"
|
|
15
|
+
/>
|
|
16
|
+
<app-button type="submit">Search</app-button>
|
|
17
|
+
</form>
|
|
18
|
+
</div>
|
|
@@ -0,0 +1,47 @@
|
|
|
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, signal } from "@angular/core";
|
|
7
|
+
import { Router } from "@angular/router";
|
|
8
|
+
// Base-app UI wrappers, inherited (not recreated) by this feature. Post-compose
|
|
9
|
+
// they land at uiBundles/<target>/src/app/components/ui/{button,input}/..., three levels
|
|
10
|
+
// up from this page folder (app/features/account-search/ -> app/components/ui/).
|
|
11
|
+
import { ButtonComponent } from "../../components/ui/button/button";
|
|
12
|
+
import { InputComponent } from "../../components/ui/input/input";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Account-search landing page. Mirrors the React `Home` page: a single search
|
|
16
|
+
* box plus a "Browse All Accounts" shortcut. Submitting navigates to the
|
|
17
|
+
* `accounts` list, carrying the typed term as the `q` query param so the search
|
|
18
|
+
* page's {@link ObjectSearchStateService} seeds the multi-field search filter.
|
|
19
|
+
*
|
|
20
|
+
* This is intentionally NOT the state-service-driven `app-search-bar` — Home
|
|
21
|
+
* has no search state of its own; it just routes into the search page.
|
|
22
|
+
*/
|
|
23
|
+
@Component({
|
|
24
|
+
selector: "app-home-page",
|
|
25
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26
|
+
imports: [ButtonComponent, InputComponent],
|
|
27
|
+
templateUrl: "./home-page.html",
|
|
28
|
+
})
|
|
29
|
+
export class HomePageComponent {
|
|
30
|
+
private readonly router = inject(Router);
|
|
31
|
+
|
|
32
|
+
/** Bound to the search input; forwarded as `?q=` on submit. */
|
|
33
|
+
protected readonly term = signal<string>("");
|
|
34
|
+
|
|
35
|
+
/** Navigate to the search page, seeding the search term when present. */
|
|
36
|
+
protected onSubmit(event: Event): void {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
this.browseAll(this.term() || undefined);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Go to the accounts list, optionally with a seeded search term. */
|
|
42
|
+
protected browseAll(q?: string): void {
|
|
43
|
+
void this.router.navigate(["/accounts"], {
|
|
44
|
+
queryParams: q ? { q } : {},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
import { HomeComponent } from './home';
|
|
3
|
+
|
|
4
|
+
describe('HomeComponent', () => {
|
|
5
|
+
beforeEach(async () => {
|
|
6
|
+
await TestBed.configureTestingModule({
|
|
7
|
+
imports: [HomeComponent],
|
|
8
|
+
}).compileComponents();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should create the component', () => {
|
|
12
|
+
const fixture = TestBed.createComponent(HomeComponent);
|
|
13
|
+
const component = fixture.componentInstance;
|
|
14
|
+
expect(component).toBeTruthy();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should render main landmark', async () => {
|
|
18
|
+
const fixture = TestBed.createComponent(HomeComponent);
|
|
19
|
+
await fixture.whenStable();
|
|
20
|
+
const compiled = fixture.nativeElement as HTMLElement;
|
|
21
|
+
expect(compiled.querySelector('main')).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
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 } from '@angular/core';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'app-home',
|
|
10
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
11
|
+
templateUrl: './home.html',
|
|
12
|
+
})
|
|
13
|
+
export class HomeComponent {}
|
package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/pages/login/login-page.html
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<main class="flex min-h-svh w-full justify-center p-6 md:p-10 items-start">
|
|
2
|
+
<div class="w-full max-w-md">
|
|
3
|
+
<app-auth-form
|
|
4
|
+
title="Login"
|
|
5
|
+
description="Enter your email below to login to your account"
|
|
6
|
+
[error]="submitError()"
|
|
7
|
+
submitText="Login"
|
|
8
|
+
submitLoadingText="Logging in…"
|
|
9
|
+
[submitting]="submitting()"
|
|
10
|
+
[footer]="{
|
|
11
|
+
text: 'Don\'t have an account?',
|
|
12
|
+
link: routes.REGISTER.PATH,
|
|
13
|
+
linkText: 'Sign up',
|
|
14
|
+
}"
|
|
15
|
+
(submitted)="onSubmit()"
|
|
16
|
+
>
|
|
17
|
+
<div class="mt-4 flex flex-col gap-4">
|
|
18
|
+
<app-field label="Email" htmlFor="login-email" [error]="controlError('email', 'email')">
|
|
19
|
+
<app-input
|
|
20
|
+
type="email"
|
|
21
|
+
[value]="form.controls.email.value ?? ''"
|
|
22
|
+
(valueChange)="setControl('email', $event)"
|
|
23
|
+
[placeholder]="placeholders.EMAIL"
|
|
24
|
+
/>
|
|
25
|
+
</app-field>
|
|
26
|
+
|
|
27
|
+
<app-field
|
|
28
|
+
label="Password"
|
|
29
|
+
htmlFor="login-password"
|
|
30
|
+
[error]="controlError('password', 'required')"
|
|
31
|
+
>
|
|
32
|
+
<app-input
|
|
33
|
+
type="password"
|
|
34
|
+
[value]="form.controls.password.value ?? ''"
|
|
35
|
+
(valueChange)="setControl('password', $event)"
|
|
36
|
+
/>
|
|
37
|
+
<a
|
|
38
|
+
[routerLink]="routes.FORGOT_PASSWORD.PATH"
|
|
39
|
+
class="text-sm underline-offset-4 hover:underline"
|
|
40
|
+
>
|
|
41
|
+
Forgot your password?
|
|
42
|
+
</a>
|
|
43
|
+
</app-field>
|
|
44
|
+
</div>
|
|
45
|
+
</app-auth-form>
|
|
46
|
+
</div>
|
|
47
|
+
</main>
|