@webiny/app-admin 6.6.0-alpha.0 → 6.6.0-alpha.2
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/base/Admin.js +17 -2
- package/base/Admin.js.map +1 -1
- package/base/Base/DefaultFieldRenderers.js +17 -2
- package/base/Base/DefaultFieldRenderers.js.map +1 -1
- package/base/Base/FieldRenderers/AutoCompleteRenderer.d.ts +13 -0
- package/base/Base/FieldRenderers/AutoCompleteRenderer.js +29 -0
- package/base/Base/FieldRenderers/AutoCompleteRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/HorizontalTabsRenderer.d.ts +2 -2
- package/base/Base/FieldRenderers/LexicalRenderer.js +10 -6
- package/base/Base/FieldRenderers/LexicalRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/MultiFilePickerRenderer.js +8 -5
- package/base/Base/FieldRenderers/MultiFilePickerRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/MultiSelectRenderer.d.ts +15 -0
- package/base/Base/FieldRenderers/MultiSelectRenderer.js +31 -0
- package/base/Base/FieldRenderers/MultiSelectRenderer.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.d.ts +2 -0
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js +5 -2
- package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/MultiValueDynamicZone.d.ts +11 -0
- package/base/Base/FieldRenderers/ObjectRenderer/{MultiValueDynamicZone.js → MultiValueDynamicZone/MultiValueDynamicZone.js} +65 -14
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/MultiValueDynamicZone.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/MultiValueDynamicZonePresenter.d.ts +13 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/MultiValueDynamicZonePresenter.js +28 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/MultiValueDynamicZonePresenter.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/abstractions.d.ts +15 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/abstractions.js +5 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/abstractions.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/feature.d.ts +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/feature.js +11 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/feature.js.map +1 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/index.d.ts +2 -0
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone/index.js +2 -0
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.d.ts +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js +19 -3
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.d.ts +10 -8
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js +34 -3
- package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.d.ts +3 -2
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js +11 -5
- package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js.map +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js +1 -1
- package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js.map +1 -1
- package/base/Base/FieldRenderers/SelectRenderer.d.ts +6 -0
- package/base/Base/FieldRenderers/SelectRenderer.js.map +1 -1
- package/base/Base/FieldRenderers/VerticalTabsRenderer.d.ts +2 -2
- package/base/Base/Menus.js +4 -4
- package/base/Base/Menus.js.map +1 -1
- package/base/createRootContainer.js +4 -2
- package/base/createRootContainer.js.map +1 -1
- package/components/Drawers/DrawerParamsContext.d.ts +6 -0
- package/components/Drawers/DrawerParamsContext.js +10 -0
- package/components/Drawers/DrawerParamsContext.js.map +1 -0
- package/components/Drawers/DrawersContext.d.ts +13 -0
- package/components/Drawers/DrawersContext.js +50 -0
- package/components/Drawers/DrawersContext.js.map +1 -0
- package/components/Drawers/useDrawers.d.ts +2 -0
- package/components/Drawers/useDrawers.js +10 -0
- package/components/Drawers/useDrawers.js.map +1 -0
- package/components/Filters/Filters.js +4 -3
- package/components/Filters/Filters.js.map +1 -1
- package/components/IconPicker/IconPickerComponent.d.ts +2 -2
- package/components/LexicalEditor/LexicalLinkForm.js +3 -0
- package/components/LexicalEditor/LexicalLinkForm.js.map +1 -1
- package/components/ListView/ListViewBulkActions.d.ts +2 -2
- package/components/ListView/ListViewContent.d.ts +2 -2
- package/components/ListView/ListViewFilters.d.ts +2 -2
- package/components/ListView/index.d.ts +6 -6
- package/components/OverlayLayout/OverlayLayout.js +4 -2
- package/components/OverlayLayout/OverlayLayout.js.map +1 -1
- package/components/OverlayLayout/components/OverlayContent.js +1 -0
- package/components/OverlayLayout/components/OverlayContent.js.map +1 -1
- package/components/RolesMultiAutocomplete/index.d.ts +4 -2
- package/components/SplitView/SplitView.js +1 -1
- package/components/SplitView/SplitView.js.map +1 -1
- package/components/Table/components/Table/TableInner.d.ts +2 -2
- package/components/TeamAutocomplete/index.d.ts +4 -2
- package/components/TeamsMultiAutocomplete/index.d.ts +4 -2
- package/components/index.d.ts +0 -1
- package/components/index.js +0 -1
- package/config/AdminConfig/Breadcrumbs.d.ts +42 -0
- package/config/AdminConfig/Breadcrumbs.js +24 -0
- package/config/AdminConfig/Breadcrumbs.js.map +1 -0
- package/config/AdminConfig/Drawer.d.ts +10 -0
- package/config/AdminConfig/Drawer.js +19 -0
- package/config/AdminConfig/Drawer.js.map +1 -0
- package/config/AdminConfig/LexicalTheme/AllowCustomColors.d.ts +5 -0
- package/config/AdminConfig/LexicalTheme/AllowCustomColors.js +18 -0
- package/config/AdminConfig/LexicalTheme/AllowCustomColors.js.map +1 -0
- package/config/AdminConfig/LexicalTheme.d.ts +2 -0
- package/config/AdminConfig/LexicalTheme.js +2 -0
- package/config/AdminConfig/LexicalTheme.js.map +1 -1
- package/config/AdminConfig.d.ts +8 -0
- package/config/AdminConfig.js +8 -1
- package/config/AdminConfig.js.map +1 -1
- package/exports/admin.d.ts +3 -0
- package/exports/admin.js +3 -0
- package/features/accessManagement/types.d.ts +3 -3
- package/features/aiChat/AiChatGateway.d.ts +30 -0
- package/features/aiChat/AiChatGateway.js +41 -0
- package/features/aiChat/AiChatGateway.js.map +1 -0
- package/features/aiChat/AiChatPresenter.d.ts +32 -0
- package/features/aiChat/AiChatPresenter.js +220 -0
- package/features/aiChat/AiChatPresenter.js.map +1 -0
- package/features/aiChat/abstractions.d.ts +124 -0
- package/features/aiChat/abstractions.js +6 -0
- package/features/aiChat/abstractions.js.map +1 -0
- package/features/aiChat/feature.d.ts +3 -0
- package/features/aiChat/feature.js +19 -0
- package/features/aiChat/feature.js.map +1 -0
- package/features/aiChat/index.d.ts +6 -0
- package/features/aiChat/index.js +3 -0
- package/features/dateFormatter/DefaultDateFormatter.d.ts +8 -0
- package/features/dateFormatter/DefaultDateFormatter.js +25 -0
- package/features/dateFormatter/DefaultDateFormatter.js.map +1 -0
- package/features/dateFormatter/abstractions.d.ts +13 -0
- package/features/dateFormatter/abstractions.js +5 -0
- package/features/dateFormatter/abstractions.js.map +1 -0
- package/features/dateFormatter/feature.d.ts +3 -0
- package/features/dateFormatter/feature.js +17 -0
- package/features/dateFormatter/feature.js.map +1 -0
- package/features/dateFormatter/index.d.ts +4 -0
- package/features/dateFormatter/index.js +4 -0
- package/features/dateFormatter/useDateFormatter.d.ts +5 -0
- package/features/dateFormatter/useDateFormatter.js +8 -0
- package/features/dateFormatter/useDateFormatter.js.map +1 -0
- package/features/featureFlags/FeatureFlagsGateway.d.ts +10 -0
- package/features/featureFlags/FeatureFlagsGateway.js +40 -0
- package/features/featureFlags/FeatureFlagsGateway.js.map +1 -0
- package/features/featureFlags/FeatureFlagsService.d.ts +16 -0
- package/features/featureFlags/FeatureFlagsService.js +64 -0
- package/features/featureFlags/FeatureFlagsService.js.map +1 -0
- package/features/featureFlags/abstractions.d.ts +19 -0
- package/features/featureFlags/abstractions.js +6 -0
- package/features/featureFlags/abstractions.js.map +1 -0
- package/features/featureFlags/feature.d.ts +3 -0
- package/features/featureFlags/feature.js +19 -0
- package/features/featureFlags/feature.js.map +1 -0
- package/features/formModel/Field.js +10 -0
- package/features/formModel/Field.js.map +1 -1
- package/features/formModel/FieldBuilder.js +1 -1
- package/features/formModel/FieldBuilder.js.map +1 -1
- package/features/formModel/FieldBuilder.test.js +4 -4
- package/features/formModel/FieldBuilder.test.js.map +1 -1
- package/features/formModel/FormErrors.d.ts +2 -2
- package/features/formModel/FormModel.test.js +50 -0
- package/features/formModel/FormModel.test.js.map +1 -1
- package/features/formModel/FormView.d.ts +8 -4
- package/features/formModel/PresenterErrors.d.ts +2 -2
- package/features/formModel/demo/FormModelDemo.d.ts +2 -2
- package/features/formModel/renderers.d.ts +1 -0
- package/features/formModel/renderers.js +1 -0
- package/features/notifications/NotificationsRenderer.d.ts +2 -2
- package/features/security/AuthenticationContext/ApiStreamClientDecorator.d.ts +22 -0
- package/features/security/AuthenticationContext/ApiStreamClientDecorator.js +32 -0
- package/features/security/AuthenticationContext/ApiStreamClientDecorator.js.map +1 -0
- package/features/security/AuthenticationContext/feature.js +2 -0
- package/features/security/AuthenticationContext/feature.js.map +1 -1
- package/features/slugify/DefaultSlugify.d.ts +8 -0
- package/features/slugify/DefaultSlugify.js +20 -0
- package/features/slugify/DefaultSlugify.js.map +1 -0
- package/features/slugify/abstractions.d.ts +12 -0
- package/features/slugify/abstractions.js +5 -0
- package/features/slugify/abstractions.js.map +1 -0
- package/features/slugify/feature.d.ts +1 -0
- package/features/slugify/feature.js +11 -0
- package/features/slugify/feature.js.map +1 -0
- package/features/slugify/index.d.ts +3 -0
- package/features/slugify/index.js +3 -0
- package/features/stringFormatter/DefaultStringFormatter.d.ts +17 -0
- package/features/stringFormatter/DefaultStringFormatter.js +19 -0
- package/features/stringFormatter/DefaultStringFormatter.js.map +1 -0
- package/features/stringFormatter/abstractions.d.ts +11 -0
- package/features/stringFormatter/abstractions.js +5 -0
- package/features/stringFormatter/abstractions.js.map +1 -0
- package/features/stringFormatter/feature.d.ts +3 -0
- package/features/stringFormatter/feature.js +19 -0
- package/features/stringFormatter/feature.js.map +1 -0
- package/features/stringFormatter/index.d.ts +4 -0
- package/features/stringFormatter/index.js +4 -0
- package/features/stringFormatter/useStringFormatter.d.ts +5 -0
- package/features/stringFormatter/useStringFormatter.js +8 -0
- package/features/stringFormatter/useStringFormatter.js.map +1 -0
- package/features/tenancy/ApiStreamClientDecorator.d.ts +16 -0
- package/features/tenancy/ApiStreamClientDecorator.js +30 -0
- package/features/tenancy/ApiStreamClientDecorator.js.map +1 -0
- package/features/tenancy/feature.js +2 -0
- package/features/tenancy/feature.js.map +1 -1
- package/features/wcp/ReactLicense.d.ts +6 -0
- package/features/wcp/ReactLicense.js +18 -0
- package/features/wcp/ReactLicense.js.map +1 -1
- package/features/wcp/WcpGateway.js +3 -0
- package/features/wcp/WcpGateway.js.map +1 -1
- package/hooks/index.d.ts +3 -0
- package/hooks/index.js +3 -0
- package/hooks/useDrawer.d.ts +9 -0
- package/hooks/useDrawer.js +19 -0
- package/hooks/useDrawer.js.map +1 -0
- package/hooks/useHotkeys.js +5 -3
- package/hooks/useHotkeys.js.map +1 -1
- package/hooks/useOpenDrawer.d.ts +7 -0
- package/hooks/useOpenDrawer.js +18 -0
- package/hooks/useOpenDrawer.js.map +1 -0
- package/hooks/useSnackbar.js.map +1 -1
- package/index.d.ts +18 -1
- package/index.js +23 -12
- package/modules/AccessManagementExtension.js +46 -22
- package/modules/AccessManagementExtension.js.map +1 -1
- package/package.json +31 -28
- package/presentation/accessManagement/SecurityPermissions.js +3 -3
- package/presentation/accessManagement/SecurityPermissions.js.map +1 -1
- package/presentation/accessManagement/apiKeys/ApiKeysPresenter.d.ts +3 -1
- package/presentation/accessManagement/apiKeys/ApiKeysPresenter.js +13 -16
- package/presentation/accessManagement/apiKeys/ApiKeysPresenter.js.map +1 -1
- package/presentation/accessManagement/apiKeys/components/ApiKeysView.d.ts +2 -2
- package/presentation/accessManagement/apiKeys/components/ApiKeysView.js +13 -7
- package/presentation/accessManagement/apiKeys/components/ApiKeysView.js.map +1 -1
- package/presentation/accessManagement/roles/RolesPresenter.d.ts +3 -1
- package/presentation/accessManagement/roles/RolesPresenter.js +11 -14
- package/presentation/accessManagement/roles/RolesPresenter.js.map +1 -1
- package/presentation/accessManagement/roles/components/RolesView.d.ts +2 -2
- package/presentation/accessManagement/roles/components/RolesView.js +10 -6
- package/presentation/accessManagement/roles/components/RolesView.js.map +1 -1
- package/presentation/accessManagement/teams/TeamsPresenter.d.ts +3 -1
- package/presentation/accessManagement/teams/TeamsPresenter.js +11 -14
- package/presentation/accessManagement/teams/TeamsPresenter.js.map +1 -1
- package/presentation/accessManagement/teams/components/TeamsView.d.ts +2 -2
- package/presentation/accessManagement/teams/components/TeamsView.js +10 -6
- package/presentation/accessManagement/teams/components/TeamsView.js.map +1 -1
- package/presentation/commandPalette/CommandPalettePresenter.d.ts +21 -0
- package/presentation/commandPalette/CommandPalettePresenter.js +91 -0
- package/presentation/commandPalette/CommandPalettePresenter.js.map +1 -0
- package/presentation/commandPalette/abstractions.d.ts +76 -0
- package/presentation/commandPalette/abstractions.js +7 -0
- package/presentation/commandPalette/abstractions.js.map +1 -0
- package/presentation/commandPalette/commands/AskAiCommand.d.ts +25 -0
- package/presentation/commandPalette/commands/AskAiCommand.js +33 -0
- package/presentation/commandPalette/commands/AskAiCommand.js.map +1 -0
- package/presentation/commandPalette/commands/CopyCurrentUrlCommand.d.ts +15 -0
- package/presentation/commandPalette/commands/CopyCurrentUrlCommand.js +33 -0
- package/presentation/commandPalette/commands/CopyCurrentUrlCommand.js.map +1 -0
- package/presentation/commandPalette/commands/SendMessageCommand.d.ts +23 -0
- package/presentation/commandPalette/commands/SendMessageCommand.js +66 -0
- package/presentation/commandPalette/commands/SendMessageCommand.js.map +1 -0
- package/presentation/commandPalette/commands/SignOutCommand.d.ts +18 -0
- package/presentation/commandPalette/commands/SignOutCommand.js +37 -0
- package/presentation/commandPalette/commands/SignOutCommand.js.map +1 -0
- package/presentation/commandPalette/commands/feature.d.ts +5 -0
- package/presentation/commandPalette/commands/feature.js +17 -0
- package/presentation/commandPalette/commands/feature.js.map +1 -0
- package/presentation/commandPalette/feature.d.ts +3 -0
- package/presentation/commandPalette/feature.js +17 -0
- package/presentation/commandPalette/feature.js.map +1 -0
- package/presentation/commandPalette/index.d.ts +3 -0
- package/presentation/commandPalette/index.js +2 -0
- package/presentation/featureFlags/FeatureFlagsProvider.d.ts +7 -0
- package/presentation/featureFlags/FeatureFlagsProvider.js +22 -0
- package/presentation/featureFlags/FeatureFlagsProvider.js.map +1 -0
- package/presentation/featureFlags/useFeatureFlags.d.ts +2 -0
- package/presentation/featureFlags/useFeatureFlags.js +17 -0
- package/presentation/featureFlags/useFeatureFlags.js.map +1 -0
- package/presentation/installation/components/SystemInstaller/SystemInstaller.d.ts +2 -2
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleStartUsing.js +0 -3
- package/presentation/installation/components/SystemInstaller/steps/FinishSetup/handleStartUsing.js.map +1 -1
- package/presentation/listPresenter/FolderAwareDataSource.js +4 -1
- package/presentation/listPresenter/FolderAwareDataSource.js.map +1 -1
- package/presentation/listPresenter/QueryMatcher.js +2 -2
- package/presentation/listPresenter/QueryMatcher.js.map +1 -1
- package/presentation/sortable/SortablePresenter.d.ts +23 -0
- package/presentation/sortable/SortablePresenter.js +175 -0
- package/presentation/sortable/SortablePresenter.js.map +1 -0
- package/presentation/sortable/abstractions.d.ts +24 -0
- package/presentation/sortable/abstractions.js +5 -0
- package/presentation/sortable/abstractions.js.map +1 -0
- package/presentation/sortable/feature.d.ts +1 -0
- package/presentation/sortable/feature.js +11 -0
- package/presentation/sortable/feature.js.map +1 -0
- package/presentation/sortable/index.d.ts +2 -0
- package/presentation/sortable/index.js +2 -0
- package/presentation/trashBin/components/BulkActions/DeleteItems.d.ts +2 -2
- package/presentation/trashBin/components/BulkActions/RestoreItems.d.ts +2 -2
- package/presentation/trashBin/components/TrashBinOverlay.d.ts +2 -2
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.d.ts +0 -10
- package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.js.map +0 -1
- package/base/Base/Menus/WebinyVersion.d.ts +0 -2
- package/base/Base/Menus/WebinyVersion.js +0 -23
- package/base/Base/Menus/WebinyVersion.js.map +0 -1
- package/base/WebinyVersion.d.ts +0 -2
- package/base/WebinyVersion.js +0 -23
- package/base/WebinyVersion.js.map +0 -1
- package/components/Wcp.d.ts +0 -19
- package/components/Wcp.js +0 -37
- package/components/Wcp.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StringFormatter } from "../../../features/stringFormatter/abstractions.js";
|
|
1
2
|
import { ListPresenter } from "../../../presentation/listPresenter/abstractions.js";
|
|
2
3
|
import { FormModelFactory } from "../../../features/formModel/abstractions.js";
|
|
3
4
|
import type { Team } from "../../../features/accessManagement/types.js";
|
|
@@ -16,13 +17,14 @@ declare class TeamsPresenterImpl implements ITeamsPresenter {
|
|
|
16
17
|
private updateTeamUseCase;
|
|
17
18
|
private deleteTeamUseCase;
|
|
18
19
|
private cache;
|
|
20
|
+
private stringFormatter;
|
|
19
21
|
private _selectedTeam;
|
|
20
22
|
private _loading;
|
|
21
23
|
private _saving;
|
|
22
24
|
private _showForm;
|
|
23
25
|
private _form;
|
|
24
26
|
private _isNew;
|
|
25
|
-
constructor(_listPresenter: ListPresenter.Interface<Team>, formModelFactory: FormModelFactory.Interface, listTeamsUseCase: ListTeamsUseCase.Interface, getTeamUseCase: GetTeamUseCase.Interface, createTeamUseCase: CreateTeamUseCase.Interface, updateTeamUseCase: UpdateTeamUseCase.Interface, deleteTeamUseCase: DeleteTeamUseCase.Interface, cache: TeamsListCache.Interface);
|
|
27
|
+
constructor(_listPresenter: ListPresenter.Interface<Team>, formModelFactory: FormModelFactory.Interface, listTeamsUseCase: ListTeamsUseCase.Interface, getTeamUseCase: GetTeamUseCase.Interface, createTeamUseCase: CreateTeamUseCase.Interface, updateTeamUseCase: UpdateTeamUseCase.Interface, deleteTeamUseCase: DeleteTeamUseCase.Interface, cache: TeamsListCache.Interface, stringFormatter: StringFormatter.Interface);
|
|
26
28
|
get vm(): ITeamsPresenterViewModel;
|
|
27
29
|
get list(): ListPresenter.Interface<Team>;
|
|
28
30
|
init(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { computed, makeAutoObservable, runInAction } from "mobx";
|
|
2
|
-
import
|
|
3
|
+
import { StringFormatter } from "../../../features/stringFormatter/abstractions.js";
|
|
3
4
|
import { ListPresenter } from "../../listPresenter/abstractions.js";
|
|
4
5
|
import { FormModelFactory } from "../../../features/formModel/abstractions.js";
|
|
5
6
|
import { ListTeamsUseCase, TeamsListCache } from "../../../features/accessManagement/teams/listTeams/abstractions.js";
|
|
@@ -10,7 +11,7 @@ import { DeleteTeamUseCase } from "../../../features/accessManagement/teams/dele
|
|
|
10
11
|
import { TeamsPresenter } from "./abstractions.js";
|
|
11
12
|
import { TeamsDataSource } from "./TeamsDataSource.js";
|
|
12
13
|
class TeamsPresenterImpl {
|
|
13
|
-
constructor(_listPresenter, formModelFactory, listTeamsUseCase, getTeamUseCase, createTeamUseCase, updateTeamUseCase, deleteTeamUseCase, cache){
|
|
14
|
+
constructor(_listPresenter, formModelFactory, listTeamsUseCase, getTeamUseCase, createTeamUseCase, updateTeamUseCase, deleteTeamUseCase, cache, stringFormatter){
|
|
14
15
|
this._listPresenter = _listPresenter;
|
|
15
16
|
this.formModelFactory = formModelFactory;
|
|
16
17
|
this.listTeamsUseCase = listTeamsUseCase;
|
|
@@ -19,6 +20,7 @@ class TeamsPresenterImpl {
|
|
|
19
20
|
this.updateTeamUseCase = updateTeamUseCase;
|
|
20
21
|
this.deleteTeamUseCase = deleteTeamUseCase;
|
|
21
22
|
this.cache = cache;
|
|
23
|
+
this.stringFormatter = stringFormatter;
|
|
22
24
|
this._selectedTeam = null;
|
|
23
25
|
this._loading = false;
|
|
24
26
|
this._saving = false;
|
|
@@ -33,6 +35,7 @@ class TeamsPresenterImpl {
|
|
|
33
35
|
updateTeamUseCase: false,
|
|
34
36
|
deleteTeamUseCase: false,
|
|
35
37
|
cache: false,
|
|
38
|
+
stringFormatter: false,
|
|
36
39
|
vm: computed
|
|
37
40
|
});
|
|
38
41
|
}
|
|
@@ -80,7 +83,7 @@ class TeamsPresenterImpl {
|
|
|
80
83
|
this._form.setData({
|
|
81
84
|
name: team.name,
|
|
82
85
|
slug: team.slug,
|
|
83
|
-
description: team.description,
|
|
86
|
+
description: team.description ?? "",
|
|
84
87
|
roles: team.roles || []
|
|
85
88
|
});
|
|
86
89
|
});
|
|
@@ -134,14 +137,12 @@ class TeamsPresenterImpl {
|
|
|
134
137
|
this._form.setData({
|
|
135
138
|
name: team.name,
|
|
136
139
|
slug: team.slug,
|
|
137
|
-
description: team.description,
|
|
140
|
+
description: team.description ?? "",
|
|
138
141
|
roles: team.roles || []
|
|
139
142
|
});
|
|
140
143
|
});
|
|
141
144
|
return team;
|
|
142
145
|
}
|
|
143
|
-
} catch {
|
|
144
|
-
return null;
|
|
145
146
|
} finally{
|
|
146
147
|
runInAction(()=>{
|
|
147
148
|
this._saving = false;
|
|
@@ -163,15 +164,10 @@ class TeamsPresenterImpl {
|
|
|
163
164
|
name: fields.text().label("Name").required("Name is required.").disabled(!canModify).onBlur((value, { form })=>{
|
|
164
165
|
const slugValue = form.field("slug").getValue();
|
|
165
166
|
if (slugValue || !value) return;
|
|
166
|
-
form.field("slug").setValue(slugify(String(value)
|
|
167
|
-
replacement: "-",
|
|
168
|
-
lower: true,
|
|
169
|
-
remove: /[*#?<>_{}[\]+~.()'"!:;@]/g,
|
|
170
|
-
trim: false
|
|
171
|
-
}));
|
|
167
|
+
form.field("slug").setValue(this.stringFormatter.slugify(String(value)));
|
|
172
168
|
}),
|
|
173
169
|
slug: fields.text().label("Slug").required("Slug is required.").disabled(!isNew || !canModify),
|
|
174
|
-
description: fields.text().label("Description").renderer("textarea").defaultValue("").disabled(!canModify),
|
|
170
|
+
description: fields.text().label("Description").renderer("textarea").defaultValue("").schema(z.string().max(500, "Description cannot be longer than 500 characters.")).disabled(!canModify),
|
|
175
171
|
roles: fields.rolesMultiSelect().label("Roles").required("Roles are required.").disabled(!canModify)
|
|
176
172
|
}),
|
|
177
173
|
layout: (layout)=>[
|
|
@@ -192,7 +188,8 @@ const TeamsPresenter_TeamsPresenter = TeamsPresenter.createImplementation({
|
|
|
192
188
|
CreateTeamUseCase,
|
|
193
189
|
UpdateTeamUseCase,
|
|
194
190
|
DeleteTeamUseCase,
|
|
195
|
-
TeamsListCache
|
|
191
|
+
TeamsListCache,
|
|
192
|
+
StringFormatter
|
|
196
193
|
]
|
|
197
194
|
});
|
|
198
195
|
export { TeamsPresenter_TeamsPresenter as TeamsPresenter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/accessManagement/teams/TeamsPresenter.js","sources":["../../../../src/presentation/accessManagement/teams/TeamsPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport slugify from \"slugify\";\nimport { ListPresenter } from \"~/presentation/listPresenter/abstractions.js\";\nimport { FormModelFactory } from \"~/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"~/features/formModel/abstractions.js\";\nimport type { Team } from \"~/features/accessManagement/types.js\";\nimport {\n ListTeamsUseCase,\n TeamsListCache\n} from \"~/features/accessManagement/teams/listTeams/abstractions.js\";\nimport { GetTeamUseCase } from \"~/features/accessManagement/teams/getTeam/abstractions.js\";\nimport { CreateTeamUseCase } from \"~/features/accessManagement/teams/createTeam/abstractions.js\";\nimport { UpdateTeamUseCase } from \"~/features/accessManagement/teams/updateTeam/abstractions.js\";\nimport { DeleteTeamUseCase } from \"~/features/accessManagement/teams/deleteTeam/abstractions.js\";\nimport {\n TeamsPresenter as Abstraction,\n type ITeamsPresenter,\n type ITeamsPresenterViewModel\n} from \"./abstractions.js\";\nimport { TeamsDataSource } from \"./TeamsDataSource.js\";\n\nclass TeamsPresenterImpl implements ITeamsPresenter {\n private _selectedTeam: Team | null = null;\n private _loading = false;\n private _saving = false;\n private _showForm = false;\n private _form: IFormModel;\n private _isNew = false;\n\n constructor(\n private _listPresenter: ListPresenter.Interface<Team>,\n private formModelFactory: FormModelFactory.Interface,\n private listTeamsUseCase: ListTeamsUseCase.Interface,\n private getTeamUseCase: GetTeamUseCase.Interface,\n private createTeamUseCase: CreateTeamUseCase.Interface,\n private updateTeamUseCase: UpdateTeamUseCase.Interface,\n private deleteTeamUseCase: DeleteTeamUseCase.Interface,\n private cache: TeamsListCache.Interface\n ) {\n this._form = this.buildForm(false, true);\n makeAutoObservable<\n TeamsPresenterImpl,\n | \"formModelFactory\"\n | \"listTeamsUseCase\"\n | \"getTeamUseCase\"\n | \"createTeamUseCase\"\n | \"updateTeamUseCase\"\n | \"deleteTeamUseCase\"\n | \"cache\"\n >(this, {\n formModelFactory: false,\n listTeamsUseCase: false,\n getTeamUseCase: false,\n createTeamUseCase: false,\n updateTeamUseCase: false,\n deleteTeamUseCase: false,\n cache: false,\n vm: computed\n });\n }\n\n get vm(): ITeamsPresenterViewModel {\n const team = this._selectedTeam;\n const systemTeam = team !== null && team.system === true;\n const pluginTeam = team !== null && (team.plugin ?? false);\n\n return {\n selectedTeam: this._selectedTeam,\n loading: this._loading,\n saving: this._saving,\n showForm: this._showForm,\n canModify: !systemTeam && !pluginTeam,\n form: this._form.vm\n };\n }\n\n get list(): ListPresenter.Interface<Team> {\n return this._listPresenter;\n }\n\n init(): void {\n const dataSource = new TeamsDataSource(this.listTeamsUseCase, this.cache);\n\n this._listPresenter.init({\n dataSource,\n initialSort: { field: \"createdOn\", direction: \"DESC\" },\n limit: 1000\n });\n }\n\n async selectTeam(id: string): Promise<void> {\n runInAction(() => {\n this._loading = true;\n this._showForm = true;\n this._isNew = false;\n });\n\n try {\n const team = await this.getTeamUseCase.execute(id);\n const systemTeam = team.system === true;\n const pluginTeam = team.plugin ?? false;\n const canModify = !systemTeam && !pluginTeam;\n\n runInAction(() => {\n this._selectedTeam = team;\n this._form = this.buildForm(false, canModify);\n this._form.setData({\n name: team.name,\n slug: team.slug,\n description: team.description,\n roles: team.roles || []\n });\n });\n } finally {\n runInAction(() => {\n this._loading = false;\n });\n }\n }\n\n createNew(): void {\n this._selectedTeam = null;\n this._isNew = true;\n this._form = this.buildForm(true, true);\n this._showForm = true;\n }\n\n deselect(): void {\n this._selectedTeam = null;\n this._showForm = false;\n }\n\n async save(): Promise<Team | null> {\n const data = await this._form.submit();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this._saving = true;\n });\n\n try {\n const roles = ((data.roles as any[]) || []).map((r: any) =>\n typeof r === \"string\" ? r : r.id\n );\n const isUpdate = this._selectedTeam !== null && this._selectedTeam.createdOn;\n\n if (isUpdate) {\n const team = await this.updateTeamUseCase.execute(this._selectedTeam!.id, {\n name: data.name as string,\n description: data.description as string,\n roles\n });\n runInAction(() => {\n this._selectedTeam = team;\n });\n return team;\n } else {\n const team = await this.createTeamUseCase.execute({\n name: data.name as string,\n slug: data.slug as string,\n description: data.description as string,\n roles\n });\n runInAction(() => {\n this._selectedTeam = team;\n this._isNew = false;\n this._form = this.buildForm(false, true);\n this._form.setData({\n name: team.name,\n slug: team.slug,\n description: team.description,\n roles: team.roles || []\n });\n });\n return team;\n }\n } catch {\n return null;\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n }\n\n async deleteTeam(id: string): Promise<void> {\n await this.deleteTeamUseCase.execute(id);\n\n runInAction(() => {\n if (this._selectedTeam !== null && this._selectedTeam.id === id) {\n this._selectedTeam = null;\n this._showForm = false;\n }\n });\n }\n\n private buildForm(isNew: boolean, canModify: boolean): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields\n .text()\n .label(\"Name\")\n .required(\"Name is required.\")\n .disabled(!canModify)\n .onBlur((value, { form }) => {\n const slugValue = form.field(\"slug\").getValue();\n if (slugValue || !value) {\n return;\n }\n form.field(\"slug\").setValue(\n slugify(String(value), {\n replacement: \"-\",\n lower: true,\n remove: /[*#?<>_{}[\\]+~.()'\"!:;@]/g,\n trim: false\n })\n );\n }),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required.\")\n .disabled(!isNew || !canModify),\n description: fields\n .text()\n .label(\"Description\")\n .renderer(\"textarea\")\n .defaultValue(\"\")\n .disabled(!canModify),\n roles: fields\n .rolesMultiSelect()\n .label(\"Roles\")\n .required(\"Roles are required.\")\n .disabled(!canModify)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"description\"),\n layout.row(\"roles\")\n ]\n });\n }\n}\n\nexport const TeamsPresenter = Abstraction.createImplementation({\n implementation: TeamsPresenterImpl,\n dependencies: [\n ListPresenter,\n FormModelFactory,\n ListTeamsUseCase,\n GetTeamUseCase,\n CreateTeamUseCase,\n UpdateTeamUseCase,\n DeleteTeamUseCase,\n TeamsListCache\n ]\n});\n"],"names":["TeamsPresenterImpl","_listPresenter","formModelFactory","listTeamsUseCase","getTeamUseCase","createTeamUseCase","updateTeamUseCase","deleteTeamUseCase","cache","makeAutoObservable","computed","team","systemTeam","pluginTeam","dataSource","TeamsDataSource","id","runInAction","canModify","data","roles","r","isUpdate","isNew","fields","value","form","slugValue","slugify","String","layout","TeamsPresenter","Abstraction","ListPresenter","FormModelFactory","ListTeamsUseCase","GetTeamUseCase","CreateTeamUseCase","UpdateTeamUseCase","DeleteTeamUseCase","TeamsListCache"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentation/accessManagement/teams/TeamsPresenter.js","sources":["../../../../src/presentation/accessManagement/teams/TeamsPresenter.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { StringFormatter } from \"~/features/stringFormatter/abstractions.js\";\nimport { ListPresenter } from \"~/presentation/listPresenter/abstractions.js\";\nimport { FormModelFactory } from \"~/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"~/features/formModel/abstractions.js\";\nimport type { Team } from \"~/features/accessManagement/types.js\";\nimport {\n ListTeamsUseCase,\n TeamsListCache\n} from \"~/features/accessManagement/teams/listTeams/abstractions.js\";\nimport { GetTeamUseCase } from \"~/features/accessManagement/teams/getTeam/abstractions.js\";\nimport { CreateTeamUseCase } from \"~/features/accessManagement/teams/createTeam/abstractions.js\";\nimport { UpdateTeamUseCase } from \"~/features/accessManagement/teams/updateTeam/abstractions.js\";\nimport { DeleteTeamUseCase } from \"~/features/accessManagement/teams/deleteTeam/abstractions.js\";\nimport {\n TeamsPresenter as Abstraction,\n type ITeamsPresenter,\n type ITeamsPresenterViewModel\n} from \"./abstractions.js\";\nimport { TeamsDataSource } from \"./TeamsDataSource.js\";\n\nclass TeamsPresenterImpl implements ITeamsPresenter {\n private _selectedTeam: Team | null = null;\n private _loading = false;\n private _saving = false;\n private _showForm = false;\n private _form: IFormModel;\n private _isNew = false;\n\n constructor(\n private _listPresenter: ListPresenter.Interface<Team>,\n private formModelFactory: FormModelFactory.Interface,\n private listTeamsUseCase: ListTeamsUseCase.Interface,\n private getTeamUseCase: GetTeamUseCase.Interface,\n private createTeamUseCase: CreateTeamUseCase.Interface,\n private updateTeamUseCase: UpdateTeamUseCase.Interface,\n private deleteTeamUseCase: DeleteTeamUseCase.Interface,\n private cache: TeamsListCache.Interface,\n private stringFormatter: StringFormatter.Interface\n ) {\n this._form = this.buildForm(false, true);\n makeAutoObservable<\n TeamsPresenterImpl,\n | \"formModelFactory\"\n | \"listTeamsUseCase\"\n | \"getTeamUseCase\"\n | \"createTeamUseCase\"\n | \"updateTeamUseCase\"\n | \"deleteTeamUseCase\"\n | \"cache\"\n | \"stringFormatter\"\n >(this, {\n formModelFactory: false,\n listTeamsUseCase: false,\n getTeamUseCase: false,\n createTeamUseCase: false,\n updateTeamUseCase: false,\n deleteTeamUseCase: false,\n cache: false,\n stringFormatter: false,\n vm: computed\n });\n }\n\n get vm(): ITeamsPresenterViewModel {\n const team = this._selectedTeam;\n const systemTeam = team !== null && team.system === true;\n const pluginTeam = team !== null && (team.plugin ?? false);\n\n return {\n selectedTeam: this._selectedTeam,\n loading: this._loading,\n saving: this._saving,\n showForm: this._showForm,\n canModify: !systemTeam && !pluginTeam,\n form: this._form.vm\n };\n }\n\n get list(): ListPresenter.Interface<Team> {\n return this._listPresenter;\n }\n\n init(): void {\n const dataSource = new TeamsDataSource(this.listTeamsUseCase, this.cache);\n\n this._listPresenter.init({\n dataSource,\n initialSort: { field: \"createdOn\", direction: \"DESC\" },\n limit: 1000\n });\n }\n\n async selectTeam(id: string): Promise<void> {\n runInAction(() => {\n this._loading = true;\n this._showForm = true;\n this._isNew = false;\n });\n\n try {\n const team = await this.getTeamUseCase.execute(id);\n const systemTeam = team.system === true;\n const pluginTeam = team.plugin ?? false;\n const canModify = !systemTeam && !pluginTeam;\n\n runInAction(() => {\n this._selectedTeam = team;\n this._form = this.buildForm(false, canModify);\n this._form.setData({\n name: team.name,\n slug: team.slug,\n description: team.description ?? \"\",\n roles: team.roles || []\n });\n });\n } finally {\n runInAction(() => {\n this._loading = false;\n });\n }\n }\n\n createNew(): void {\n this._selectedTeam = null;\n this._isNew = true;\n this._form = this.buildForm(true, true);\n this._showForm = true;\n }\n\n deselect(): void {\n this._selectedTeam = null;\n this._showForm = false;\n }\n\n async save(): Promise<Team | null> {\n const data = await this._form.submit();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this._saving = true;\n });\n\n try {\n const roles = ((data.roles as any[]) || []).map((r: any) =>\n typeof r === \"string\" ? r : r.id\n );\n const isUpdate = this._selectedTeam !== null && this._selectedTeam.createdOn;\n\n if (isUpdate) {\n const team = await this.updateTeamUseCase.execute(this._selectedTeam!.id, {\n name: data.name as string,\n description: data.description as string,\n roles\n });\n runInAction(() => {\n this._selectedTeam = team;\n });\n return team;\n } else {\n const team = await this.createTeamUseCase.execute({\n name: data.name as string,\n slug: data.slug as string,\n description: data.description as string,\n roles\n });\n runInAction(() => {\n this._selectedTeam = team;\n this._isNew = false;\n this._form = this.buildForm(false, true);\n this._form.setData({\n name: team.name,\n slug: team.slug,\n description: team.description ?? \"\",\n roles: team.roles || []\n });\n });\n return team;\n }\n // Errors deliberately propagate to the caller, which reports them to the user. This\n // used to be a bare `catch { return null }`, and `null` is also what `save()` returns\n // when client-side validation fails - so a rejected request looked to the view exactly\n // like a form that had not been submitted, and failed silently.\n } finally {\n runInAction(() => {\n this._saving = false;\n });\n }\n }\n\n async deleteTeam(id: string): Promise<void> {\n await this.deleteTeamUseCase.execute(id);\n\n runInAction(() => {\n if (this._selectedTeam !== null && this._selectedTeam.id === id) {\n this._selectedTeam = null;\n this._showForm = false;\n }\n });\n }\n\n private buildForm(isNew: boolean, canModify: boolean): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields\n .text()\n .label(\"Name\")\n .required(\"Name is required.\")\n .disabled(!canModify)\n .onBlur((value, { form }) => {\n const slugValue = form.field(\"slug\").getValue();\n if (slugValue || !value) {\n return;\n }\n form.field(\"slug\").setValue(this.stringFormatter.slugify(String(value)));\n }),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required.\")\n .disabled(!isNew || !canModify),\n description: fields\n .text()\n .label(\"Description\")\n .renderer(\"textarea\")\n .defaultValue(\"\")\n .schema(\n z.string().max(500, \"Description cannot be longer than 500 characters.\")\n )\n .disabled(!canModify),\n roles: fields\n .rolesMultiSelect()\n .label(\"Roles\")\n .required(\"Roles are required.\")\n .disabled(!canModify)\n }),\n layout: layout => [\n layout.row(\"name\", \"slug\"),\n layout.row(\"description\"),\n layout.row(\"roles\")\n ]\n });\n }\n}\n\nexport const TeamsPresenter = Abstraction.createImplementation({\n implementation: TeamsPresenterImpl,\n dependencies: [\n ListPresenter,\n FormModelFactory,\n ListTeamsUseCase,\n GetTeamUseCase,\n CreateTeamUseCase,\n UpdateTeamUseCase,\n DeleteTeamUseCase,\n TeamsListCache,\n StringFormatter\n ]\n});\n"],"names":["TeamsPresenterImpl","_listPresenter","formModelFactory","listTeamsUseCase","getTeamUseCase","createTeamUseCase","updateTeamUseCase","deleteTeamUseCase","cache","stringFormatter","makeAutoObservable","computed","team","systemTeam","pluginTeam","dataSource","TeamsDataSource","id","runInAction","canModify","data","roles","r","isUpdate","isNew","fields","value","form","slugValue","String","z","layout","TeamsPresenter","Abstraction","ListPresenter","FormModelFactory","ListTeamsUseCase","GetTeamUseCase","CreateTeamUseCase","UpdateTeamUseCase","DeleteTeamUseCase","TeamsListCache","StringFormatter"],"mappings":"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"}
|
|
@@ -147,12 +147,16 @@ const TeamsForm = observer(({ newEntry, id })=>{
|
|
|
147
147
|
newEntry
|
|
148
148
|
]);
|
|
149
149
|
const handleSave = useCallback(async ()=>{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
id
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
try {
|
|
151
|
+
const team = await presenter.save();
|
|
152
|
+
if (team) {
|
|
153
|
+
if (!vm.selectedTeam || vm.selectedTeam.id !== team.id) goToRoute(Routes.Teams.List, {
|
|
154
|
+
id: team.id
|
|
155
|
+
});
|
|
156
|
+
showSnackbar("Team saved successfully!");
|
|
157
|
+
}
|
|
158
|
+
} catch (e) {
|
|
159
|
+
showSnackbar(e.message);
|
|
156
160
|
}
|
|
157
161
|
}, [
|
|
158
162
|
presenter,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/accessManagement/teams/components/TeamsView.js","sources":["../../../../../src/presentation/accessManagement/teams/components/TeamsView.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport orderBy from \"lodash/orderBy.js\";\nimport { useFeature } from \"@webiny/app\";\nimport {\n SplitView,\n LeftPanel,\n RightPanel,\n SimpleForm,\n SimpleFormHeader,\n SimpleFormContent,\n SimpleFormFooter,\n EmptyView,\n useSnackbar,\n useConfirmationDialog,\n SearchUI,\n useRouter,\n useRoute\n} from \"~/index.js\";\nimport { FormView } from \"~/features/formModel/FormView.js\";\nimport {\n Alert,\n Button,\n DataList,\n DataListModal,\n DeleteIcon,\n Grid,\n List,\n OverlayLoader,\n Select,\n Tooltip\n} from \"@webiny/admin-ui\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport { TeamsPresenterFeature } from \"../feature.js\";\nimport { Routes } from \"../../routes.js\";\nimport type { Team } from \"~/features/accessManagement/types.js\";\nimport { FormErrors } from \"~/index.js\";\n\nconst SORTERS = [\n { label: \"Newest to oldest\", sorter: \"createdOn_DESC\" },\n { label: \"Oldest to newest\", sorter: \"createdOn_ASC\" },\n { label: \"Name A-Z\", sorter: \"name_ASC\" },\n { label: \"Name Z-A\", sorter: \"name_DESC\" }\n];\n\nconst deserializeSorters = (data: string): [string, \"asc\" | \"desc\"] => {\n const [field, order] = data.split(\"_\");\n return [field, order.toLowerCase() === \"asc\" ? \"asc\" : \"desc\"];\n};\n\nconst TeamsDataList = observer(({ activeId }: { activeId: string | undefined }) => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n const { showConfirmation } = useConfirmationDialog({\n dataTestId: \"default-data-list.delete-dialog\"\n });\n\n const [filter, setFilter] = useState(\"\");\n const [sort, setSort] = useState(SORTERS[0].sorter);\n\n const teams = presenter.list.vm.rows;\n const loading = presenter.list.vm.pagination.loading;\n\n const filteredData = useMemo(() => {\n if (filter === \"\") {\n return teams;\n }\n const lc = filter.toLowerCase();\n return teams.filter(\n (t: Team) =>\n t.name.toLowerCase().includes(lc) ||\n t.slug.toLowerCase().includes(lc) ||\n (t.description && t.description.toLowerCase().includes(lc))\n );\n }, [teams, filter]);\n\n const sortedData = useMemo(() => {\n if (!sort) {\n return filteredData;\n }\n const [key, order] = deserializeSorters(sort);\n return orderBy(filteredData, [key], [order]);\n }, [filteredData, sort]);\n\n const deleteItem = useCallback(\n (item: Team) => {\n showConfirmation(async () => {\n try {\n await presenter.deleteTeam(item.id);\n showSnackbar(`Team \"${item.slug}\" deleted.`);\n if (activeId === item.id) {\n goToRoute(Routes.Teams.List);\n }\n } catch (e: any) {\n showSnackbar(e.message);\n }\n });\n },\n [activeId]\n );\n\n return (\n <DataList\n title={\"Teams\"}\n refresh={null}\n actions={\n <Button\n text={\"New\"}\n icon={<AddIcon />}\n size={\"sm\"}\n className={\"ml-xs\"}\n data-testid=\"new-record-button\"\n onClick={() => goToRoute(Routes.Teams.List, { new: true })}\n />\n }\n data={sortedData}\n loading={loading}\n search={\n <SearchUI\n value={filter}\n onChange={setFilter}\n inputPlaceholder={\"Search teams...\"}\n />\n }\n modalOverlay={\n <DataListModal.Content>\n <Grid>\n <Grid.Column span={12}>\n <Select\n value={sort}\n onChange={setSort}\n label={\"Sort by\"}\n options={SORTERS.map(({ label, sorter: value }) => ({\n label,\n value\n }))}\n />\n </Grid.Column>\n </Grid>\n </DataListModal.Content>\n }\n modalOverlayAction={<DataListModal.Trigger data-testid={\"default-data-list.filter\"} />}\n >\n {({ data }: { data: Team[] }) => (\n <List data-testid=\"default-data-list\">\n {data.map(item => (\n <List.Item\n key={item.id}\n selected={item.id === activeId}\n title={item.name}\n description={item.description}\n onClick={() => goToRoute(Routes.Teams.List, { id: item.id })}\n actions={\n item.system || item.plugin ? (\n <Tooltip\n content={\n item.system\n ? \"Cannot delete system teams.\"\n : \"Cannot delete teams registered via extensions.\"\n }\n trigger={<DeleteIcon disabled />}\n />\n ) : (\n <DeleteIcon\n onClick={() => deleteItem(item)}\n data-testid={\"default-data-list.delete\"}\n />\n )\n }\n />\n ))}\n </List>\n )}\n </DataList>\n );\n});\n\nconst TeamsForm = observer(({ newEntry, id }: { newEntry: boolean; id: string | undefined }) => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n const { vm } = presenter;\n\n useEffect(() => {\n if (id) {\n presenter.selectTeam(id);\n } else if (newEntry) {\n presenter.createNew();\n } else {\n presenter.deselect();\n }\n }, [id, newEntry]);\n\n const handleSave = useCallback(async () => {\n const team = await presenter.save();\n if (team) {\n if (!vm.selectedTeam || vm.selectedTeam.id !== team.id) {\n goToRoute(Routes.Teams.List, { id: team.id });\n }\n showSnackbar(\"Team saved successfully!\");\n }\n }, [presenter, vm.selectedTeam]);\n\n if (!vm.showForm) {\n return (\n <EmptyView\n icon={<SettingsIcon />}\n title={\"Click on the left side list to display team details or create a...\"}\n action={\n <Button\n text={\"New Team\"}\n icon={<AddIcon />}\n data-testid=\"new-record-button\"\n onClick={() => goToRoute(Routes.Teams.List, { new: true })}\n />\n }\n />\n );\n }\n\n return (\n <SimpleForm>\n {vm.loading || vm.saving ? <OverlayLoader /> : null}\n <SimpleFormHeader\n title={vm.selectedTeam ? vm.selectedTeam.name || \"Untitled\" : \"Untitled\"}\n />\n <SimpleFormContent>\n {vm.selectedTeam && vm.selectedTeam.system ? (\n <Alert type={\"info\"} title={\"Permissions are locked\"}>\n This is a protected system team and you can't modify its permissions.\n </Alert>\n ) : null}\n {vm.selectedTeam && vm.selectedTeam.plugin ? (\n <Alert type={\"info\"} title={\"Important\"}>\n This team is registered via an extension, and cannot be modified.\n </Alert>\n ) : null}\n <FormErrors form={vm.form} className={\"mb-md\"} />\n <FormView name={\"Team\"} form={vm.form} />\n </SimpleFormContent>\n <SimpleFormFooter>\n <Button\n variant={\"secondary\"}\n text={\"Cancel\"}\n onClick={() => goToRoute(Routes.Teams.List)}\n />\n {vm.canModify ? (\n <Button\n text={\"Save\"}\n data-testid=\"admin.am.team.new.save\"\n onClick={handleSave}\n />\n ) : null}\n </SimpleFormFooter>\n </SimpleForm>\n );\n});\n\nexport const TeamsView = observer(() => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { route } = useRoute(Routes.Teams.List);\n\n useEffect(() => {\n presenter.init();\n }, [presenter]);\n\n return (\n <SplitView>\n <LeftPanel>\n <TeamsDataList activeId={route.params.id} />\n </LeftPanel>\n <RightPanel>\n <TeamsForm newEntry={route.params.new === true} id={route.params.id} />\n </RightPanel>\n </SplitView>\n );\n});\n"],"names":["SORTERS","deserializeSorters","data","field","order","TeamsDataList","observer","activeId","presenter","useFeature","TeamsPresenterFeature","goToRoute","useRouter","showSnackbar","useSnackbar","showConfirmation","useConfirmationDialog","filter","setFilter","useState","sort","setSort","teams","loading","filteredData","useMemo","lc","t","sortedData","key","orderBy","deleteItem","useCallback","item","Routes","e","DataList","Button","AddIcon","SearchUI","DataListModal","Grid","Select","label","value","List","Tooltip","DeleteIcon","TeamsForm","newEntry","id","vm","useEffect","handleSave","team","EmptyView","SettingsIcon","SimpleForm","OverlayLoader","SimpleFormHeader","SimpleFormContent","Alert","FormErrors","FormView","SimpleFormFooter","TeamsView","route","useRoute","SplitView","LeftPanel","RightPanel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"presentation/accessManagement/teams/components/TeamsView.js","sources":["../../../../../src/presentation/accessManagement/teams/components/TeamsView.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport orderBy from \"lodash/orderBy.js\";\nimport { useFeature } from \"@webiny/app\";\nimport {\n SplitView,\n LeftPanel,\n RightPanel,\n SimpleForm,\n SimpleFormHeader,\n SimpleFormContent,\n SimpleFormFooter,\n EmptyView,\n useSnackbar,\n useConfirmationDialog,\n SearchUI,\n useRouter,\n useRoute\n} from \"~/index.js\";\nimport { FormView } from \"~/features/formModel/FormView.js\";\nimport {\n Alert,\n Button,\n DataList,\n DataListModal,\n DeleteIcon,\n Grid,\n List,\n OverlayLoader,\n Select,\n Tooltip\n} from \"@webiny/admin-ui\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport { TeamsPresenterFeature } from \"../feature.js\";\nimport { Routes } from \"../../routes.js\";\nimport type { Team } from \"~/features/accessManagement/types.js\";\nimport { FormErrors } from \"~/index.js\";\n\nconst SORTERS = [\n { label: \"Newest to oldest\", sorter: \"createdOn_DESC\" },\n { label: \"Oldest to newest\", sorter: \"createdOn_ASC\" },\n { label: \"Name A-Z\", sorter: \"name_ASC\" },\n { label: \"Name Z-A\", sorter: \"name_DESC\" }\n];\n\nconst deserializeSorters = (data: string): [string, \"asc\" | \"desc\"] => {\n const [field, order] = data.split(\"_\");\n return [field, order.toLowerCase() === \"asc\" ? \"asc\" : \"desc\"];\n};\n\nconst TeamsDataList = observer(({ activeId }: { activeId: string | undefined }) => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n const { showConfirmation } = useConfirmationDialog({\n dataTestId: \"default-data-list.delete-dialog\"\n });\n\n const [filter, setFilter] = useState(\"\");\n const [sort, setSort] = useState(SORTERS[0].sorter);\n\n const teams = presenter.list.vm.rows;\n const loading = presenter.list.vm.pagination.loading;\n\n const filteredData = useMemo(() => {\n if (filter === \"\") {\n return teams;\n }\n const lc = filter.toLowerCase();\n return teams.filter(\n (t: Team) =>\n t.name.toLowerCase().includes(lc) ||\n t.slug.toLowerCase().includes(lc) ||\n (t.description && t.description.toLowerCase().includes(lc))\n );\n }, [teams, filter]);\n\n const sortedData = useMemo(() => {\n if (!sort) {\n return filteredData;\n }\n const [key, order] = deserializeSorters(sort);\n return orderBy(filteredData, [key], [order]);\n }, [filteredData, sort]);\n\n const deleteItem = useCallback(\n (item: Team) => {\n showConfirmation(async () => {\n try {\n await presenter.deleteTeam(item.id);\n showSnackbar(`Team \"${item.slug}\" deleted.`);\n if (activeId === item.id) {\n goToRoute(Routes.Teams.List);\n }\n } catch (e: any) {\n showSnackbar(e.message);\n }\n });\n },\n [activeId]\n );\n\n return (\n <DataList\n title={\"Teams\"}\n refresh={null}\n actions={\n <Button\n text={\"New\"}\n icon={<AddIcon />}\n size={\"sm\"}\n className={\"ml-xs\"}\n data-testid=\"new-record-button\"\n onClick={() => goToRoute(Routes.Teams.List, { new: true })}\n />\n }\n data={sortedData}\n loading={loading}\n search={\n <SearchUI\n value={filter}\n onChange={setFilter}\n inputPlaceholder={\"Search teams...\"}\n />\n }\n modalOverlay={\n <DataListModal.Content>\n <Grid>\n <Grid.Column span={12}>\n <Select\n value={sort}\n onChange={setSort}\n label={\"Sort by\"}\n options={SORTERS.map(({ label, sorter: value }) => ({\n label,\n value\n }))}\n />\n </Grid.Column>\n </Grid>\n </DataListModal.Content>\n }\n modalOverlayAction={<DataListModal.Trigger data-testid={\"default-data-list.filter\"} />}\n >\n {({ data }: { data: Team[] }) => (\n <List data-testid=\"default-data-list\">\n {data.map(item => (\n <List.Item\n key={item.id}\n selected={item.id === activeId}\n title={item.name}\n description={item.description}\n onClick={() => goToRoute(Routes.Teams.List, { id: item.id })}\n actions={\n item.system || item.plugin ? (\n <Tooltip\n content={\n item.system\n ? \"Cannot delete system teams.\"\n : \"Cannot delete teams registered via extensions.\"\n }\n trigger={<DeleteIcon disabled />}\n />\n ) : (\n <DeleteIcon\n onClick={() => deleteItem(item)}\n data-testid={\"default-data-list.delete\"}\n />\n )\n }\n />\n ))}\n </List>\n )}\n </DataList>\n );\n});\n\nconst TeamsForm = observer(({ newEntry, id }: { newEntry: boolean; id: string | undefined }) => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n const { vm } = presenter;\n\n useEffect(() => {\n if (id) {\n presenter.selectTeam(id);\n } else if (newEntry) {\n presenter.createNew();\n } else {\n presenter.deselect();\n }\n }, [id, newEntry]);\n\n const handleSave = useCallback(async () => {\n try {\n const team = await presenter.save();\n if (team) {\n if (!vm.selectedTeam || vm.selectedTeam.id !== team.id) {\n goToRoute(Routes.Teams.List, { id: team.id });\n }\n showSnackbar(\"Team saved successfully!\");\n }\n } catch (e: any) {\n showSnackbar(e.message);\n }\n }, [presenter, vm.selectedTeam]);\n\n if (!vm.showForm) {\n return (\n <EmptyView\n icon={<SettingsIcon />}\n title={\"Click on the left side list to display team details or create a...\"}\n action={\n <Button\n text={\"New Team\"}\n icon={<AddIcon />}\n data-testid=\"new-record-button\"\n onClick={() => goToRoute(Routes.Teams.List, { new: true })}\n />\n }\n />\n );\n }\n\n return (\n <SimpleForm>\n {vm.loading || vm.saving ? <OverlayLoader /> : null}\n <SimpleFormHeader\n title={vm.selectedTeam ? vm.selectedTeam.name || \"Untitled\" : \"Untitled\"}\n />\n <SimpleFormContent>\n {vm.selectedTeam && vm.selectedTeam.system ? (\n <Alert type={\"info\"} title={\"Permissions are locked\"}>\n This is a protected system team and you can't modify its permissions.\n </Alert>\n ) : null}\n {vm.selectedTeam && vm.selectedTeam.plugin ? (\n <Alert type={\"info\"} title={\"Important\"}>\n This team is registered via an extension, and cannot be modified.\n </Alert>\n ) : null}\n <FormErrors form={vm.form} className={\"mb-md\"} />\n <FormView name={\"Team\"} form={vm.form} />\n </SimpleFormContent>\n <SimpleFormFooter>\n <Button\n variant={\"secondary\"}\n text={\"Cancel\"}\n onClick={() => goToRoute(Routes.Teams.List)}\n />\n {vm.canModify ? (\n <Button\n text={\"Save\"}\n data-testid=\"admin.am.team.new.save\"\n onClick={handleSave}\n />\n ) : null}\n </SimpleFormFooter>\n </SimpleForm>\n );\n});\n\nexport const TeamsView = observer(() => {\n const { presenter } = useFeature(TeamsPresenterFeature);\n const { route } = useRoute(Routes.Teams.List);\n\n useEffect(() => {\n presenter.init();\n }, [presenter]);\n\n return (\n <SplitView>\n <LeftPanel>\n <TeamsDataList activeId={route.params.id} />\n </LeftPanel>\n <RightPanel>\n <TeamsForm newEntry={route.params.new === true} id={route.params.id} />\n </RightPanel>\n </SplitView>\n );\n});\n"],"names":["SORTERS","deserializeSorters","data","field","order","TeamsDataList","observer","activeId","presenter","useFeature","TeamsPresenterFeature","goToRoute","useRouter","showSnackbar","useSnackbar","showConfirmation","useConfirmationDialog","filter","setFilter","useState","sort","setSort","teams","loading","filteredData","useMemo","lc","t","sortedData","key","orderBy","deleteItem","useCallback","item","Routes","e","DataList","Button","AddIcon","SearchUI","DataListModal","Grid","Select","label","value","List","Tooltip","DeleteIcon","TeamsForm","newEntry","id","vm","useEffect","handleSave","team","EmptyView","SettingsIcon","SimpleForm","OverlayLoader","SimpleFormHeader","SimpleFormContent","Alert","FormErrors","FormView","SimpleFormFooter","TeamsView","route","useRoute","SplitView","LeftPanel","RightPanel"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Command, CommandPalettePresenter as Abstraction, type CommandPaletteViewModel } from "./abstractions.js";
|
|
2
|
+
export declare class CommandPalettePresenter implements Abstraction.Interface {
|
|
3
|
+
private getCommands;
|
|
4
|
+
private isOpen;
|
|
5
|
+
private activeCommandName;
|
|
6
|
+
private aiModeActive;
|
|
7
|
+
private query;
|
|
8
|
+
private resolvedCommands;
|
|
9
|
+
constructor(getCommands: () => Command.Interface[]);
|
|
10
|
+
init(): void;
|
|
11
|
+
get shortcutKeys(): Record<string, (e: KeyboardEvent) => void>;
|
|
12
|
+
get vm(): CommandPaletteViewModel;
|
|
13
|
+
open(): void;
|
|
14
|
+
close(): void;
|
|
15
|
+
enterAiMode(): void;
|
|
16
|
+
exitAiMode(): void;
|
|
17
|
+
setQuery(query: string): void;
|
|
18
|
+
toggle(): void;
|
|
19
|
+
useCommand(name: string): void;
|
|
20
|
+
cancelCommand(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { makeAutoObservable } from "mobx";
|
|
2
|
+
class CommandPalettePresenter {
|
|
3
|
+
constructor(getCommands){
|
|
4
|
+
this.getCommands = getCommands;
|
|
5
|
+
this.isOpen = false;
|
|
6
|
+
this.activeCommandName = null;
|
|
7
|
+
this.aiModeActive = false;
|
|
8
|
+
this.query = "";
|
|
9
|
+
this.resolvedCommands = [];
|
|
10
|
+
makeAutoObservable(this);
|
|
11
|
+
}
|
|
12
|
+
init() {
|
|
13
|
+
this.resolvedCommands = this.getCommands();
|
|
14
|
+
}
|
|
15
|
+
get shortcutKeys() {
|
|
16
|
+
const keys = {};
|
|
17
|
+
for (const cmd of this.resolvedCommands)if (cmd.shortcut) keys[cmd.shortcut] = (e)=>{
|
|
18
|
+
e.preventDefault();
|
|
19
|
+
this.useCommand(cmd.name);
|
|
20
|
+
};
|
|
21
|
+
return keys;
|
|
22
|
+
}
|
|
23
|
+
get vm() {
|
|
24
|
+
const activeCmd = null !== this.activeCommandName ? this.resolvedCommands.find((c)=>c.name === this.activeCommandName) : null;
|
|
25
|
+
return {
|
|
26
|
+
isOpen: this.isOpen,
|
|
27
|
+
aiModeActive: this.aiModeActive,
|
|
28
|
+
query: this.query,
|
|
29
|
+
commands: this.resolvedCommands.map((cmd)=>({
|
|
30
|
+
name: cmd.name,
|
|
31
|
+
label: cmd.label,
|
|
32
|
+
description: cmd.description,
|
|
33
|
+
icon: cmd.icon,
|
|
34
|
+
category: cmd.category,
|
|
35
|
+
keywords: cmd.keywords,
|
|
36
|
+
shortcut: cmd.shortcut,
|
|
37
|
+
hasDetailView: Boolean(cmd.detailView)
|
|
38
|
+
})),
|
|
39
|
+
activeCommand: activeCmd && activeCmd.detailView ? {
|
|
40
|
+
command: activeCmd,
|
|
41
|
+
DetailView: activeCmd.detailView
|
|
42
|
+
} : null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
open() {
|
|
46
|
+
this.resolvedCommands = this.getCommands();
|
|
47
|
+
this.activeCommandName = null;
|
|
48
|
+
this.aiModeActive = false;
|
|
49
|
+
this.query = "";
|
|
50
|
+
this.isOpen = true;
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
this.isOpen = false;
|
|
54
|
+
this.activeCommandName = null;
|
|
55
|
+
this.aiModeActive = false;
|
|
56
|
+
this.query = "";
|
|
57
|
+
}
|
|
58
|
+
enterAiMode() {
|
|
59
|
+
this.aiModeActive = true;
|
|
60
|
+
this.query = "";
|
|
61
|
+
}
|
|
62
|
+
exitAiMode() {
|
|
63
|
+
this.aiModeActive = false;
|
|
64
|
+
this.query = "";
|
|
65
|
+
}
|
|
66
|
+
setQuery(query) {
|
|
67
|
+
this.query = query;
|
|
68
|
+
}
|
|
69
|
+
toggle() {
|
|
70
|
+
if (this.isOpen) this.close();
|
|
71
|
+
else this.open();
|
|
72
|
+
}
|
|
73
|
+
useCommand(name) {
|
|
74
|
+
const cmd = this.resolvedCommands.find((c)=>c.name === name);
|
|
75
|
+
if (!cmd) return;
|
|
76
|
+
if (cmd.entersAiMode) return void this.enterAiMode();
|
|
77
|
+
if (cmd.detailView) {
|
|
78
|
+
this.activeCommandName = name;
|
|
79
|
+
this.isOpen = true;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
cmd.execute?.();
|
|
83
|
+
this.close();
|
|
84
|
+
}
|
|
85
|
+
cancelCommand() {
|
|
86
|
+
this.activeCommandName = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export { CommandPalettePresenter };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=CommandPalettePresenter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/commandPalette/CommandPalettePresenter.js","sources":["../../../src/presentation/commandPalette/CommandPalettePresenter.ts"],"sourcesContent":["import { makeAutoObservable } from \"mobx\";\nimport {\n Command,\n CommandPalettePresenter as Abstraction,\n type CommandPaletteViewModel\n} from \"./abstractions.js\";\n\nexport class CommandPalettePresenter implements Abstraction.Interface {\n private isOpen = false;\n private activeCommandName: string | null = null;\n private aiModeActive = false;\n private query = \"\";\n private resolvedCommands: Command.Interface[] = [];\n\n constructor(private getCommands: () => Command.Interface[]) {\n makeAutoObservable(this);\n }\n\n init(): void {\n this.resolvedCommands = this.getCommands();\n }\n\n get shortcutKeys(): Record<string, (e: KeyboardEvent) => void> {\n const keys: Record<string, (e: KeyboardEvent) => void> = {};\n for (const cmd of this.resolvedCommands) {\n if (cmd.shortcut) {\n keys[cmd.shortcut] = (e: KeyboardEvent) => {\n e.preventDefault();\n this.useCommand(cmd.name);\n };\n }\n }\n return keys;\n }\n\n get vm(): CommandPaletteViewModel {\n const activeCmd =\n this.activeCommandName !== null\n ? this.resolvedCommands.find(c => c.name === this.activeCommandName)\n : null;\n\n return {\n isOpen: this.isOpen,\n aiModeActive: this.aiModeActive,\n query: this.query,\n commands: this.resolvedCommands.map(cmd => ({\n name: cmd.name,\n label: cmd.label,\n description: cmd.description,\n icon: cmd.icon,\n category: cmd.category,\n keywords: cmd.keywords,\n shortcut: cmd.shortcut,\n hasDetailView: Boolean(cmd.detailView)\n })),\n activeCommand:\n activeCmd && activeCmd.detailView\n ? {\n command: activeCmd,\n DetailView: activeCmd.detailView\n }\n : null\n };\n }\n\n open(): void {\n this.resolvedCommands = this.getCommands();\n this.activeCommandName = null;\n this.aiModeActive = false;\n this.query = \"\";\n this.isOpen = true;\n }\n\n close(): void {\n this.isOpen = false;\n this.activeCommandName = null;\n this.aiModeActive = false;\n this.query = \"\";\n }\n\n enterAiMode(): void {\n this.aiModeActive = true;\n this.query = \"\";\n }\n\n exitAiMode(): void {\n this.aiModeActive = false;\n this.query = \"\";\n }\n\n setQuery(query: string): void {\n this.query = query;\n }\n\n toggle(): void {\n if (this.isOpen) {\n this.close();\n } else {\n this.open();\n }\n }\n\n useCommand(name: string): void {\n const cmd = this.resolvedCommands.find(c => c.name === name);\n if (!cmd) {\n return;\n }\n\n if (cmd.entersAiMode) {\n // A mode replaces the command list and keeps the input row, so the palette stays open.\n this.enterAiMode();\n return;\n }\n\n if (cmd.detailView) {\n this.activeCommandName = name;\n this.isOpen = true;\n return;\n }\n\n cmd.execute?.();\n this.close();\n }\n\n cancelCommand(): void {\n this.activeCommandName = null;\n }\n}\n"],"names":["CommandPalettePresenter","getCommands","makeAutoObservable","keys","cmd","e","activeCmd","c","Boolean","query","name"],"mappings":";AAOO,MAAMA;IAOT,YAAoBC,WAAsC,CAAE;aAAxCA,WAAW,GAAXA;aANZ,MAAM,GAAG;aACT,iBAAiB,GAAkB;aACnC,YAAY,GAAG;aACf,KAAK,GAAG;aACR,gBAAgB,GAAwB,EAAE;QAG9CC,mBAAmB,IAAI;IAC3B;IAEA,OAAa;QACT,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,WAAW;IAC5C;IAEA,IAAI,eAA2D;QAC3D,MAAMC,OAAmD,CAAC;QAC1D,KAAK,MAAMC,OAAO,IAAI,CAAC,gBAAgB,CACnC,IAAIA,IAAI,QAAQ,EACZD,IAAI,CAACC,IAAI,QAAQ,CAAC,GAAG,CAACC;YAClBA,EAAE,cAAc;YAChB,IAAI,CAAC,UAAU,CAACD,IAAI,IAAI;QAC5B;QAGR,OAAOD;IACX;IAEA,IAAI,KAA8B;QAC9B,MAAMG,YACF,AAA2B,SAA3B,IAAI,CAAC,iBAAiB,GAChB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAACC,CAAAA,IAAKA,EAAE,IAAI,KAAK,IAAI,CAAC,iBAAiB,IACjE;QAEV,OAAO;YACH,QAAQ,IAAI,CAAC,MAAM;YACnB,cAAc,IAAI,CAAC,YAAY;YAC/B,OAAO,IAAI,CAAC,KAAK;YACjB,UAAU,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACH,CAAAA,MAAQ;oBACxC,MAAMA,IAAI,IAAI;oBACd,OAAOA,IAAI,KAAK;oBAChB,aAAaA,IAAI,WAAW;oBAC5B,MAAMA,IAAI,IAAI;oBACd,UAAUA,IAAI,QAAQ;oBACtB,UAAUA,IAAI,QAAQ;oBACtB,UAAUA,IAAI,QAAQ;oBACtB,eAAeI,QAAQJ,IAAI,UAAU;gBACzC;YACA,eACIE,aAAaA,UAAU,UAAU,GAC3B;gBACI,SAASA;gBACT,YAAYA,UAAU,UAAU;YACpC,IACA;QACd;IACJ;IAEA,OAAa;QACT,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,WAAW;QACxC,IAAI,CAAC,iBAAiB,GAAG;QACzB,IAAI,CAAC,YAAY,GAAG;QACpB,IAAI,CAAC,KAAK,GAAG;QACb,IAAI,CAAC,MAAM,GAAG;IAClB;IAEA,QAAc;QACV,IAAI,CAAC,MAAM,GAAG;QACd,IAAI,CAAC,iBAAiB,GAAG;QACzB,IAAI,CAAC,YAAY,GAAG;QACpB,IAAI,CAAC,KAAK,GAAG;IACjB;IAEA,cAAoB;QAChB,IAAI,CAAC,YAAY,GAAG;QACpB,IAAI,CAAC,KAAK,GAAG;IACjB;IAEA,aAAmB;QACf,IAAI,CAAC,YAAY,GAAG;QACpB,IAAI,CAAC,KAAK,GAAG;IACjB;IAEA,SAASG,KAAa,EAAQ;QAC1B,IAAI,CAAC,KAAK,GAAGA;IACjB;IAEA,SAAe;QACX,IAAI,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,KAAK;aAEV,IAAI,CAAC,IAAI;IAEjB;IAEA,WAAWC,IAAY,EAAQ;QAC3B,MAAMN,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAACG,CAAAA,IAAKA,EAAE,IAAI,KAAKG;QACvD,IAAI,CAACN,KACD;QAGJ,IAAIA,IAAI,YAAY,EAAE,YAElB,IAAI,CAAC,WAAW;QAIpB,IAAIA,IAAI,UAAU,EAAE;YAChB,IAAI,CAAC,iBAAiB,GAAGM;YACzB,IAAI,CAAC,MAAM,GAAG;YACd;QACJ;QAEAN,IAAI,OAAO;QACX,IAAI,CAAC,KAAK;IACd;IAEA,gBAAsB;QAClB,IAAI,CAAC,iBAAiB,GAAG;IAC7B;AACJ"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import { Abstraction } from "@webiny/di";
|
|
3
|
+
export interface CommandDetailProps {
|
|
4
|
+
command: ICommand;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onBack: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A command registered with the command palette via dependency injection. Register an
|
|
10
|
+
* implementation with `Command.createImplementation(...)` and add it to the container;
|
|
11
|
+
* the palette resolves all of them with `container.resolveAll(Command)`.
|
|
12
|
+
*/
|
|
13
|
+
export interface ICommand {
|
|
14
|
+
name: string;
|
|
15
|
+
label: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
icon?: React.ReactNode;
|
|
18
|
+
category?: string;
|
|
19
|
+
keywords?: string[];
|
|
20
|
+
shortcut?: string;
|
|
21
|
+
execute?(params?: unknown): void | Promise<void>;
|
|
22
|
+
detailView?: React.ComponentType<CommandDetailProps>;
|
|
23
|
+
entersAiMode?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const Command: Abstraction<ICommand>;
|
|
26
|
+
export declare namespace Command {
|
|
27
|
+
type Interface = ICommand;
|
|
28
|
+
type DetailProps = CommandDetailProps;
|
|
29
|
+
}
|
|
30
|
+
export interface CommandItemVm {
|
|
31
|
+
name: string;
|
|
32
|
+
label: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
icon?: React.ReactNode;
|
|
35
|
+
category?: string;
|
|
36
|
+
keywords?: string[];
|
|
37
|
+
shortcut?: string;
|
|
38
|
+
hasDetailView: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface ActiveCommandVm {
|
|
41
|
+
command: ICommand;
|
|
42
|
+
DetailView: React.ComponentType<CommandDetailProps>;
|
|
43
|
+
}
|
|
44
|
+
export interface CommandPaletteViewModel {
|
|
45
|
+
isOpen: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* A mode is showing instead of the command list. The palette keeps ONE input row across every
|
|
48
|
+
* mode, so this is the palette's state rather than the mode's.
|
|
49
|
+
*/
|
|
50
|
+
aiModeActive: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* What the user has typed. Owned here rather than by the component because it is cleared
|
|
53
|
+
* whenever the palette opens, closes, or enters or leaves a mode.
|
|
54
|
+
*/
|
|
55
|
+
query: string;
|
|
56
|
+
commands: CommandItemVm[];
|
|
57
|
+
activeCommand: ActiveCommandVm | null;
|
|
58
|
+
}
|
|
59
|
+
export interface ICommandPalettePresenter {
|
|
60
|
+
vm: CommandPaletteViewModel;
|
|
61
|
+
shortcutKeys: Record<string, (e: KeyboardEvent) => void>;
|
|
62
|
+
init(): void;
|
|
63
|
+
open(): void;
|
|
64
|
+
close(): void;
|
|
65
|
+
toggle(): void;
|
|
66
|
+
useCommand(name: string): void;
|
|
67
|
+
cancelCommand(): void;
|
|
68
|
+
enterAiMode(): void;
|
|
69
|
+
exitAiMode(): void;
|
|
70
|
+
setQuery(query: string): void;
|
|
71
|
+
}
|
|
72
|
+
export declare const CommandPalettePresenter: Abstraction<ICommandPalettePresenter>;
|
|
73
|
+
export declare namespace CommandPalettePresenter {
|
|
74
|
+
type Interface = ICommandPalettePresenter;
|
|
75
|
+
type ViewModel = CommandPaletteViewModel;
|
|
76
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createAbstraction } from "@webiny/feature/admin";
|
|
2
|
+
import { Abstraction } from "@webiny/di";
|
|
3
|
+
const Command = createAbstraction("Command");
|
|
4
|
+
const CommandPalettePresenter = new Abstraction("CommandPalettePresenter");
|
|
5
|
+
export { Command, CommandPalettePresenter };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=abstractions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/commandPalette/abstractions.js","sources":["../../../src/presentation/commandPalette/abstractions.ts"],"sourcesContent":["import type React from \"react\";\nimport { createAbstraction } from \"@webiny/feature/admin\";\nimport { Abstraction } from \"@webiny/di\";\n\nexport interface CommandDetailProps {\n command: ICommand;\n onClose: () => void;\n onBack: () => void;\n}\n\n/**\n * A command registered with the command palette via dependency injection. Register an\n * implementation with `Command.createImplementation(...)` and add it to the container;\n * the palette resolves all of them with `container.resolveAll(Command)`.\n */\nexport interface ICommand {\n name: string;\n label: string;\n description?: string;\n icon?: React.ReactNode;\n category?: string;\n keywords?: string[];\n /* Global hotkey (is-hotkey syntax, e.g. \"cmd+shift+m\") that runs this command. */\n shortcut?: string;\n /* Omitted by a command that only selects a mode; there is no action to run. */\n execute?(params?: unknown): void | Promise<void>;\n /* Optional React view rendered inside the palette when the command is selected. */\n detailView?: React.ComponentType<CommandDetailProps>;\n /*\n * Selecting this command switches the palette into AI mode rather than doing something. A mode\n * needs the shared input row, so the palette stays open and `execute` is never called.\n *\n * Named after the one mode that exists. If a second one ever arrives, this becomes\n * `entersMode: \"aiChat\"` and the palette looks the mode up by name instead of hardcoding it.\n */\n entersAiMode?: boolean;\n}\n\nexport const Command = createAbstraction<ICommand>(\"Command\");\n\nexport namespace Command {\n export type Interface = ICommand;\n export type DetailProps = CommandDetailProps;\n}\n\nexport interface CommandItemVm {\n name: string;\n label: string;\n description?: string;\n icon?: React.ReactNode;\n category?: string;\n keywords?: string[];\n shortcut?: string;\n hasDetailView: boolean;\n}\n\nexport interface ActiveCommandVm {\n command: ICommand;\n DetailView: React.ComponentType<CommandDetailProps>;\n}\n\nexport interface CommandPaletteViewModel {\n isOpen: boolean;\n /**\n * A mode is showing instead of the command list. The palette keeps ONE input row across every\n * mode, so this is the palette's state rather than the mode's.\n */\n aiModeActive: boolean;\n /**\n * What the user has typed. Owned here rather than by the component because it is cleared\n * whenever the palette opens, closes, or enters or leaves a mode.\n */\n query: string;\n commands: CommandItemVm[];\n activeCommand: ActiveCommandVm | null;\n}\n\nexport interface ICommandPalettePresenter {\n vm: CommandPaletteViewModel;\n shortcutKeys: Record<string, (e: KeyboardEvent) => void>;\n init(): void;\n open(): void;\n close(): void;\n toggle(): void;\n useCommand(name: string): void;\n cancelCommand(): void;\n enterAiMode(): void;\n exitAiMode(): void;\n setQuery(query: string): void;\n}\n\nexport const CommandPalettePresenter = new Abstraction<ICommandPalettePresenter>(\n \"CommandPalettePresenter\"\n);\n\nexport namespace CommandPalettePresenter {\n export type Interface = ICommandPalettePresenter;\n export type ViewModel = CommandPaletteViewModel;\n}\n"],"names":["Command","createAbstraction","CommandPalettePresenter","Abstraction"],"mappings":";;AAsCO,MAAMA,UAAUC,kBAA4B;AAqD5C,MAAMC,0BAA0B,IAAIC,YACvC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Command } from "../abstractions.js";
|
|
3
|
+
/**
|
|
4
|
+
* Discoverable entry point for the palette's AI mode.
|
|
5
|
+
*
|
|
6
|
+
* `entersAiMode` rather than `execute`: the design keeps one input row across every mode, so selecting
|
|
7
|
+
* this switches the palette instead of running an action, and the palette stays open. A command
|
|
8
|
+
* without a `detailView` is otherwise executed and then closed, which a mode cannot survive.
|
|
9
|
+
*
|
|
10
|
+
* It exists as a command at all so it stays searchable ("ai", "ask", "assistant") for people who
|
|
11
|
+
* never learn the space shortcut.
|
|
12
|
+
*/
|
|
13
|
+
declare class AskAiCommandImpl implements Command.Interface {
|
|
14
|
+
name: string;
|
|
15
|
+
label: string;
|
|
16
|
+
description: string;
|
|
17
|
+
category: string;
|
|
18
|
+
keywords: string[];
|
|
19
|
+
icon: React.JSX.Element;
|
|
20
|
+
entersAiMode: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const AskAiCommand: typeof AskAiCommandImpl & {
|
|
23
|
+
__abstraction: import("@webiny/di").Abstraction<import("../abstractions.js").ICommand>;
|
|
24
|
+
};
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { Icon } from "@webiny/admin-ui";
|
|
3
|
+
import { ReactComponent } from "@webiny/icons/auto_awesome.svg";
|
|
4
|
+
import { Command } from "../abstractions.js";
|
|
5
|
+
class AskAiCommandImpl {
|
|
6
|
+
constructor(){
|
|
7
|
+
this.name = "admin.ai.ask";
|
|
8
|
+
this.label = "Ask AI";
|
|
9
|
+
this.description = "Ask about your content in plain language";
|
|
10
|
+
this.category = "Assistant";
|
|
11
|
+
this.keywords = [
|
|
12
|
+
"ai",
|
|
13
|
+
"ask",
|
|
14
|
+
"assistant",
|
|
15
|
+
"chat",
|
|
16
|
+
"search"
|
|
17
|
+
];
|
|
18
|
+
this.icon = /*#__PURE__*/ react.createElement(Icon, {
|
|
19
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
20
|
+
size: "sm",
|
|
21
|
+
color: "neutral-strong",
|
|
22
|
+
label: ""
|
|
23
|
+
});
|
|
24
|
+
this.entersAiMode = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const AskAiCommand = Command.createImplementation({
|
|
28
|
+
implementation: AskAiCommandImpl,
|
|
29
|
+
dependencies: []
|
|
30
|
+
});
|
|
31
|
+
export { AskAiCommand };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=AskAiCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/commandPalette/commands/AskAiCommand.js","sources":["../../../../src/presentation/commandPalette/commands/AskAiCommand.tsx"],"sourcesContent":["import React from \"react\";\nimport { Icon } from \"@webiny/admin-ui\";\nimport { ReactComponent as AiIcon } from \"@webiny/icons/auto_awesome.svg\";\nimport { Command } from \"../abstractions.js\";\n\n/**\n * Discoverable entry point for the palette's AI mode.\n *\n * `entersAiMode` rather than `execute`: the design keeps one input row across every mode, so selecting\n * this switches the palette instead of running an action, and the palette stays open. A command\n * without a `detailView` is otherwise executed and then closed, which a mode cannot survive.\n *\n * It exists as a command at all so it stays searchable (\"ai\", \"ask\", \"assistant\") for people who\n * never learn the space shortcut.\n */\nclass AskAiCommandImpl implements Command.Interface {\n name = \"admin.ai.ask\";\n label = \"Ask AI\";\n description = \"Ask about your content in plain language\";\n category = \"Assistant\";\n keywords = [\"ai\", \"ask\", \"assistant\", \"chat\", \"search\"];\n icon = <Icon icon={<AiIcon />} size=\"sm\" color=\"neutral-strong\" label=\"\" />;\n entersAiMode = true;\n}\n\nexport const AskAiCommand = Command.createImplementation({\n implementation: AskAiCommandImpl,\n dependencies: []\n});\n"],"names":["AskAiCommandImpl","Icon","AiIcon","AskAiCommand","Command"],"mappings":";;;;AAeA,MAAMA;;aACF,IAAI,GAAG;aACP,KAAK,GAAG;aACR,WAAW,GAAG;aACd,QAAQ,GAAG;aACX,QAAQ,GAAG;YAAC;YAAM;YAAO;YAAa;YAAQ;SAAS;aACvD,IAAI,GAAG,WAAP,GAAO,oBAACC,MAAIA;YAAC,oBAAM,oBAACC,gBAAMA;YAAK,MAAK;YAAK,OAAM;YAAiB,OAAM;;aACtE,YAAY,GAAG;;AACnB;AAEO,MAAMC,eAAeC,QAAQ,oBAAoB,CAAC;IACrD,gBAAgBJ;IAChB,cAAc,EAAE;AACpB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Command } from "../abstractions.js";
|
|
3
|
+
declare class CopyCurrentUrlCommandImpl implements Command.Interface {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description: string;
|
|
7
|
+
category: string;
|
|
8
|
+
keywords: string[];
|
|
9
|
+
icon: React.JSX.Element;
|
|
10
|
+
execute(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const CopyCurrentUrlCommand: typeof CopyCurrentUrlCommandImpl & {
|
|
13
|
+
__abstraction: import("@webiny/di").Abstraction<import("../abstractions.js").ICommand>;
|
|
14
|
+
};
|
|
15
|
+
export {};
|